@moatamed-sce/ui-components 0.1.1 → 0.1.2

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.
@@ -52,6 +52,7 @@ import { RadioButtonModule } from 'primeng/radiobutton';
52
52
  import * as i1$4 from 'primeng/drawer';
53
53
  import { DrawerModule } from 'primeng/drawer';
54
54
 
55
+ /** Radio group that renders each option as a selectable card with an optional icon and description; unlike the other sce field components it is a ControlValueAccessor, so it accepts `formControlName`. */
55
56
  class SceCardRadioGroupComponent {
56
57
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
57
58
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
@@ -113,6 +114,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
113
114
  ], template: "@if (label()) {\n <p class=\"sce-card-radio-group__label\">{{ label() }}</p>\n}\n\n<div class=\"sce-card-radio-group__grid\" role=\"radiogroup\" [attr.aria-label]=\"label() || null\">\n @for (view of optionViews(); track view.option.value) {\n <div\n class=\"sce-card-radio-group__card\"\n [class.sce-card-radio-group__card--selected]=\"view.selected\"\n [class.sce-card-radio-group__card--disabled]=\"isDisabled() || disabled()\"\n [attr.aria-checked]=\"view.selected\"\n [attr.aria-disabled]=\"isDisabled() || disabled()\"\n role=\"radio\"\n tabindex=\"0\"\n (click)=\"select(view.option)\"\n (keydown.space)=\"select(view.option)\"\n (keydown.enter)=\"select(view.option)\"\n >\n <span class=\"sce-card-radio-group__dot-ring\" [class.sce-card-radio-group__dot-ring--selected]=\"view.selected\" aria-hidden=\"true\">\n @if (view.selected) {\n <span class=\"sce-card-radio-group__dot\"></span>\n }\n </span>\n\n <span class=\"sce-card-radio-group__content\">\n @if (view.option.icon) {\n <img class=\"sce-card-radio-group__icon\" [src]=\"view.option.icon\" alt=\"\" aria-hidden=\"true\" />\n }\n <span class=\"sce-card-radio-group__option-label\" [class.sce-card-radio-group__option-label--selected]=\"view.selected\">\n {{ view.option.label }}\n </span>\n @if (view.option.description) {\n <span class=\"sce-card-radio-group__description\">\n {{ view.option.description }}\n </span>\n }\n </span>\n </div>\n }\n</div>\n", styles: [":host{display:block}.sce-card-radio-group__label{margin-block-end:var(--space-12);font-size:var(--font-size-md);font-weight:600;color:var(--text-text-primary-900);text-align:start}.sce-card-radio-group__grid{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-12)}@media(max-width:768px){.sce-card-radio-group__grid{grid-template-columns:1fr}}.sce-card-radio-group__card{display:flex;flex-direction:row-reverse;justify-content:space-between;align-items:center;gap:var(--space-16);padding-block:var(--space-16);padding-inline:var(--space-24);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);cursor:pointer;transition:border-color var(--transition-base),box-shadow var(--transition-base)}.sce-card-radio-group__card:hover:not(.sce-card-radio-group__card--disabled){border-color:var(--color-neutral-300)}.sce-card-radio-group__card:focus-visible{outline:2px solid var(--color-sucess-500);outline-offset:2px}.sce-card-radio-group__card--selected{border-color:var(--color-sucess-500)}.sce-card-radio-group__card--disabled{opacity:.6;cursor:not-allowed;pointer-events:none}.sce-card-radio-group__dot-ring{display:flex;align-items:center;justify-content:center;flex-shrink:0;block-size:var(--size-20);inline-size:var(--size-20);border:2px solid var(--color-neutral-300);border-radius:var(--radius-full);transition:border-color var(--transition-base)}.sce-card-radio-group__dot-ring--selected{border-color:var(--color-sucess-500)}.sce-card-radio-group__dot{block-size:var(--space-10);inline-size:var(--space-10);border-radius:var(--radius-full);background-color:var(--color-sucess-500)}.sce-card-radio-group__content{display:flex;flex:1;flex-direction:column;text-align:start}.sce-card-radio-group__icon{block-size:var(--size-24);inline-size:var(--size-24);object-fit:contain;margin-block-end:var(--space-4)}.sce-card-radio-group__option-label{font-size:var(--font-size-md);font-weight:700;color:var(--text-text-primary-900);transition:color var(--transition-base)}.sce-card-radio-group__option-label--selected{color:var(--text-text-primary-900)}.sce-card-radio-group__description{display:block;margin-block-start:var(--space-4);font-size:var(--font-size-xs);color:var(--color-neutral-500)}\n"] }]
114
115
  }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
115
116
 
117
+ /** Shared form-field wrapper that renders the label, required marker, projected control, help text and error message for the other sce field components; `id` and `label` are required. */
116
118
  class SceFieldComponent {
117
119
  id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
118
120
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
@@ -209,6 +211,7 @@ function createFieldErrorSignal(sources) {
209
211
  });
210
212
  }
211
213
 
214
+ /** Single-line text form field built on PrimeNG InputText, with a shared validation engine and an optional inline or absolute prefix; validation is opt-in, since `validationMode` defaults to `'never'`. */
212
215
  class SceTextFieldComponent {
213
216
  mirrorLabelAsPlaceholder = inject(SCE_MIRROR_LABEL_AS_PLACEHOLDER, {
214
217
  optional: true,
@@ -299,6 +302,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
299
302
  args: [{ selector: 'sce-text-field', standalone: true, imports: [FormsModule, InputText, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-text-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-field [id]=\"id()\" [label]=\"label()\" [required]=\"required()\" [helpText]=\"helpText()\" [error]=\"computedError()\">\n <div\n class=\"sce-text-field__control\"\n [class.inlineContainer]=\"isInlinePrefix()\"\n [class.inlineContainerInvalid]=\"isInlinePrefix() && computedError()\"\n [attr.dir]=\"dir() ?? null\"\n >\n @if (prefix() && prefixMode() === 'absolute') {\n <span class=\"sce-text-field__prefix\" aria-hidden=\"true\">{{ prefix() }}</span>\n }\n <input\n pInputText\n [id]=\"id()\"\n [class]=\"inputClasses()\"\n [type]=\"type()\"\n [attr.dir]=\"dir() ?? null\"\n [attr.name]=\"name() ?? null\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n [attr.list]=\"listId() ?? null\"\n [placeholder]=\"resolvedPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"onValueChange($event)\"\n (focus)=\"onFocus($event)\"\n (blur)=\"onBlur($event)\"\n [attr.aria-invalid]=\"computedError() ? true : null\"\n />\n @if (prefix() && prefixMode() === 'inline') {\n <span class=\"inlinePrefix\" aria-hidden=\"true\">{{ prefix() }}</span>\n }\n </div>\n</sce-field>\n", styles: ["@charset \"UTF-8\";sce-text-field{display:block}sce-text-field .w-full{width:100%}.sce-text-field__control{position:relative;display:flex;align-items:center;width:100%}.sce-text-field__control[dir=rtl] .p-inputtext.w-full{direction:ltr;text-align:end}.sce-text-field__control[dir=rtl] .p-inputtext.w-full::placeholder{text-align:end}.sce-text-field__control[dir=rtl] .inlineContainer .inlineInput.p-inputtext{direction:ltr;text-align:end}.sce-text-field__control[dir=rtl] .inlineContainer .inlineInput.p-inputtext::placeholder{text-align:end}.sce-text-field__prefix{position:absolute;inset-inline-end:var(--space-16);top:50%;transform:translateY(-50%);color:var(--color-muted-fg);-webkit-user-select:none;user-select:none;pointer-events:none;z-index:1}.sce-text-field__input--prefixed{padding-inline-end:calc(var(--space-4) + var(--space-6))}.inlineContainer{display:flex;align-items:center;justify-content:flex-end;width:100%;min-width:0;min-height:var(--size-52);box-sizing:border-box;padding-inline:var(--space-16);border:1px solid var(--color-neutral-200);border-radius:var(--radius-brand-sm);background:var(--app-surface);transition:border-color .2s;direction:ltr}.inlineContainer:focus-within{border-color:var(--button-background-primary-bg-primary)}.inlineContainerInvalid{border-color:var(--color-red-500);border-width:1.5px}.inlinePrefix{flex:0 0 auto;order:-1;color:var(--color-muted-fg);font-weight:var(--font-weight-regular);white-space:nowrap;margin-inline-end:var(--space-8)}.inlineContainer .inlineInput.p-inputtext,.inlineContainer input.p-inputtext.inlineInput{flex:0 1 auto;width:auto;min-width:0;max-width:100%;min-height:auto;padding:0;border:none;border-radius:0;background:transparent;box-shadow:none;field-sizing:content}.inlineContainer .inlineInput.p-inputtext:enabled:focus,.inlineContainer input.p-inputtext.inlineInput:enabled:focus{background:transparent;box-shadow:none}.inlineContainer .inlineInput.p-inputtext:focus,.inlineContainer input.p-inputtext.inlineInput:focus{outline:none;box-shadow:none}\n"] }]
300
303
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], listId: [{ type: i0.Input, args: [{ isSignal: true, alias: "listId", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], prefixMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixMode", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], focused: [{ type: i0.Output, args: ["focused"] }], blurred: [{ type: i0.Output, args: ["blurred"] }] } });
301
304
 
305
+ /** Multi-line textarea form field built on PrimeNG Textarea with the shared validation engine; validation is opt-in, since `validationMode` defaults to `'never'`. */
302
306
  class SceTextareaFieldComponent {
303
307
  mirrorLabelAsPlaceholder = inject(SCE_MIRROR_LABEL_AS_PLACEHOLDER, {
304
308
  optional: true,
@@ -369,6 +373,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
369
373
  args: [{ selector: 'sce-textarea-field', standalone: true, imports: [FormsModule, Textarea, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-textarea-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-field [id]=\"id()\" [label]=\"label()\" [required]=\"required()\" [helpText]=\"helpText()\" [error]=\"computedError()\">\n <textarea\n pTextarea\n [id]=\"id()\"\n [rows]=\"rows()\"\n [placeholder]=\"resolvedPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [attr.name]=\"name() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n [class]=\"inputClasses()\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"onValueChange($event)\"\n (blur)=\"onBlur($event)\"\n [attr.aria-invalid]=\"computedError() ? true : null\"\n ></textarea>\n</sce-field>\n" }]
370
374
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], blurred: [{ type: i0.Output, args: ["blurred"] }] } });
371
375
 
376
+ /** Password form field built on PrimeNG Password with a reveal toggle enabled by default and an optional strength-feedback panel; `id` and `label` are required. */
372
377
  class ScePasswordFieldComponent {
373
378
  id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
374
379
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
@@ -399,6 +404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
399
404
  args: [{ selector: 'sce-password-field', standalone: true, imports: [FormsModule, Password, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-password-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-field [id]=\"id()\" [label]=\"label()\" [required]=\"required()\" [helpText]=\"helpText()\" [error]=\"error()\">\n <p-password\n [inputId]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [toggleMask]=\"toggleMask()\"\n [feedback]=\"feedback()\"\n [promptLabel]=\"promptLabel() ?? ''\"\n [weakLabel]=\"weakLabel() ?? ''\"\n [mediumLabel]=\"mediumLabel() ?? ''\"\n [strongLabel]=\"strongLabel() ?? ''\"\n [attr.name]=\"name() ?? null\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"valueChange.emit($event)\"\n [styleClass]=\"wrapperClasses()\"\n [inputStyleClass]=\"inputClasses()\"\n [attr.aria-invalid]=\"error() ? true : null\"\n />\n</sce-field>\n", styles: ["sce-password-field{display:block}.sce-password-field .p-password,.sce-password-field .p-password-input{width:100%}\n"] }]
400
405
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], toggleMask: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleMask", required: false }] }], feedback: [{ type: i0.Input, args: [{ isSignal: true, alias: "feedback", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], promptLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "promptLabel", required: false }] }], weakLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "weakLabel", required: false }] }], mediumLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediumLabel", required: false }] }], strongLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "strongLabel", required: false }] }], panelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClassName", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
401
406
 
407
+ /** Single-select form field built on PrimeNG Select with a built-in validation engine that shows errors once the control is touched; when no placeholder is given it falls back to the label if the `SCE_MIRROR_LABEL_AS_PLACEHOLDER` token is provided. */
402
408
  class SceSelectFieldComponent {
403
409
  mirrorLabelAsPlaceholder = inject(SCE_MIRROR_LABEL_AS_PLACEHOLDER, {
404
410
  optional: true,
@@ -483,6 +489,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
483
489
  args: [{ selector: 'sce-select-field', standalone: true, imports: [FormsModule, Select, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-select-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"containerClassName()\" [attr.dir]=\"dir()\" [class]=\"fieldClassName()\">\n <sce-field\n [id]=\"id()\"\n [label]=\"label()\"\n [required]=\"required()\"\n [helpText]=\"helpText()\"\n [error]=\"displayError()\"\n [labelClassName]=\"labelClassName()\"\n [fieldClassName]=\"fieldClassName()\"\n >\n <p-select\n [inputId]=\"id()\"\n [ariaLabel]=\"label() || resolvedPlaceholder()\"\n [options]=\"options()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n optionDisabled=\"disabled\"\n [placeholder]=\"resolvedPlaceholder()\"\n [disabled]=\"disabled()\"\n [filter]=\"filter()\"\n [filterPlaceholder]=\"filterPlaceholder() ?? ''\"\n [showClear]=\"showClear()\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"onValueChange($event)\"\n (onBlur)=\"onBlur()\"\n [class.p-invalid]=\"displayError()\"\n [class.sce-select--borderless]=\"borderless()\"\n [styleClass]=\"'w-full ' + inputClassName()\"\n [panelStyleClass]=\"panelClassName()\"\n appendTo=\"body\"\n />\n </sce-field>\n</div>\n", styles: ["@charset \"UTF-8\";.root .p-select{width:100%;min-height:var(--space-56);border-radius:var(--radius-xl);border:1px solid var(--color-neutral-200);background:var(--color-surface);transition:border-color .15s ease}.root .p-select:not(.p-disabled).p-focus{box-shadow:none;border-color:var(--button-background-primary-bg-primary)}.root .p-select.sce-select--borderless:not(.p-invalid){border-color:transparent;border-radius:var(--radius-2xl, var(--radius-2xl))}.root .p-select.p-select.p-invalid{border-color:var(--text-text-error-primary)}.root .p-select.p-select.p-invalid:not(.p-disabled).p-focus{border-color:var(--text-text-error-primary);box-shadow:none}.root[dir=rtl] .p-select{display:flex;align-items:center;direction:ltr}.root[dir=rtl] .p-select .p-select-dropdown{order:-2;position:relative;inset:auto;display:flex;align-items:center;justify-content:center;align-self:stretch;flex-shrink:0;width:var(--space-40);margin:0;background:transparent;border:none}.root[dir=rtl] .p-select .p-select-clear-icon{order:-1;position:relative;inset:auto;flex-shrink:0;align-self:center;margin-inline-start:0;margin-inline-end:var(--space-4)}.root[dir=rtl] .p-select .p-select-label{order:0;display:flex;align-items:center;flex:1 1 auto;min-width:0;direction:ltr;text-align:end;justify-content:flex-end;width:auto;margin:0;padding-inline-start:var(--space-8);padding-inline-end:var(--space-16)}.root[dir=rtl] .p-select .p-select-label.p-placeholder{text-align:end}.root .p-select .p-select-label{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);color:var(--details-value-color);padding:var(--space-15, var(--space-15)) var(--space-14, var(--space-14))}.root .p-select .p-select-label.p-placeholder{color:var(--form-input-placeholder-color);opacity:1}.root .p-select-overlay{border-radius:var(--radius-xl);overflow:hidden}.root .p-select-overlay .p-select-list .p-select-option{transition:background-color .12s ease}.root .p-select-overlay .p-select-header .p-select-filter.p-select-filter{margin-inline-end:unset}\n"] }]
484
490
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], fieldClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldClassName", required: false }] }], labelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClassName", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], panelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClassName", required: false }] }], borderless: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderless", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showError: [{ type: i0.Input, args: [{ isSignal: true, alias: "showError", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], containerClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerClassName", required: false }] }] } });
485
491
 
492
+ /** Multi-select form field built on PrimeNG MultiSelect with a built-in required/min/max validation engine and an optional footer for adding new options; `id` and `label` are required. */
486
493
  class SceMultiSelectFieldComponent {
487
494
  id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
488
495
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
@@ -594,6 +601,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
594
601
  args: [{ selector: 'sce-multi-select-field', standalone: true, imports: [FormsModule, MultiSelect, PrimeTemplate, InputText, ButtonModule, SceFieldComponent, TranslatePipe], encapsulation: ViewEncapsulation.None, host: { class: 'sce-multi-select-field' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"containerClassName()\" [attr.dir]=\"dir()\">\n <sce-field\n [id]=\"id()\"\n [label]=\"label()\"\n [required]=\"required()\"\n [helpText]=\"helpText()\"\n [error]=\"computedError()\"\n [labelClassName]=\"labelClassName()\"\n [fieldClassName]=\"fieldClassName()\"\n >\n <p-multiselect\n [inputId]=\"id()\"\n [options]=\"options()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n optionDisabled=\"disabled\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [filter]=\"filter()\"\n [filterPlaceHolder]=\"filterPlaceholder() ?? ''\"\n [showClear]=\"showClear()\"\n [display]=\"display()\"\n [selectionLimit]=\"maxSelected() ?? null\"\n [selectedItemsLabel]=\"resolvedSelectedItemsLabel()\"\n [ngModel]=\"value()\"\n (ngModelChange)=\"onValueChange($event)\"\n (onBlur)=\"onBlur()\"\n [class.p-invalid]=\"computedError()\"\n [styleClass]=\"inputClasses()\"\n [panelStyleClass]=\"panelClassName()\"\n appendTo=\"body\"\n >\n @if (allowAdd()) {\n <ng-template pTemplate=\"footer\">\n <div class=\"sce-multi-select-field__add-footer\">\n <input\n pInputText\n class=\"sce-multi-select-field__add-input\"\n [ngModel]=\"newOptionValue()\"\n (ngModelChange)=\"onNewOptionInput($event)\"\n [placeholder]=\"addOptionPlaceholder()\"\n (keydown.enter)=\"$event.preventDefault(); handleAddOption()\"\n />\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-plus\"\n class=\"p-button-sm\"\n [attr.aria-label]=\"'common.add' | translate\"\n [disabled]=\"!newOptionValue().trim()\"\n (click)=\"handleAddOption()\"\n ></button>\n </div>\n </ng-template>\n }\n </p-multiselect>\n </sce-field>\n</div>\n", styles: ["@charset \"UTF-8\";.root .p-multiselect{width:100%;min-height:var(--space-56);border-radius:var(--radius-xl);border:1px solid var(--color-neutral-200);background:var(--color-surface);transition:border-color .15s ease}.root .p-multiselect:not(.p-disabled).p-focus{box-shadow:none;border-color:var(--button-background-primary-bg-primary)}.root .p-multiselect.p-multiselect.p-invalid{border-color:var(--text-text-error-primary)}.root .p-multiselect.p-multiselect.p-invalid:not(.p-disabled).p-focus{border-color:var(--text-text-error-primary);box-shadow:none}.root .p-multiselect .p-multiselect-label{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);color:var(--details-value-color);padding:var(--space-15, var(--space-15)) var(--space-14, var(--space-14));white-space:normal;display:flex;flex-wrap:wrap;gap:var(--space-8);align-items:center}.root .p-multiselect .p-multiselect-label-container{display:flex;flex:1;overflow:hidden}.root .p-multiselect .p-multiselect-token{max-width:100%;border:0;border-radius:var(--radius-full);background:var(--details-row-bg);font-family:var(--font-family-arabic-primary);color:var(--text-text-primary-900);font-size:var(--font-size-md);font-weight:500;padding:var(--space-4) var(--space-10);flex-direction:row-reverse}.root .p-multiselect .p-multiselect-token-label{max-width:var(--size-220);overflow:hidden;text-overflow:ellipsis}.root .p-multiselect .p-multiselect-token-icon{margin-inline-start:var(--space-8)}.root .p-multiselect .p-multiselect-label.p-placeholder{color:var(--form-input-placeholder-color);opacity:1}.root .p-multiselect-panel{border-radius:var(--radius-xl);overflow:hidden}.root .p-multiselect-panel .p-multiselect-items .p-multiselect-item{transition:background-color .12s ease}.sce-multi-select-field__add-footer{display:flex;gap:var(--space-2);padding:var(--space-3);border-block-start:1px solid var(--text-text-primary-100)}.sce-multi-select-field__add-input{flex:1;font-size:var(--font-size-sm)}\n"] }]
595
602
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], panelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClassName", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], fieldClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldClassName", required: false }] }], labelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClassName", required: false }] }], containerClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerClassName", required: false }] }], minSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelected", required: false }] }], maxSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelected", required: false }] }], validationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMode", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], validate: [{ type: i0.Input, args: [{ isSignal: true, alias: "validate", required: false }] }], selectedItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsLabel", required: false }] }], allowAdd: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowAdd", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], addOption: [{ type: i0.Output, args: ["addOption"] }] } });
596
603
 
604
+ /** Toggle switch built on PrimeNG ToggleSwitch, with optional active/inactive labels that fall back to translated defaults. */
597
605
  class SceSwitchComponent {
598
606
  translate = inject(TranslateService);
599
607
  checked = input(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
@@ -614,6 +622,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
614
622
 
615
623
  const RATING_MAX = 5;
616
624
  const STARS = [1, 2, 3, 4, 5];
625
+ /** Five-star rating input with hover preview, arrow-key adjustment and an optional error message, emitting the selected score. */
617
626
  class SceStarRatingInputComponent {
618
627
  value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
619
628
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
@@ -651,6 +660,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
651
660
  args: [{ host: { class: 'sce-star-rating-input' }, selector: 'sce-star-rating-input', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"starRating\">\n <!-- Focus lives on the child <button> stars (natively focusable); the group delegates keys.\n Making the group itself focusable would add a redundant tab stop. -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n <div class=\"starRow\" role=\"radiogroup\" [attr.aria-label]=\"ariaLabel()\" (mouseleave)=\"hoverScore.set(0)\" (keydown)=\"onKeyDown($event)\">\n @for (score of stars; track score) {\n <button\n type=\"button\"\n role=\"radio\"\n [attr.aria-checked]=\"value() === score\"\n [attr.aria-label]=\"score + ' / ' + max\"\n class=\"starButton\"\n [class.starButtonActive]=\"displayScore() >= score\"\n [disabled]=\"disabled()\"\n (mouseenter)=\"hoverScore.set(score)\"\n (focus)=\"hoverScore.set(score)\"\n (blur)=\"hoverScore.set(0)\"\n (click)=\"onStarClick(score)\"\n >\n <span class=\"starGlyph\" aria-hidden=\"true\">\u2605</span>\n </button>\n }\n </div>\n @if (error()) {\n <p class=\"starError\" role=\"alert\">{{ error() }}</p>\n }\n</div>\n", styles: [".sce-star-rating-input{display:contents}\n", ".starRating{display:flex;flex-direction:column;gap:var(--space-2)}.starRow{display:flex;flex-direction:row-reverse;gap:var(--space-1)}.starButton{background:transparent;border:none;cursor:pointer;padding:0;line-height:1;color:var(--color-neutral-300);transition:color .15s}.starButton:disabled{cursor:not-allowed;opacity:.5}.starButtonActive .starGlyph,.starButton.starButtonActive{color:var(--color-warning-400, #f59e0b)}.starGlyph{font-size:var(--font-size-3xl, 2rem)}.starError{color:var(--color-error-600);font-size:var(--font-size-sm);margin:0}\n"] }]
652
661
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
653
662
 
663
+ /** Currency amount field wrapped in `sce-field` that sanitizes typed text to a non-negative decimal and emits the parsed number, or `null` when cleared; `id` and `label` are required. */
654
664
  class SceCurrencyInputComponent {
655
665
  id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
656
666
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
@@ -690,6 +700,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
690
700
  args: [{ selector: 'sce-currency-input', standalone: true, imports: [FormsModule, InputText, SceFieldComponent], encapsulation: ViewEncapsulation.None, host: { class: 'sce-currency-input' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-field [id]=\"id()\" [label]=\"label()\" [required]=\"required()\" [helpText]=\"helpText()\" [error]=\"error()\">\n <div class=\"wrap\" [class.invalid]=\"invalid() || error()\" [class.disabled]=\"disabled()\" [class.readonly]=\"readonly()\">\n <input\n pInputText\n class=\"input\"\n [id]=\"id()\"\n inputmode=\"decimal\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [ngModel]=\"displayValue()\"\n (ngModelChange)=\"onInput($event)\"\n [attr.aria-invalid]=\"invalid() || error() ? true : null\"\n />\n <img class=\"icon\" src=\"/assets/icons/Saudi_Riyal_Symbol 1.svg\" alt=\"\" aria-hidden=\"true\" />\n </div>\n</sce-field>\n", styles: ["@charset \"UTF-8\";.wrap{display:flex;align-items:center;gap:var(--space-8);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding:0 .85rem;transition:border-color .15s ease,box-shadow .15s ease;min-height:var(--space-44, var(--size-44))}.wrap:focus-within{border-color:var(--form-control-focus-border)}.wrap.invalid{border-color:var(--text-text-error-primary)}.wrap.disabled,.wrap.readonly{background:var(--color-neutral-100);opacity:.85;cursor:not-allowed}.wrap .input,.wrap .input.p-inputtext{flex:1;min-width:0;border:0;border-radius:0;background:transparent;box-shadow:none;height:auto;padding-inline-start:0;padding-inline-end:0;outline:none;font:inherit;color:inherit;width:100%}.wrap .input:enabled:focus,.wrap .input.p-inputtext:enabled:focus{border:0;box-shadow:none;outline:none}.icon{flex-shrink:0;opacity:.75;width:var(--space-18);height:1.15rem;pointer-events:none}\n"] }]
691
701
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
692
702
 
703
+ /** Unlabelled numeric input with a trailing unit suffix that sanitizes typed text to a non-negative number and emits the sanitized string. */
693
704
  class SceUnitInputComponent {
694
705
  value = input('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
695
706
  unit = input('', ...(ngDevMode ? [{ debugName: "unit" }] : /* istanbul ignore next */ []));
@@ -726,6 +737,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
726
737
  args: [{ selector: 'sce-unit-input', standalone: true, imports: [FormsModule, InputText], encapsulation: ViewEncapsulation.None, host: { class: 'sce-unit-input' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClasses()\">\n <input\n pInputText\n [id]=\"id()\"\n [name]=\"name()\"\n [value]=\"displayValue()\"\n (input)=\"onInput($any($event.target).value)\"\n (focus)=\"onFocus($event)\"\n [attr.inputmode]=\"inputMode()\"\n [attr.min]=\"min() ?? null\"\n [attr.step]=\"step() ?? null\"\n type=\"text\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readOnly()\"\n [attr.aria-invalid]=\"invalid() ? true : null\"\n [attr.aria-label]=\"ariaLabel() || placeholder() || unit()\"\n [placeholder]=\"placeholder()\"\n [class]=\"inputClasses()\"\n />\n <span class=\"unit\" aria-hidden=\"true\">{{ unit() }}</span>\n</div>\n", styles: ["@charset \"UTF-8\";.wrap{display:flex;align-items:center;gap:var(--space-8);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding:0 .85rem;transition:border-color .15s ease,box-shadow .15s ease;min-height:var(--space-44, var(--size-44))}.wrap:focus-within{border-color:var(--form-control-focus-border)}.wrap.invalid{border-color:var(--text-text-error-primary)}.wrap.disabled{background:var(--color-neutral-100);opacity:.85;cursor:not-allowed}.wrap .input,.wrap .input.p-inputtext{flex:1;min-width:0;border:0;border-radius:0;background:transparent;box-shadow:none;padding-inline-start:0;padding-inline-end:0;outline:none;font:inherit;color:inherit;width:100%}.wrap .input:enabled:focus,.wrap .input.p-inputtext:enabled:focus{border:0;box-shadow:none;outline:none}.unit{flex-shrink:0;color:var(--text-text-secondary-700);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:1;pointer-events:none}\n"] }]
727
738
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], inputMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputMode", required: false }] }], allowDecimal: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDecimal", required: false }] }], inputClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClassName", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], focused: [{ type: i0.Output, args: ["focused"] }] } });
728
739
 
740
+ /** Labelled numeric field with a trailing unit suffix that defaults to the translated square-metre unit; `id` and `label` are required. */
729
741
  class SceUnitInputFieldComponent {
730
742
  translate = inject(TranslateService);
731
743
  id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
@@ -798,6 +810,7 @@ function endOfHijriMonth(anchor) {
798
810
  d.setDate(d.getDate() - 1);
799
811
  return d;
800
812
  }
813
+ /** Steps a `Date` forward or back by `delta` Hijri months by walking day-by-day across Umm al-Qura month boundaries. */
801
814
  function addHijriMonths(anchor, delta) {
802
815
  let next = new Date(anchor);
803
816
  const steps = Math.abs(delta);
@@ -821,6 +834,7 @@ function addHijriMonths(anchor, delta) {
821
834
  function pad2(n) {
822
835
  return String(n).padStart(2, '0');
823
836
  }
837
+ /** Formats a `Date` as its Umm al-Qura Hijri `YYYY-MM-DD` string. */
824
838
  function toHijriValue(date) {
825
839
  const { year, month, day } = getHijriYmd(date);
826
840
  return `${year}-${pad2(month)}-${pad2(day)}`;
@@ -828,10 +842,12 @@ function toHijriValue(date) {
828
842
  function getGregorianYmd(date) {
829
843
  return { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate() };
830
844
  }
845
+ /** Formats a `Date` as its local-time Gregorian `YYYY-MM-DD` string. */
831
846
  function toGregorianValue(date) {
832
847
  const { year, month, day } = getGregorianYmd(date);
833
848
  return `${year}-${pad2(month)}-${pad2(day)}`;
834
849
  }
850
+ /** Parses a `YYYY-MM-DD` string in the given calendar system back to a `Date`, returning `null` if it is malformed or (for Hijri) has no Gregorian match in the scanned window. */
835
851
  function parseValueToDate(value, system) {
836
852
  const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(value.trim());
837
853
  if (!match) {
@@ -928,6 +944,7 @@ function gregorianMonthNames(locale) {
928
944
  const base = locale === 'ar' ? 'ar-SA' : 'en-US';
929
945
  return Array.from({ length: 12 }, (_, i) => new Intl.DateTimeFormat(base, { month: 'long' }).format(new Date(2024, i, 1)));
930
946
  }
947
+ /** Builds the six-week day grid around `anchor` for the given calendar system and locale, along with the anchor month's index and year number. */
931
948
  function buildCalendarGrid(anchor, system, locale) {
932
949
  const weekdayFormatter = new Intl.DateTimeFormat(locale === 'ar' ? 'ar-SA' : 'en-US', {
933
950
  weekday: 'short',
@@ -1000,10 +1017,12 @@ function formatDateForDisplay(value, system, locale, displayFormat = 'iso', disp
1000
1017
  return value;
1001
1018
  }
1002
1019
  }
1020
+ /** Returns the Umm al-Qura Hijri year, month, and day numbers for a `Date`. */
1003
1021
  function getHijriYmdFromDate(date) {
1004
1022
  return getHijriYmd(date);
1005
1023
  }
1006
1024
 
1025
+ /** Fully-controlled modal calendar used by `sce-date-field`, rendering the day grid plus month and year pickers and emitting every navigation and selection as an output; `locale` and `grid` are required. */
1007
1026
  class SceDatePickerModalComponent {
1008
1027
  open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
1009
1028
  locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -1109,6 +1128,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1109
1128
  args: [{ host: { class: 'sce-date-picker-modal' }, selector: 'sce-date-picker-modal', standalone: true, imports: [TranslatePipe], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open()) {\n <div class=\"df-backdrop\" role=\"presentation\" (click)=\"onBackdropClick($event)\">\n <div\n class=\"df-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\n [attr.aria-label]=\"'date.selectDate' | translate\"\n >\n <!-- Title bar -->\n <div class=\"df-titlebar\">\n <span class=\"df-title\">{{ 'date.selectDate' | translate }}</span>\n <button type=\"button\" class=\"df-close-btn\" [attr.aria-label]=\"'common.close' | translate\" (click)=\"cancel.emit()\">&#x2715;</button>\n </div>\n\n <!-- Calendar system toggle -->\n @if (showToggle() && !hijriOnly()) {\n <div class=\"df-tabs\" role=\"tablist\">\n <button\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"system() === 'hijri'\"\n class=\"df-tab\"\n [class.df-tab--active]=\"system() === 'hijri'\"\n (click)=\"systemChange.emit('hijri')\"\n >\n {{ 'date.hijri' | translate }}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"system() === 'gregorian'\"\n class=\"df-tab\"\n [class.df-tab--active]=\"system() === 'gregorian'\"\n (click)=\"systemChange.emit('gregorian')\"\n >\n {{ 'date.gregorian' | translate }}\n </button>\n </div>\n }\n\n <!-- Calendar header -->\n <div class=\"df-cal-header\">\n <button type=\"button\" class=\"df-nav-btn\" [attr.aria-label]=\"'date.previousMonth' | translate\" (click)=\"movePrev.emit()\">\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n <div class=\"df-month-year\">\n <button type=\"button\" class=\"df-month-year-btn\" (click)=\"showMonthPickerChange.emit()\">\n {{ monthLabel() }}\n </button>\n <button type=\"button\" class=\"df-month-year-btn\" (click)=\"showYearPickerChange.emit()\">\n {{ currentYearNumber() }}\n </button>\n </div>\n <button type=\"button\" class=\"df-nav-btn\" [attr.aria-label]=\"'date.nextMonth' | translate\" (click)=\"moveNext.emit()\">\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n </div>\n\n <!-- Month picker -->\n @if (showMonthPicker()) {\n <div class=\"df-month-grid\">\n @for (name of monthNames(); track name; let i = $index) {\n <button\n type=\"button\"\n class=\"df-month-cell\"\n [class.df-month-cell--active]=\"i === currentMonthIndex()\"\n (click)=\"selectMonth.emit(i)\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n <!-- Year picker -->\n @if (showYearPicker()) {\n <div class=\"df-year-picker\">\n <div class=\"df-year-picker-header\">\n <button type=\"button\" class=\"df-nav-btn\" (click)=\"yearPagePrev.emit()\">\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n <span class=\"df-year-range-label\">{{ yearRangeLabel() }}</span>\n <button type=\"button\" class=\"df-nav-btn\" (click)=\"yearPageNext.emit()\">\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n </div>\n <div class=\"df-year-grid\">\n @for (year of yearRange(); track year) {\n <button\n type=\"button\"\n class=\"df-year-cell\"\n [class.df-year-cell--active]=\"year === currentYearNumber()\"\n (click)=\"selectYear.emit(year)\"\n >\n {{ year }}\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Day grid -->\n @if (!showMonthPicker() && !showYearPicker()) {\n <div class=\"df-weekdays\">\n @for (w of grid().weekdays; track w) {\n <div class=\"df-weekday\">{{ w }}</div>\n }\n </div>\n <div class=\"df-days\" (mouseleave)=\"selectionMode() === 'range' ? clearHoverDay.emit() : null\">\n @for (view of dayViews(); track view.day.date.toISOString()) {\n <button\n type=\"button\"\n [disabled]=\"view.disabled\"\n [class]=\"view.classes\"\n (mouseenter)=\"onDayMouseEnter(view.day.value, view.disabled)\"\n (click)=\"onDayClick(view.day.value, view.disabled)\"\n >\n {{ view.day.labelDay }}\n </button>\n }\n </div>\n\n <!-- Time row -->\n <div class=\"df-time-row\">\n <span class=\"df-time-label\">{{ 'date.time' | translate }}</span>\n <span class=\"df-time-value\">11:59 {{ 'date.pm' | translate }}</span>\n </div>\n }\n\n <!-- Footer -->\n <div class=\"df-footer\">\n <button type=\"button\" class=\"df-footer-btn df-footer-btn--confirm\" (click)=\"confirm.emit()\">\n {{ 'common.confirm' | translate }}\n </button>\n <button type=\"button\" class=\"df-footer-btn df-footer-btn--cancel\" (click)=\"cancel.emit()\">\n {{ 'common.cancel' | translate }}\n </button>\n </div>\n </div>\n </div>\n}\n" }]
1110
1129
  }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], system: [{ type: i0.Input, args: [{ isSignal: true, alias: "system", required: false }] }], showToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggle", required: false }] }], hijriOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "hijriOnly", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], draftSingle: [{ type: i0.Input, args: [{ isSignal: true, alias: "draftSingle", required: false }] }], draftRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "draftRange", required: false }] }], hoveredDay: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoveredDay", required: false }] }], anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], canShowToday: [{ type: i0.Input, args: [{ isSignal: true, alias: "canShowToday", required: false }] }], grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: true }] }], currentMonthIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentMonthIndex", required: false }] }], currentYearNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentYearNumber", required: false }] }], yearRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearRange", required: false }] }], yearPageStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearPageStart", required: false }] }], showMonthPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMonthPicker", required: false }] }], showYearPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "showYearPicker", required: false }] }], systemChange: [{ type: i0.Output, args: ["systemChange"] }], showMonthPickerChange: [{ type: i0.Output, args: ["showMonthPickerChange"] }], showYearPickerChange: [{ type: i0.Output, args: ["showYearPickerChange"] }], movePrev: [{ type: i0.Output, args: ["movePrev"] }], moveNext: [{ type: i0.Output, args: ["moveNext"] }], selectDay: [{ type: i0.Output, args: ["selectDay"] }], hoverDay: [{ type: i0.Output, args: ["hoverDay"] }], clearHoverDay: [{ type: i0.Output, args: ["clearHoverDay"] }], selectMonth: [{ type: i0.Output, args: ["selectMonth"] }], selectYear: [{ type: i0.Output, args: ["selectYear"] }], yearPagePrev: [{ type: i0.Output, args: ["yearPagePrev"] }], yearPageNext: [{ type: i0.Output, args: ["yearPageNext"] }], today: [{ type: i0.Output, args: ["today"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], confirm: [{ type: i0.Output, args: ["confirm"] }], backdropClick: [{ type: i0.Output, args: ["backdropClick"] }] } });
1111
1130
 
1131
+ /** Date field that pairs a text input with a modal calendar supporting both Hijri and Gregorian systems and single or range selection; it defaults to the Hijri calendar and locks body scroll while the calendar is open. */
1112
1132
  class SceDateFieldComponent {
1113
1133
  doc = inject(DOCUMENT);
1114
1134
  id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
@@ -1367,6 +1387,7 @@ function getPaginationItems(currentPage, totalPages) {
1367
1387
  items.push(totalPages);
1368
1388
  return items;
1369
1389
  }
1390
+ /** Page-number paginator with an ellipsis window and a page-size select; it is stateless (`page`, `pageSize`, `totalItems` are required inputs) and derives direction from `locale` unless `dir` is set — note it uses `ViewEncapsulation.None`. */
1370
1391
  class ScePaginatorComponent {
1371
1392
  page = input.required(...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
1372
1393
  pageSize = input.required(...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
@@ -1405,6 +1426,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1405
1426
  args: [{ host: { class: 'sce-paginator' }, selector: 'sce-paginator', standalone: true, imports: [Select, FormsModule, TranslatePipe, DigitPipe], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-paginator__bar\" [attr.dir]=\"effectiveDir()\">\n <div class=\"sce-paginator__nav\">\n <button\n type=\"button\"\n [disabled]=\"currentPage() <= 1\"\n (click)=\"goToPage(currentPage() - 1)\"\n class=\"sce-paginator__btn\"\n [attr.aria-label]=\"'pagination.previousPage' | translate\"\n >\n @if (isRtl()) {\n <img src=\"/assets/icons/caret-right.svg\" width=\"24\" height=\"24\" aria-hidden=\"true\" alt=\"\" />\n } @else {\n <img src=\"/assets/icons/caret-left.svg\" width=\"24\" height=\"24\" aria-hidden=\"true\" alt=\"\" />\n }\n </button>\n\n <!-- track $index: pagination items are positional; 'ellipsis' repeats, so there is no identity -->\n @for (item of items(); track $index) {\n @if (item === 'ellipsis') {\n <span class=\"sce-paginator__ellipsis\">. . .</span>\n } @else {\n <button\n type=\"button\"\n [disabled]=\"item === currentPage()\"\n (click)=\"goToPage(item)\"\n class=\"sce-paginator__page\"\n [class.sce-paginator__page--active]=\"item === currentPage()\"\n >\n {{ item | digit }}\n </button>\n }\n }\n\n <button\n type=\"button\"\n [disabled]=\"currentPage() >= totalPages()\"\n (click)=\"goToPage(currentPage() + 1)\"\n class=\"sce-paginator__btn\"\n [attr.aria-label]=\"'pagination.nextPage' | translate\"\n >\n @if (isRtl()) {\n <img src=\"/assets/icons/caret-left.svg\" width=\"20\" height=\"20\" aria-hidden=\"true\" alt=\"\" />\n } @else {\n <img src=\"/assets/icons/caret-right.svg\" width=\"20\" height=\"20\" aria-hidden=\"true\" alt=\"\" />\n }\n </button>\n </div>\n\n <div class=\"sce-paginator__size\">\n <p class=\"sce-paginator__show-label\">\n {{ showLabel() ?? ('common.pagination.show' | translate) }}\n </p>\n <p-select\n dir=\"ltr\"\n [options]=\"pageSizeSelectOptions()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"pageSize()\"\n (ngModelChange)=\"onPageSizeSelect($event)\"\n styleClass=\"pageSizeDropdown\"\n panelStyleClass=\"pageSizePanel\"\n appendTo=\"body\"\n />\n </div>\n</div>\n", styles: [".sce-paginator__bar{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:var(--space-12);width:100%;min-height:var(--space-48)}.sce-paginator__nav{display:flex;flex-wrap:wrap;gap:var(--space-6);align-items:center;min-width:0}@media(max-width:576px){.sce-paginator__nav{width:100%;justify-content:center}}@media(min-width:577px){.sce-paginator__nav{gap:var(--space-8)}}.sce-paginator__size{width:8.3125rem;flex-shrink:0;display:flex;justify-content:space-between;align-items:center;gap:var(--space-12)}@media(max-width:576px){.sce-paginator__size{width:100%}}.sce-paginator__btn{display:flex;align-items:center;justify-content:center;width:var(--size-40);height:var(--size-40);border-radius:var(--radius-full);background:var(--pagination-surface);border:none;cursor:pointer;transition:background-color .2s;flex-shrink:0}@media(min-width:577px){.sce-paginator__btn{width:var(--size-44);height:var(--size-44)}}.sce-paginator__btn:hover{background:var(--pagination-surface-hover)}.sce-paginator__btn:disabled{opacity:.5;cursor:not-allowed}.sce-paginator__ellipsis{display:flex;align-items:center;justify-content:center;width:var(--size-40);height:var(--size-40);border-radius:var(--radius-full);background:var(--pagination-surface);color:var(--pagination-text);font-family:var(--font-family-base);font-weight:var(--font-weight-medium);font-size:var(--font-size-sm);letter-spacing:.005em;flex-shrink:0}@media(min-width:577px){.sce-paginator__ellipsis{width:var(--size-44);height:var(--size-44)}}.sce-paginator__page{display:flex;align-items:center;justify-content:center;width:var(--size-40);height:var(--size-40);border-radius:var(--radius-full);background:var(--pagination-surface);color:var(--pagination-text);font-family:var(--font-family-base);font-weight:var(--font-weight-medium);font-size:var(--font-size-sm);letter-spacing:.005em;border:none;cursor:pointer;transition:background-color .2s;flex-shrink:0}@media(min-width:577px){.sce-paginator__page{width:var(--size-44);height:var(--size-44)}}.sce-paginator__page:hover{background:var(--pagination-surface-inactive-hover)}.sce-paginator__page--active{background:var(--pagination-surface-active);color:var(--pagination-text-active);cursor:default}.sce-paginator__page--active:hover{background:var(--pagination-surface-active-hover)}.sce-paginator__show-label{font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-medium);font-size:var(--font-size-base);letter-spacing:0;color:var(--color-neutral-700);margin:0}.pageSizeDropdown{width:var(--space-88, var(--size-88));height:var(--space-48);border-radius:var(--radius-full);border:1px solid var(--control-border);background:var(--dropdown-surface);align-items:center}.pageSizeDropdown .p-select-label{display:flex;align-items:center;justify-content:center;width:100%;padding:0 1rem;margin:0;font-family:var(--font-family-base);font-size:var(--font-size-md);font-weight:var(--font-weight-regular);color:var(--control-text);text-align:center}.pageSizeDropdown .p-select-label.p-inputtext{height:100%;border:0;background:transparent;box-shadow:none}.pageSizeDropdown .p-select-dropdown{width:var(--space-28);color:var(--control-text)}.pageSizeDropdown.p-select:not(.p-disabled).p-focus{box-shadow:none;outline:none;border-color:var(--control-border)}.pageSizePanel .p-select-option{font-family:var(--font-family-base);font-size:var(--font-size-md);justify-content:center}.pageSizePanel .p-select-option.p-select-option-selected,.pageSizePanel .p-select-option.p-focus{background:var(--form-control-option-selected-bg);color:var(--form-control-option-selected-text)}.pageSizePanel .p-select-option:not(.p-select-option-selected):not(.p-disabled):hover{background:var(--form-control-option-hover-bg);color:var(--form-control-option-selected-text)}\n"] }]
1406
1427
  }], propDecorators: { page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: true }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], numberFormatter: [{ type: i0.Input, args: [{ isSignal: true, alias: "numberFormatter", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }] } });
1407
1428
 
1429
+ /** Design-system demo harness that wires `sce-paginator` to local page state; not for production pages. */
1408
1430
  class ScePaginatorDemoComponent {
1409
1431
  totalRecords = input(120, ...(ngDevMode ? [{ debugName: "totalRecords" }] : /* istanbul ignore next */ []));
1410
1432
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -1425,6 +1447,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1425
1447
  args: [{ host: { class: 'sce-paginator-demo' }, selector: 'sce-paginator-demo', standalone: true, imports: [ScePaginatorComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-paginator\n [page]=\"page\"\n [pageSize]=\"pageSize\"\n [totalItems]=\"totalRecords()\"\n [locale]=\"locale()\"\n (pageChange)=\"onPageChange($event)\"\n (pageSizeChange)=\"onPageSizeChange($event)\"\n/>\n", styles: [":host{display:block}.sce-paginator-demo{display:contents}\n"] }]
1426
1448
  }], propDecorators: { totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }] } });
1427
1449
 
1450
+ /** Shared PrimeNG-Dialog shell that every sce dialog builds on, providing the sticky header, close button, projected body and footer and the size presets; setting `locked` blocks both Escape and mask dismissal. */
1428
1451
  class SceDialogShellComponent {
1429
1452
  /** Controls dialog visibility. */
1430
1453
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
@@ -1507,6 +1530,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1507
1530
  args: [{ host: { class: 'sce-dialog-shell' }, selector: 'sce-dialog-shell', standalone: true, imports: [Dialog, TranslatePipe], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<p-dialog\n [visible]=\"visible()\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [showHeader]=\"false\"\n [dismissableMask]=\"effectiveDismissableMask()\"\n [closeOnEscape]=\"effectiveCloseOnEscape()\"\n [styleClass]=\"rootStyleClass()\"\n [style]=\"style()\"\n contentStyleClass=\"content\"\n appendTo=\"body\"\n (onHide)=\"onHide()\"\n>\n <div [class]=\"shellClass()\" [dir]=\"dir()\">\n <header [class]=\"headerClass()\">\n <div class=\"headerText\">\n <h2 class=\"title\">{{ title() }}</h2>\n @if (subtitle()) {\n <p class=\"subtitle\">{{ subtitle() }}</p>\n }\n </div>\n @if (showCloseButton()) {\n <button\n type=\"button\"\n class=\"closeButton\"\n [disabled]=\"locked()\"\n (click)=\"close.emit()\"\n [attr.aria-label]=\"closeAriaLabel() ?? ('common.close' | translate)\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n\n @if (hasBody()) {\n <div [class]=\"bodyClass()\">\n <ng-content />\n </div>\n }\n\n @if (hasFooter()) {\n <div class=\"shellFooter\">\n <ng-content select=\"[dialogFooter]\" />\n </div>\n }\n </div>\n</p-dialog>\n", styles: ["@charset \"UTF-8\";.sce-dialog-shell-dialog{width:min(var(--size-560),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));max-height:90vb;border-radius:var(--radius-20);overflow:hidden}.sce-dialog-shell-dialog.size-sm,.sce-dialog-shell-dialog.size-md{width:min(var(--size-560),100vi - var(--size-24));max-width:calc(100vi - var(--size-24))}.sce-dialog-shell-dialog.size-lg{width:min(var(--size-720),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));min-width:min(var(--size-560),100vi - var(--size-24))}.sce-dialog-shell-dialog.size-xl{width:min(var(--size-960),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));min-width:min(var(--size-560),100vi - var(--size-24))}.sce-dialog-shell-dialog .content{padding:0;border-radius:var(--radius-20);max-height:90vb;display:flex;flex-direction:column;overflow:hidden}.sce-dialog-shell-dialog .shell{display:flex;flex-direction:column;min-height:0;flex:1 1 auto;background:var(--color-surface);gap:var(--space-16);padding:var(--space-32)}.sce-dialog-shell-dialog .header{flex:0 0 auto;position:relative;display:flex;align-items:flex-start;gap:var(--space-12);padding:0}.sce-dialog-shell-dialog .headerOnly{padding-block-end:0}.sce-dialog-shell-dialog .headerCenter .header{display:grid;grid-template-columns:1fr;text-align:center;direction:inherit}.sce-dialog-shell-dialog .closeButton{width:var(--space-40);height:var(--space-40);display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:var(--radius-xl);background:var(--app-surface-muted);color:var(--details-title-color);font-size:var(--font-size-22);line-height:1;cursor:pointer;flex:0 0 auto}.sce-dialog-shell-dialog .closeButton .pi{font-size:var(--font-size-base)}.sce-dialog-shell-dialog .closeButton:hover{background:var(--app-surface-hover)}.sce-dialog-shell-dialog .headerCenter .closeButton{position:absolute;inset-inline-end:0;top:0}.sce-dialog-shell-dialog .headerText{display:grid;gap:var(--space-8);min-width:0;flex:1 1 auto}.sce-dialog-shell-dialog .headerCenter .headerText{padding-inline:var(--space-56)}.sce-dialog-shell-dialog .headerCenter .header{min-height:var(--space-72)}.sce-dialog-shell-dialog .title{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-bold);font-size:var(--font-size-2xl-24);line-height:1.4;color:var(--text-text-primary-900);text-align:start}.sce-dialog-shell-dialog .headerCenter .title{text-align:center}.sce-dialog-shell-dialog .subtitle{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-regular);font-size:var(--font-size-lg);line-height:1.5;color:var(--text-text-secondary-700);text-align:start}.sce-dialog-shell-dialog .headerCenter .subtitle{text-align:center}.sce-dialog-shell-dialog .headerSpacer{display:none}.sce-dialog-shell-dialog .body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding:0;display:grid;gap:var(--space-20)}.sce-dialog-shell-dialog .body::-webkit-scrollbar{width:var(--space-8)}.sce-dialog-shell-dialog .body::-webkit-scrollbar-track{background:transparent}.sce-dialog-shell-dialog .body::-webkit-scrollbar-thumb{background:var(--color-neutral-200);border-radius:var(--radius-lg)}.sce-dialog-shell-dialog .body::-webkit-scrollbar-thumb:hover{background:var(--color-neutral-300)}.sce-dialog-shell-dialog .bodyCompact{padding:0}.sce-dialog-shell-dialog .shellFooter{display:contents}.sce-dialog-shell-dialog .footer{position:relative;flex:0 0 auto;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12);padding:0;background:var(--color-surface);width:100%}.sce-dialog-shell-dialog .footer>button{display:block;width:100%;box-sizing:border-box}.sce-dialog-shell-dialog .footerSingle{grid-template-columns:1fr}@media(max-width:768px){.sce-dialog-shell-dialog,.sce-dialog-shell-dialog.size-md,.sce-dialog-shell-dialog.size-lg,.sce-dialog-shell-dialog.size-xl,.sce-dialog-shell-dialog.size-sm{width:calc(100vi - var(--space-16, var(--size-16)));min-width:0;max-width:calc(100vi - var(--size-16));max-height:calc(100vb - var(--size-32))}.sce-dialog-shell-dialog .shell{padding:var(--space-16);gap:var(--space-12)}}\n"] }]
1508
1531
  }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], centerHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerHeader", required: false }] }], showCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseButton", required: false }] }], locked: [{ type: i0.Input, args: [{ isSignal: true, alias: "locked", required: false }] }], dismissableMask: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissableMask", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], style: [{ type: i0.Input, args: [{ isSignal: true, alias: "style", required: false }] }], compactBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "compactBody", required: false }] }], closeAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeAriaLabel", required: false }] }], hasBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBody", required: false }] }], hasFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasFooter", required: false }] }], close: [{ type: i0.Output, args: ["close"] }] } });
1509
1532
 
1533
+ /** Design-system demo host that shows `sce-dialog-shell` and reports its visibility back through `visibleChange`. */
1510
1534
  class SceDialogShellDemoComponent {
1511
1535
  visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
1512
1536
  visibleChange = output();
@@ -1533,6 +1557,7 @@ const ICON_BY_VARIANT = {
1533
1557
  warning: 'pi pi-exclamation-circle',
1534
1558
  info: 'pi pi-info-circle',
1535
1559
  };
1560
+ /** Confirmation dialog built on `sce-dialog-shell` with per-variant icon and button styling and an optional reason field; supplying `onConfirmHandler` makes it await the async handler and lock the buttons, mask and Escape while pending. */
1536
1561
  class SceConfirmDialogComponent {
1537
1562
  translate = inject(TranslateService);
1538
1563
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
@@ -1684,6 +1709,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1684
1709
  args: [{ host: { class: 'sce-confirm-dialog' }, selector: 'sce-confirm-dialog', standalone: true, imports: [SceDialogShellComponent, FormsModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"title()\"\n [subtitle]=\"subtitleText()\"\n [size]=\"size()\"\n [centerHeader]=\"centerHeader()\"\n [locked]=\"isPending()\"\n [hasBody]=\"hasBodyContent()\"\n (close)=\"onDialogClose()\"\n>\n <!-- Icon -->\n @if (icon() !== undefined) {\n <div class=\"iconWrap\">\n <span class=\"iconCircle {{ iconClass() }}\">\n @if (icon() === 'custom') {\n <ng-content select=\"[confirmIcon]\" />\n } @else {\n <i [class]=\"iconPiClass()\" aria-hidden=\"true\"></i>\n }\n </span>\n </div>\n }\n\n <!-- Custom body slot -->\n @if (hasBodySlot()) {\n <ng-content select=\"[confirmBody]\" />\n }\n\n <!-- Body description -->\n @if (showBodyDescription()) {\n <p class=\"message\">{{ description() }}</p>\n }\n\n <!-- Reason/comment field -->\n @if (field(); as f) {\n <div class=\"fieldGroup\">\n <p class=\"fieldLabel\">\n {{ f.label }}\n @if (fieldRequired()) {\n <span class=\"requiredMark\" aria-hidden=\"true\"> *</span>\n }\n </p>\n @if (multiline()) {\n <textarea\n class=\"p-inputtextarea p-inputtext w-full\"\n [class.p-invalid]=\"fieldHasError()\"\n [placeholder]=\"f.placeholder ?? ''\"\n [value]=\"fieldValue()\"\n [required]=\"fieldRequired()\"\n [attr.aria-required]=\"fieldRequired()\"\n [attr.aria-invalid]=\"fieldHasError()\"\n [attr.maxlength]=\"f.maxLength ?? null\"\n [rows]=\"f.rows ?? 4\"\n (input)=\"onFieldChange($any($event.target).value)\"\n ></textarea>\n } @else {\n <input\n class=\"p-inputtext w-full\"\n [class.p-invalid]=\"fieldHasError()\"\n [placeholder]=\"f.placeholder ?? ''\"\n [value]=\"fieldValue()\"\n [required]=\"fieldRequired()\"\n [attr.aria-required]=\"fieldRequired()\"\n [attr.aria-invalid]=\"fieldHasError()\"\n [attr.maxlength]=\"f.maxLength ?? null\"\n (input)=\"onFieldChange($any($event.target).value)\"\n />\n }\n @if (displayedFieldError()) {\n <p class=\"fieldError\">{{ displayedFieldError() }}</p>\n }\n </div>\n }\n\n <!-- Footer buttons -->\n <div dialogFooter class=\"footer\" [class.footerSingle]=\"hideCancelButton()\">\n <button type=\"button\" [class]=\"confirmBtnClass()\" [disabled]=\"confirmBtnDisabled()\" (click)=\"onConfirm()\">\n {{ resolvedConfirmLabel() }}\n </button>\n @if (!hideCancelButton()) {\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"cancelBtnDisabled()\" (click)=\"onCancel()\">\n {{ resolvedCancelLabel() }}\n </button>\n }\n </div>\n</sce-dialog-shell>\n", styles: ["@charset \"UTF-8\";.sce-dialog-shell-dialog{width:min(var(--size-560),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));max-height:90vb;border-radius:var(--radius-20);overflow:hidden}.sce-dialog-shell-dialog.size-sm,.sce-dialog-shell-dialog.size-md{width:min(var(--size-560),100vi - var(--size-24));max-width:calc(100vi - var(--size-24))}.sce-dialog-shell-dialog.size-lg{width:min(var(--size-720),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));min-width:min(var(--size-560),100vi - var(--size-24))}.sce-dialog-shell-dialog.size-xl{width:min(var(--size-960),100vi - var(--size-24));max-width:calc(100vi - var(--size-24));min-width:min(var(--size-560),100vi - var(--size-24))}.sce-dialog-shell-dialog .content{padding:0;border-radius:var(--radius-20);max-height:90vb;display:flex;flex-direction:column;overflow:hidden}.sce-dialog-shell-dialog .shell{display:flex;flex-direction:column;min-height:0;flex:1 1 auto;background:var(--color-surface);gap:var(--space-16);padding:var(--space-32)}.sce-dialog-shell-dialog .header{flex:0 0 auto;position:relative;display:flex;align-items:flex-start;gap:var(--space-12);padding:0}.sce-dialog-shell-dialog .headerOnly{padding-block-end:0}.sce-dialog-shell-dialog .headerCenter .header{display:grid;grid-template-columns:1fr;text-align:center;direction:inherit}.sce-dialog-shell-dialog .closeButton{width:var(--space-40);height:var(--space-40);display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:var(--radius-xl);background:var(--app-surface-muted);color:var(--details-title-color);font-size:var(--font-size-22);line-height:1;cursor:pointer;flex:0 0 auto}.sce-dialog-shell-dialog .closeButton .pi{font-size:var(--font-size-base)}.sce-dialog-shell-dialog .closeButton:hover{background:var(--app-surface-hover)}.sce-dialog-shell-dialog .headerCenter .closeButton{position:absolute;inset-inline-end:0;top:0}.sce-dialog-shell-dialog .headerText{display:grid;gap:var(--space-8);min-width:0;flex:1 1 auto}.sce-dialog-shell-dialog .headerCenter .headerText{padding-inline:var(--space-56)}.sce-dialog-shell-dialog .headerCenter .header{min-height:var(--space-72)}.sce-dialog-shell-dialog .title{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-bold);font-size:var(--font-size-2xl-24);line-height:1.4;color:var(--text-text-primary-900);text-align:start}.sce-dialog-shell-dialog .headerCenter .title{text-align:center}.sce-dialog-shell-dialog .subtitle{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-regular);font-size:var(--font-size-lg);line-height:1.5;color:var(--text-text-secondary-700);text-align:start}.sce-dialog-shell-dialog .headerCenter .subtitle{text-align:center}.sce-dialog-shell-dialog .headerSpacer{display:none}.sce-dialog-shell-dialog .body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding:0;display:grid;gap:var(--space-20)}.sce-dialog-shell-dialog .body::-webkit-scrollbar{width:var(--space-8)}.sce-dialog-shell-dialog .body::-webkit-scrollbar-track{background:transparent}.sce-dialog-shell-dialog .body::-webkit-scrollbar-thumb{background:var(--color-neutral-200);border-radius:var(--radius-lg)}.sce-dialog-shell-dialog .body::-webkit-scrollbar-thumb:hover{background:var(--color-neutral-300)}.sce-dialog-shell-dialog .bodyCompact{padding:0}.sce-dialog-shell-dialog .shellFooter{display:contents}.sce-dialog-shell-dialog .footer{position:relative;flex:0 0 auto;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12);padding:0;background:var(--color-surface);width:100%}.sce-dialog-shell-dialog .footer>button{display:block;width:100%;box-sizing:border-box}.sce-dialog-shell-dialog .footerSingle{grid-template-columns:1fr}@media(max-width:768px){.sce-dialog-shell-dialog,.sce-dialog-shell-dialog.size-md,.sce-dialog-shell-dialog.size-lg,.sce-dialog-shell-dialog.size-xl,.sce-dialog-shell-dialog.size-sm{width:calc(100vi - var(--space-16, var(--size-16)));min-width:0;max-width:calc(100vi - var(--size-16));max-height:calc(100vb - var(--size-32))}.sce-dialog-shell-dialog .shell{padding:var(--space-16);gap:var(--space-12)}}\n", "@charset \"UTF-8\";.message{margin:0;font-family:var(--font-family-arabic-primary);font-weight:400;font-size:var(--font-size-md);line-height:1.6;text-align:start;color:var(--text-text-secondary-700)}.iconWrap{display:flex;justify-content:center;margin-block-end:var(--space-4)}.iconCircle{width:var(--space-56);height:var(--space-56);border-radius:var(--radius-full);display:inline-flex;align-items:center;justify-content:center;font-size:var(--font-size-26)}.iconPrimary{background:color-mix(in srgb,var(--button-background-primary-bg-primary) 12%,transparent);color:var(--button-background-primary-bg-primary)}.iconDanger{background:var(--color-red-200);color:var(--color-red-700)}.iconSuccess{background:var(--color-kiwi-100);color:var(--color-kiwi-700)}.iconWarning{background:var(--color-yellow-100);color:var(--color-orange-600)}.iconInfo{background:var(--color-blue-100);color:var(--color-blue-700)}.fieldGroup{display:grid;gap:var(--space-8);text-align:start}.fieldLabel{margin:0;font-family:var(--font-family-arabic-primary);font-weight:500;font-size:var(--font-size-sm);color:var(--form-label-muted)}.requiredMark{color:var(--color-danger);margin-inline-start:var(--space-2)}.fieldError{margin:0;color:var(--color-danger);font-size:var(--font-size-sm);font-weight:500}.btn{width:100%;min-height:var(--space-48);border-radius:var(--radius-xl);padding:var(--space-10) var(--space-20);font-family:var(--font-family-arabic-primary);font-weight:700;font-size:var(--font-size-md-15);text-align:center;border:1px solid transparent;cursor:pointer;transition:background .15s ease,border-color .15s ease,color .15s ease,opacity .15s ease}.btn:disabled{opacity:.55;cursor:not-allowed}.cancel{border:1.5px solid var(--color-brand-primary-900);color:var(--color-brand-primary-900);background:var(--background-bg-primary)}.cancel:hover:not(:disabled){background:var(--color-surface-2);border-color:var(--color-brand-primary-900);color:var(--color-brand-primary-900)}.confirmPrimary{background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.confirmPrimary:hover:not(:disabled){background:var(--button-background-primary-bg-hover)}.confirmDanger{background:var(--color-attention-500);color:var(--background-bg-primary);border:none}.confirmDanger:hover:not(:disabled){background:var(--color-attention-600)}.confirmSuccess{background:var(--color-kiwi-700);color:var(--text-text-primaryon-brand)}.confirmWarning{background:var(--color-orange-500);color:var(--text-text-primaryon-brand)}.confirmInfo{background:var(--color-blue-700);color:var(--text-text-primaryon-brand)}\n"] }]
1685
1710
  }], ctorParameters: () => [], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], confirmDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmDisabled", required: false }] }], cancelDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelDisabled", required: false }] }], hideCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCancelButton", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], centerHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerHeader", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], hasBodySlot: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBodySlot", required: false }] }], onConfirmHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "onConfirmHandler", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], confirm: [{ type: i0.Output, args: ["confirm"] }] } });
1686
1711
 
1712
+ /** Design-system demo host that shows `sce-confirm-dialog` and reports its visibility back through `visibleChange`. */
1687
1713
  class SceConfirmDialogDemoComponent {
1688
1714
  visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
1689
1715
  visibleChange = output();
@@ -1810,6 +1836,7 @@ function defaultStrings(dir) {
1810
1836
  tooManyFiles: max => `Maximum ${max} files`,
1811
1837
  };
1812
1838
  }
1839
+ /** Drag-and-drop file picker with client-side accept/size/count validation and image previews; uploading is the consumer's job (it only emits `fileChange`/`filesChange`), it is not a ControlValueAccessor, and it uses `ViewEncapsulation.None`. */
1813
1840
  class SceFileUploadZoneComponent {
1814
1841
  translate = inject(TranslateService);
1815
1842
  // Inputs
@@ -2050,6 +2077,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2050
2077
  args: ['fileInput']
2051
2078
  }] } });
2052
2079
 
2080
+ /** Design-system demo page for `sce-file-upload-zone`, showing its zone and dialog variants under the `dir` passed in. */
2053
2081
  class SceFileUploadZoneDemoComponent {
2054
2082
  dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
2055
2083
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceFileUploadZoneDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -2129,6 +2157,7 @@ function hashLabel(label) {
2129
2157
  }
2130
2158
  return Math.abs(hash);
2131
2159
  }
2160
+ /** Maps a free-text Arabic or English status label to a tone by keyword match, falling back to one of eight stable hash-picked tones. */
2132
2161
  function resolveBusinessStatusTone(label) {
2133
2162
  const key = normalizeBusinessStatusKey(label ?? '');
2134
2163
  if (!key) {
@@ -2141,6 +2170,7 @@ function resolveBusinessStatusTone(label) {
2141
2170
  }
2142
2171
  return FALLBACK_TONES[hashLabel(key) % FALLBACK_TONES.length];
2143
2172
  }
2173
+ /** Resolves a label and its tone together, substituting `fallbackLabel` (an em dash by default) when the label is blank. */
2144
2174
  function resolveBusinessStatusPresentation(label, fallbackLabel = '—') {
2145
2175
  const resolved = (label ?? '').trim() || fallbackLabel;
2146
2176
  return {
@@ -2148,6 +2178,7 @@ function resolveBusinessStatusPresentation(label, fallbackLabel = '—') {
2148
2178
  tone: resolveBusinessStatusTone(resolved),
2149
2179
  };
2150
2180
  }
2181
+ /** Convenience wrapper over `resolveBusinessStatusPresentation` that returns the plain `{ label, tone }` shape table cells bind to. */
2151
2182
  function toBusinessStatusTableCell(label, fallbackLabel = '—') {
2152
2183
  const presentation = resolveBusinessStatusPresentation(label, fallbackLabel);
2153
2184
  return { label: presentation.label, tone: presentation.tone };
@@ -2189,6 +2220,7 @@ function businessStatusToneClassName(tone) {
2189
2220
  /**
2190
2221
  * React source: Moatamed-Frontend/src/shared-utils/components/tag/tag.tsx
2191
2222
  */
2223
+ /** Status pill rendering `label`; colour comes from `businessTone` when set and otherwise from `variant` (default `pending`), and it uses `ViewEncapsulation.None`. */
2192
2224
  class SceTagComponent {
2193
2225
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2194
2226
  variant = input('pending', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -2232,6 +2264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2232
2264
  args: [{ host: { class: 'sce-tag' }, selector: 'sce-tag', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"tag\" [class]=\"classes()\">{{ label() }}</span>\n", styles: ["@charset \"UTF-8\";.tag{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border-radius:var(--radius-full);border:0;font-weight:600;line-height:1.2;width:fit-content}.sizeSm,.sizeMd{padding-block:var(--space-4);padding-inline:var(--space-12);font-size:var(--font-size-xs)}.sizeLg{padding-block:var(--space-6);padding-inline:var(--space-14, var(--space-14));font-size:var(--font-size-md)}.variantPending{background:var(--color-yellow-100);color:var(--color-yellow-700)}.variantInProgress{background:var(--color-kiwi-100);color:var(--color-kiwi-700)}.variantInfo{background:var(--details-row-bg);color:var(--text-text-secondary-700)}.variantSuccess{background:var(--color-success-100);color:var(--color-success-700)}.variantInactive{background:var(--details-row-bg);color:var(--text-text-secondary-700)}.variantDanger{background:var(--color-red-100);color:var(--color-red-700)}.variantWarning{background:var(--color-yellow-100);color:var(--color-yellow-700)}.variantNeutral{background:var(--color-neutral-100);color:var(--color-neutral-700)}.variantPurple{background:var(--color-violet-100);color:var(--color-violet-800)}.variantAssigned{background:var(--color-blue-100);color:var(--color-blue-700)}.variantReview{background:var(--color-kiwi-100);color:var(--color-kiwi-700)}.variantNew{background:var(--color-info-100);color:var(--color-info-700)}.variantClosed{background:var(--color-neutral-200);color:var(--color-neutral-800)}.toneDraftInitial{background:var(--color-primary-100);color:var(--color-primary-800)}.toneModified{background:var(--color-info-100);color:var(--color-info-700)}.toneCancelled{background:var(--color-error-100);color:var(--color-error-700)}.toneClosed{background:var(--color-neutral-100);color:var(--color-neutral-600)}.toneReturnedEdit{background:var(--color-warning-100);color:var(--color-warning-700)}.toneActive{background:var(--color-success-100);color:var(--color-success-700)}.tonePendingBeneficiary{background:var(--color-warning-100);color:var(--color-warning-700)}.tonePendingApproval{background:var(--color-warning-100);color:var(--color-warning-800)}.toneRequestDraft{background:var(--color-info-100);color:var(--color-info-700)}.toneOpenOffers{background:var(--color-brand-secondary-100);color:var(--color-brand-secondary-800)}.toneExtended{background:var(--color-warning-100);color:var(--color-warning-700)}.toneRequestClosed{background:var(--color-neutral-100);color:var(--text-text-secondary-700)}.toneAwarded{background:var(--color-success-100);color:var(--color-success-800)}.toneRequestNew{background:var(--color-info-100);color:var(--color-info-700)}.toneRejected{background:var(--color-error-100);color:var(--color-attention-600)}.toneApproved{background:var(--color-success-100);color:var(--color-success-700)}.toneInvitationPublic{background:var(--color-primary-100);color:var(--text-text-brand-primary)}.toneInvitationDirect{background:var(--color-violet-100);color:var(--color-violet-800)}.toneFallback1{background:var(--color-info-50, var(--color-info-100));color:var(--color-brand-primary-800)}.toneFallback2{background:var(--color-pink-100);color:var(--color-pink-800)}.toneFallback3{background:var(--color-violet-100);color:var(--color-violet-800)}.toneFallback4{background:var(--color-warning-50, var(--color-warning-100));color:var(--color-warning-800)}.toneFallback5{background:var(--color-success-50, var(--color-success-100));color:var(--color-success-800)}.toneFallback6{background:var(--color-error-50, var(--color-error-100));color:var(--color-error-700)}.toneFallback7{background:var(--color-neutral-50);color:var(--color-violet-700)}.toneFallback8{background:var(--color-info-100);color:var(--color-info-800)}\n"] }]
2233
2265
  }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], businessTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "businessTone", required: false }] }], toneClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "toneClassName", required: false }] }] } });
2234
2266
 
2267
+ /** Status tag whose colour tone is inferred from the label text when `tone` is not supplied explicitly. */
2235
2268
  class SceBusinessStatusTagComponent {
2236
2269
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2237
2270
  tone = input(...(ngDevMode ? [undefined, { debugName: "tone" }] : /* istanbul ignore next */ []));
@@ -2248,6 +2281,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2248
2281
  args: [{ host: { class: 'sce-business-status-tag' }, selector: 'sce-business-status-tag', standalone: true, imports: [SceTagComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-tag [label]=\"label()\" [size]=\"size()\" [className]=\"toneClass()\" />\n", styles: [":host{display:block}.sce-business-status-tag{display:contents}\n"] }]
2249
2282
  }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
2250
2283
 
2284
+ /** Loading placeholder in one of several shape variants, optionally repeated `count` times with a shortened last line. */
2251
2285
  class SceSkeleton {
2252
2286
  /** Shape variant of the skeleton */
2253
2287
  variant = input('text', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -2320,6 +2354,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2320
2354
  args: [{ host: { class: 'sce-skeleton' }, selector: 'sce-skeleton', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe], template: "<div\n class=\"skeleton-container\"\n [class.skeleton-container--multi]=\"isMultiLine()\"\n [style]=\"containerStyles()\"\n role=\"status\"\n [attr.aria-label]=\"'ARIA.LOADING_CONTENT' | translate\"\n>\n @for (line of lines(); track line.index) {\n <span\n class=\"skeleton\"\n [class.skeleton--text]=\"variant() === 'text'\"\n [class.skeleton--circular]=\"variant() === 'circular'\"\n [class.skeleton--rectangular]=\"variant() === 'rectangular'\"\n [class.skeleton--rounded]=\"variant() === 'rounded'\"\n [class.skeleton--avatar]=\"variant() === 'avatar'\"\n [class.skeleton--button]=\"variant() === 'button'\"\n [class.skeleton--chip]=\"variant() === 'chip'\"\n [class.skeleton--card]=\"variant() === 'card'\"\n [class.skeleton--image]=\"variant() === 'image'\"\n [class.skeleton--header]=\"variant() === 'header'\"\n [class.skeleton--paragraph]=\"variant() === 'paragraph'\"\n [class.skeleton--divider]=\"variant() === 'divider'\"\n [class.skeleton--badge]=\"variant() === 'badge'\"\n [class.skeleton--input]=\"variant() === 'input'\"\n [class.skeleton--pulse]=\"animation() === 'pulse'\"\n [class.skeleton--wave]=\"animation() === 'wave'\"\n [class.skeleton--no-animation]=\"animation() === 'none'\"\n [class.skeleton--last]=\"line.isLast\"\n [style]=\"skeletonStyles()\"\n aria-hidden=\"true\"\n ></span>\n }\n <span class=\"sr-only\">{{ 'COMMON.LOADING' | translate }}</span>\n</div>\n", styles: [":host{display:block;--skeleton-bg: rgba(31, 42, 55, .08);--skeleton-wave-color-start: transparent;--skeleton-wave-color-mid-light: rgba(255, 255, 255, .35);--skeleton-wave-color-mid: rgba(255, 255, 255, .6);--skeleton-wave-color-mid-light-end: rgba(255, 255, 255, .35);--skeleton-wave-color-end: transparent;--skeleton-pulse-duration: 1.8s;--skeleton-pulse-opacity-min: .4;--skeleton-wave-duration: 2s;--skeleton-radius-xs: var(--radius-xs);--skeleton-radius-sm: var(--radius-md);--skeleton-radius-md: var(--radius-lg);--skeleton-radius-lg: var(--radius-lg);--skeleton-radius-full: 9999px;--skeleton-radius-circle: 50%;--skeleton-text-height: 1em;--skeleton-text-scale-y: .7;--skeleton-circular-size: 48px;--skeleton-rect-height: 120px;--skeleton-avatar-size: 40px;--skeleton-button-width: 120px;--skeleton-button-height: var(--space-40);--skeleton-chip-width: var(--space-72);--skeleton-chip-height: var(--space-28);--skeleton-card-height: 200px;--skeleton-image-height: 180px;--skeleton-header-width: 60%;--skeleton-header-height: 1.5em;--skeleton-paragraph-height: .9em;--skeleton-paragraph-scale-y: .8;--skeleton-divider-height: 1px;--skeleton-badge-width: var(--space-48);--skeleton-badge-height: var(--space-20);--skeleton-input-height: 44px;--skeleton-last-line-width: 65%}:host-context(html[data-theme=dark]){--skeleton-bg: rgba(255, 255, 255, .1);--skeleton-wave-color-mid-light: rgba(255, 255, 255, .06);--skeleton-wave-color-mid: rgba(255, 255, 255, .12);--skeleton-wave-color-mid-light-end: rgba(255, 255, 255, .06)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.skeleton-container{display:contents}.skeleton-container--multi{display:flex;flex-direction:column}.skeleton{display:block;background-color:var(--skeleton-bg);overflow:hidden;position:relative}.skeleton--text{width:100%;height:var(--skeleton-text-height);border-radius:var(--skeleton-radius-xs);transform-origin:0 55%;transform:scaleY(var(--skeleton-text-scale-y))}.skeleton--circular{width:var(--skeleton-circular-size);height:var(--skeleton-circular-size);border-radius:var(--skeleton-radius-circle);flex-shrink:0}.skeleton--rectangular{width:100%;height:var(--skeleton-rect-height);border-radius:0}.skeleton--rounded{width:100%;height:var(--skeleton-rect-height);border-radius:var(--skeleton-radius-md)}.skeleton--avatar{width:var(--skeleton-avatar-size);height:var(--skeleton-avatar-size);border-radius:var(--skeleton-radius-circle);flex-shrink:0}.skeleton--button{width:var(--skeleton-button-width);height:var(--skeleton-button-height);border-radius:var(--skeleton-radius-sm);flex-shrink:0}.skeleton--chip{display:inline-block;width:var(--skeleton-chip-width);height:var(--skeleton-chip-height);border-radius:var(--skeleton-radius-full);flex-shrink:0}.skeleton--card{width:100%;height:var(--skeleton-card-height);border-radius:var(--skeleton-radius-lg)}.skeleton--image{width:100%;height:var(--skeleton-image-height);border-radius:var(--skeleton-radius-md)}.skeleton--header{width:var(--skeleton-header-width);height:var(--skeleton-header-height);border-radius:var(--skeleton-radius-xs)}.skeleton--paragraph{width:100%;height:var(--skeleton-paragraph-height);border-radius:var(--skeleton-radius-xs);transform-origin:0 55%;transform:scaleY(var(--skeleton-paragraph-scale-y))}.skeleton--divider{width:100%;height:var(--skeleton-divider-height);border-radius:0}.skeleton--badge{display:inline-block;width:var(--skeleton-badge-width);height:var(--skeleton-badge-height);border-radius:var(--skeleton-radius-xs);flex-shrink:0}.skeleton--input{width:100%;height:var(--skeleton-input-height);border-radius:var(--skeleton-radius-sm)}.skeleton--last{width:var(--skeleton-last-line-width)}.skeleton--pulse{animation:skeleton-pulse var(--skeleton-pulse-duration) ease-in-out infinite}.skeleton--wave:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,var(--skeleton-wave-color-start) 0%,var(--skeleton-wave-color-mid-light) 30%,var(--skeleton-wave-color-mid) 50%,var(--skeleton-wave-color-mid-light-end) 70%,var(--skeleton-wave-color-end) 100%);animation:skeleton-wave var(--skeleton-wave-duration) ease-in-out infinite}.skeleton--no-animation{animation:none}.skeleton--no-animation:after{display:none}@keyframes skeleton-pulse{0%{opacity:1}50%{opacity:var(--skeleton-pulse-opacity-min)}to{opacity:1}}@keyframes skeleton-wave{0%{transform:translate(-100%)}50%{transform:translate(100%)}to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.skeleton--pulse{animation:none}.skeleton--wave:after{animation:none;display:none}}\n"] }]
2321
2355
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], animation: [{ type: i0.Input, args: [{ isSignal: true, alias: "animation", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], shrinkLastLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "shrinkLastLine", required: false }] }], aspectRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "aspectRatio", required: false }] }] } });
2322
2356
 
2357
+ /** Empty state with an illustration (or a tinted PrimeIcons circle when no `imageSrc` is given), a title and a subtitle, each settable as literal text or a translation key; the `error` tone announces assertively via `role="alert"` while every other tone stays a polite status. */
2323
2358
  class SceEmptyStateComponent {
2324
2359
  /** Translation key for the title (e.g. COMMON.NO_DATA). Used when title is not provided. */
2325
2360
  titleKey = input(...(ngDevMode ? [undefined, { debugName: "titleKey" }] : /* istanbul ignore next */ []));
@@ -2588,6 +2623,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2588
2623
 
2589
2624
  const IGNORED_ROW_ACTIVATION_TAGS = new Set(['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA', 'LABEL']);
2590
2625
  const IGNORED_ROW_ACTIVATION_ROLES = new Set(['button', 'link', 'switch', 'checkbox', 'menuitem']);
2626
+ /** Data table driven by `columns` and `rows`, with sorting, client- or server-side pagination, status/switch cells, and row actions; its empty body reads differently depending on `error`, `searching`, and `filtered`, and it uses `ViewEncapsulation.None`. */
2591
2627
  class SceGenericTableComponent {
2592
2628
  messageService = inject(MessageService);
2593
2629
  translate = inject(TranslateService);
@@ -2919,6 +2955,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2919
2955
  ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tableWrapper\">\n <div class=\"tableScroll\">\n <table class=\"table\" [attr.aria-busy]=\"resolvedLoading() ? 'true' : null\">\n <thead>\n <tr>\n @for (col of columnViews(); track col.field) {\n <th [style.text-align]=\"col.align ?? (col.isActionColumn ? 'center' : null)\">\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"sortHeaderButton\"\n [class.sortHeaderButtonActive]=\"col.isSortActive\"\n [style.justify-content]=\"col.align === 'center' ? 'center' : col.align === 'end' ? 'flex-end' : 'space-between'\"\n [style.gap]=\"col.align === 'center' ? '8px' : null\"\n [style.margin]=\"col.align === 'center' ? '0 auto' : col.isActionColumn ? '0 auto' : null\"\n (click)=\"onSortClick(col)\"\n >\n @if (col.isSortActive) {\n <i\n class=\"pi sortIconActive\"\n [class.pi-arrow-down]=\"sort()?.orderBy === 2\"\n [class.pi-arrow-up]=\"sort()?.orderBy !== 2\"\n aria-hidden=\"true\"\n ></i>\n } @else {\n <img src=\"/assets/icons/sort.svg\" width=\"16\" height=\"16\" class=\"sortIcon\" aria-hidden=\"true\" alt=\"\" />\n }\n <span>{{ col.header }}</span>\n </button>\n } @else {\n {{ col.header }}\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (resolvedLoading()) {\n @for (row of skeletonRows(); track row) {\n <tr class=\"skeletonRow\">\n @for (col of columnViews(); track col.field) {\n <td class=\"skeletonCell\" [style.text-align]=\"col.align ?? (col.isActionColumn ? 'center' : null)\">\n @if (col.isActionColumn) {\n <sce-skeleton variant=\"rounded\" width=\"2rem\" height=\"2rem\" borderRadius=\"var(--radius-lg)\" animation=\"wave\" />\n } @else if (isStatusColumn(col.field)) {\n <sce-skeleton variant=\"chip\" width=\"5.5rem\" height=\"1.5rem\" animation=\"wave\" />\n } @else {\n <sce-skeleton variant=\"text\" [width]=\"col.skeletonWidth\" height=\"0.875rem\" animation=\"wave\" />\n }\n </td>\n }\n </tr>\n }\n } @else if (error() || rows().length === 0) {\n <tr class=\"placeholderRow\">\n <td [attr.colspan]=\"columns().length\" class=\"placeholderCell\">\n <sce-result-state\n [status]=\"bodyStatus()\"\n [titleKey]=\"bodyTitleKey()\"\n [subtitleKey]=\"bodySubtitleKey()\"\n [imageSrc]=\"bodyImage()\"\n [iconSize]=\"bodyIconSize()\"\n [actions]=\"bodyActions()\"\n (retry)=\"errorRetry.emit()\"\n (clearFilters)=\"clearFilters.emit()\"\n (clearSearch)=\"clearSearch.emit()\"\n />\n </td>\n </tr>\n } @else {\n @for (rowView of rowViews(); track rowView.row.id) {\n <tr\n [class.linkedRow]=\"rowView.row.rowHref\"\n [class.clickableRow]=\"!rowView.row.rowHref\"\n [tabindex]=\"!rowView.row.rowHref ? 0 : null\"\n (click)=\"onRowActivate(rowView.row, $any($event))\"\n (keydown.enter)=\"onRowActivate(rowView.row, $any($event))\"\n >\n @for (cellView of rowView.cells; track cellView.col.field; let colIndex = $index) {\n <td\n class=\"dataCell\"\n [class.hasLink]=\"rowView.row.rowHref\"\n [style.text-align]=\"cellView.col.align ?? (cellView.col.isActionColumn ? 'center' : null)\"\n [style.justify-content]=\"cellView.col.align === 'center' ? 'center' : cellView.col.align === 'end' ? 'flex-end' : null\"\n >\n @if (rowView.row.rowHref && !cellView.col.isActionColumn && !cellView.isSwitch) {\n <a [href]=\"rowView.row.rowHref\" class=\"rowCellLink\" data-row-nav-link tabindex=\"-1\" aria-hidden=\"true\"></a>\n }\n @if (cellView.isSwitch) {\n @let switchCell = $any(cellView.value);\n <sce-switch\n [checked]=\"switchCell.checked\"\n [disabled]=\"switchCell.disabled ?? false\"\n [showLabel]=\"true\"\n [activeLabel]=\"switchCell.activeLabel ?? ''\"\n [inactiveLabel]=\"switchCell.inactiveLabel ?? ''\"\n (checkedChange)=\"onSwitchChange(switchCell.rowId, cellView.col.field, $event); ($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n } @else if (isStatusCell(cellView.value)) {\n @if (cellView.value.tone !== undefined || cellView.value.variant === undefined) {\n <sce-business-status-tag [label]=\"cellView.value.label\" [tone]=\"cellView.value.tone\" size=\"sm\" />\n } @else {\n <sce-tag [label]=\"cellView.value.label\" [variant]=\"cellView.value.variant!\" size=\"sm\" />\n }\n } @else if (cellView.col.isActionColumn) {\n @if (rowView.hasRowActions) {\n <div class=\"rowActionsCell\">\n @if (rowView.canEdit) {\n <button\n type=\"button\"\n class=\"rowActionBtn rowActionBtnEdit\"\n (click)=\"$event.stopPropagation(); editClick.emit(rowView.row)\"\n [attr.aria-label]=\"'table.edit' | translate\"\n >\n <i class=\"pi pi-pencil\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (rowView.canDelete) {\n <button\n type=\"button\"\n class=\"rowActionBtn rowActionBtnDelete\"\n (click)=\"$event.stopPropagation(); deleteClick.emit(rowView.row)\"\n [attr.aria-label]=\"'table.delete' | translate\"\n >\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n } @else {\n <i\n class=\"pi actionChevron\"\n [class.pi-chevron-left]=\"locale() === 'ar'\"\n [class.pi-chevron-right]=\"locale() === 'en'\"\n aria-hidden=\"true\"\n ></i>\n }\n } @else if (colIndex === 0 && rowView.row.rowHref) {\n @if (cellView.copyText) {\n <span class=\"copyCell\">\n <a [href]=\"rowView.row.rowHref\" class=\"rowPrimaryLink\" data-row-nav-link>\n <span class=\"copyCellValue\">{{ cellView.text }}</span>\n </a>\n <button\n type=\"button\"\n class=\"copyBtn\"\n [class.copyBtnCopied]=\"copiedCellKey() === rowView.row.id + '-' + cellView.col.field\"\n data-row-click-ignore\n [attr.aria-label]=\"'table.copy.ariaLabel' | translate\"\n (click)=\"$event.stopPropagation(); copyToClipboard(cellView.copyText!, rowView.row.id + '-' + cellView.col.field)\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n </button>\n </span>\n } @else {\n <a [href]=\"rowView.row.rowHref\" class=\"rowPrimaryLink\" data-row-nav-link>\n {{ cellView.text }}\n </a>\n }\n } @else {\n @if (cellView.copyText) {\n <span class=\"copyCell\">\n <span class=\"copyCellValue\">{{ cellView.text }}</span>\n <button\n type=\"button\"\n class=\"copyBtn\"\n [class.copyBtnCopied]=\"copiedCellKey() === rowView.row.id + '-' + cellView.col.field\"\n data-row-click-ignore\n [attr.aria-label]=\"'table.copy.ariaLabel' | translate\"\n (click)=\"$event.stopPropagation(); copyToClipboard(cellView.copyText!, rowView.row.id + '-' + cellView.col.field)\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n </button>\n </span>\n } @else {\n {{ cellView.text }}\n }\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n @if (paginationEnabled() && resolvedLoading()) {\n <div class=\"paginationWrap paginationWrap--skeleton\" aria-hidden=\"true\">\n <sce-skeleton variant=\"text\" width=\"8rem\" height=\"2.25rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"12rem\" height=\"2.25rem\" animation=\"wave\" />\n </div>\n } @else if (paginationEnabled()) {\n <div class=\"paginationWrap\">\n <sce-paginator\n [page]=\"resolvedPage()\"\n [pageSize]=\"resolvedPageSize()\"\n [totalItems]=\"totalItems()\"\n [locale]=\"locale()\"\n [pageSizeOptions]=\"pagination()?.pageSizeOptions ?? [4, 8, 12, 16]\"\n [showLabel]=\"pagination()?.showLabel\"\n (pageChange)=\"onPaginatorPageChange($event)\"\n (pageSizeChange)=\"onPaginatorPageSizeChange($event)\"\n />\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.tableWrapper{background:var(--app-surface);border-radius:var(--space-16);display:flex;flex-direction:column;overflow:hidden}.paginationWrap{margin-block-start:var(--space-16)}.tableScroll{overflow-x:auto;overflow-y:hidden;min-width:0;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--color-neutral-300) var(--color-neutral-100)}.tableScroll::-webkit-scrollbar{height:var(--space-10)}.tableScroll::-webkit-scrollbar-track{background:var(--color-neutral-100);border-radius:var(--radius-10)}.tableScroll::-webkit-scrollbar-thumb{background-color:var(--color-neutral-300);border-radius:var(--radius-10)}html[dir=rtl] .tableScroll{direction:rtl}.tableFooter{flex-shrink:0;margin-block-start:var(--space-16);padding-inline:var(--space-16);padding-block-end:var(--space-16);width:100%;box-sizing:border-box}.paginationWrap--skeleton{display:flex;align-items:center;justify-content:space-between;gap:var(--space-12);padding-inline:var(--space-16);min-height:var(--space-44)}.table tbody tr.skeletonRow{background:transparent;border-block-end:1px solid var(--card-border-subtle);pointer-events:none;min-height:4.5rem}.table tbody tr.skeletonRow:hover{background:transparent}.table tbody td.skeletonCell{vertical-align:middle;padding:var(--space-24) 2rem}.table tbody td.skeletonCell:last-child{display:table-cell}.table tbody td.skeletonCell sce-skeleton{display:block;max-width:100%}.loadingState{min-height:var(--size-280);display:flex;align-items:center;justify-content:center;padding:var(--space-24)}.emptyState{min-height:var(--size-280);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:var(--space-12);text-align:center;padding:var(--space-24)}.emptyTitle{margin:0;font-family:var(--font-family-text);font-weight:600;font-size:var(--typo-size-text-lg);color:var(--text-text-display)}.emptySubtitle{margin:0;font-family:var(--font-family-text);font-weight:400;font-size:var(--typo-size-text-md);color:var(--text-text-secondary-paragraph)}.table{width:100%;min-width:max-content;border-collapse:collapse}.table thead{background:var(--color-neutral-100)}.table thead th{padding:var(--space-20) 1.75rem;text-align:start;color:var(--form-field-text-placeholder);font-weight:600;font-size:var(--font-size-xs);white-space:nowrap}.sortHeaderButton{border:0;background:transparent;display:inline-flex;align-items:center;gap:var(--space-6);color:inherit;font:inherit;cursor:pointer;padding:0;width:100%;justify-content:space-between;flex-direction:row-reverse}.sortHeaderButtonActive{color:var(--text-text-brand-primary)}.sortIcon{opacity:.7;transition:opacity .2s ease}.sortIconActive{opacity:1;font-size:var(--font-size-md);color:var(--text-text-brand-primary)}.table tbody tr{border-block-end:1px solid var(--card-border-subtle);transition:background-color .3s ease}.table tbody tr:hover{background:var(--table-row-hover)}.clickableRow{cursor:pointer}.linkedRow{position:relative;cursor:pointer}.dataCell .copyCell{position:relative;z-index:2;display:flex;align-items:center;width:100%;min-height:100%;gap:var(--space-6)}.dataCell .copyCell .rowPrimaryLink{flex:1;min-width:0}.dataCell .copyBtn{position:relative;z-index:3}.rowCellLink{position:absolute;inset:0;z-index:1}.rowPrimaryLink{position:relative;z-index:2;display:inline-flex;align-items:center;max-width:100%;color:inherit;font:inherit;font-weight:inherit;text-decoration:none}.rowPrimaryLink:hover{color:var(--text-text-brand-primary);text-decoration:underline}.cellContent{position:relative;z-index:2;pointer-events:none}.cellContent,.cellContent *{pointer-events:none}.cellContent :is(button,a,input,select,textarea,[role=switch],[data-row-click-ignore]){pointer-events:auto}.table tbody td{padding:var(--space-24) 2rem;color:var(--color-text-heading-700);font-size:var(--font-size-md);text-align:start;font-weight:500}.table tbody td:last-child{display:flex;align-items:center;justify-content:flex-start}.table tbody td.dataCell:last-child{display:table-cell}.copyCell{display:inline-flex;align-items:center;gap:var(--space-6);max-width:100%;min-width:0}.copyCellValue{min-width:0}.copyBtn{display:inline-flex;align-items:center;justify-content:center;width:var(--space-24);height:var(--space-24);flex-shrink:0;border:0;border-radius:var(--space-6);background:transparent;color:var(--form-field-text-placeholder);cursor:pointer;opacity:0;transition:opacity .15s ease,color .15s ease,background-color .15s ease}.cellContent .copyCell{position:relative;z-index:2}.copyCell:hover .copyBtn,.copyCell:focus-within .copyBtn,.dataCell:hover .copyBtn{opacity:1}.copyBtn:hover{color:var(--text-text-brand-primary);background:var(--surface-overlay-soft)}.copyBtnCopied{opacity:1;color:var(--text-text-brand-primary)}@media(hover:none){.copyBtn{opacity:1}}.table tbody tr.placeholderRow{background:transparent;border-block-end:0}.table tbody tr.placeholderRow:hover{background:transparent}.table tbody .placeholderRow td.placeholderCell,.table tbody .placeholderRow td.placeholderCell:last-child{display:table-cell;padding:0;text-align:center}.dataCell{position:relative}.rowCellLink{position:absolute;inset:0;z-index:1;opacity:0;cursor:pointer}.dataCell.hasLink{position:relative}.actionChevron{font-size:var(--font-size-md);color:var(--text-text-secondary-600);transition:transform .2s ease,color .2s ease}.clickableRow:hover .actionChevron,.linkedRow:hover .actionChevron{color:var(--text-text-brand-primary, var(--color-brand-primary-600));transform:scale(1.1)}.rowActionsCell{display:flex;align-items:center;justify-content:center;gap:var(--space-2, .5rem)}.rowActionBtn{display:inline-flex;align-items:center;justify-content:center;width:var(--space-32);height:var(--space-32);border-radius:var(--radius-md, .5rem);border:1px solid transparent;background:transparent;cursor:pointer;transition:background .15s ease,color .15s ease;color:var(--text-text-secondary-600)}.rowActionBtn:hover{background:var(--color-neutral-100, var(--color-neutral-100));color:var(--text-text-primary-900)}.rowActionBtn.rowActionBtnDelete{color:var(--text-text-error-primary, var(--color-attention-600))}.rowActionBtn.rowActionBtnDelete:hover{background:var(--color-error-50, var(--color-error-50));color:var(--color-error-600, var(--color-error-600))}\n"] }]
2920
2956
  }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], loadingDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingDelay", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], errorStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStatus", required: false }] }], filtered: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtered", required: false }] }], searching: [{ type: i0.Input, args: [{ isSignal: true, alias: "searching", required: false }] }], errorRetry: [{ type: i0.Output, args: ["errorRetry"] }], clearFilters: [{ type: i0.Output, args: ["clearFilters"] }], clearSearch: [{ type: i0.Output, args: ["clearSearch"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], switchChange: [{ type: i0.Output, args: ["switchChange"] }], editClick: [{ type: i0.Output, args: ["editClick"] }], deleteClick: [{ type: i0.Output, args: ["deleteClick"] }] } });
2921
2957
 
2958
+ /** Design-system demo harness for `sce-generic-table` with three hard-coded rows; its columns and rows re-translate whenever `LanguageService.locale()` changes. */
2922
2959
  class SceGenericTableDemoComponent {
2923
2960
  translate = inject(TranslateService);
2924
2961
  language = inject(LanguageService);
@@ -2964,6 +3001,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2964
3001
 
2965
3002
  /** Simple in-memory SVG cache shared across all SceIcon instances. */
2966
3003
  const svgCache = new Map();
3004
+ /** Inline SVG icon that fetches the named asset over HTTP, sanitizes it and caches it in a module-level cache shared by all instances. */
2967
3005
  class SceIcon {
2968
3006
  http = inject(HttpClient);
2969
3007
  sanitizer = inject(DomSanitizer);
@@ -3025,6 +3063,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3025
3063
  args: [{ selector: 'sce-icon', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-icon', '[style.width.px]': 'widthPx()', '[style.height.px]': 'heightPx()' }, template: "@if (iconSrc()) {\n <span class=\"sce-icon\" [class]=\"'sce-icon ' + (name() || '')\" [innerHTML]=\"svgContent()\"></span>\n}\n", styles: [":host{display:block;display:inline-flex;align-items:center;justify-content:center;width:100%;height:100%}.sce-icon{display:flex;width:100%;height:100%;align-items:center;justify-content:center}.sce-icon ::ng-deep svg{flex-grow:1;width:100%;height:100%;color:inherit}\n"] }]
3026
3064
  }], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
3027
3065
 
3066
+ /** Verified/unverified badge icon derived from an engineering office's service-provider status. */
3028
3067
  class SceEngineeringOfficeVerificationBadgeComponent {
3029
3068
  status = input(...(ngDevMode ? [undefined, { debugName: "status" }] : /* istanbul ignore next */ []));
3030
3069
  size = input(24, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
@@ -3077,6 +3116,7 @@ function isOfficeBrandPhotoSrc(src) {
3077
3116
  function officeImageNeedsUnoptimized(src) {
3078
3117
  return (src.startsWith('/images/') || src.startsWith('/api/cms/media') || src.startsWith('blob:') || src.startsWith('data:'));
3079
3118
  }
3119
+ /** Circular office logo that renders uploaded photos with `object-fit: cover` and bundled SVGs with `contain`, falling back to the default office icon when the source is empty or fails to load. */
3080
3120
  class SceOfficeBrandLogoComponent {
3081
3121
  /** Logo source. http(s)/CMS/blob/data render as photo; anything else as bundled icon. */
3082
3122
  src = input('', ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
@@ -3106,6 +3146,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3106
3146
  /**
3107
3147
  * React source: feedback/inline-api-error.tsx
3108
3148
  */
3149
+ /** Inline error banner for an already-resolved `message`, showing a retry button only when `retryable` is opted into (it defaults to false so a failed save cannot re-trigger a load). */
3109
3150
  class SceInlineApiErrorComponent {
3110
3151
  message = input.required(...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
3111
3152
  className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
@@ -3170,6 +3211,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3170
3211
  /**
3171
3212
  * React source: Moatamed-Frontend/src/shared-utils/components/notifications/notification-type-badge.tsx
3172
3213
  */
3214
+ /** Small pill showing a notification's kind: renders the already-translated `label` styled by `variant` (default `info`), with extra classes from `className`; uses `ViewEncapsulation.None`. */
3173
3215
  class SceNotificationTypeBadgeComponent {
3174
3216
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
3175
3217
  variant = input('info', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -3235,6 +3277,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3235
3277
  }, template: "@if (value(); as text) {\n <bdi class=\"sce-bidi-isolate__run\" [class.sce-bidi-isolate__run--tabular]=\"tabular()\" [attr.dir]=\"dir()\">{{ text }}</bdi>\n} @else {\n <bdi class=\"sce-bidi-isolate__run\" [class.sce-bidi-isolate__run--tabular]=\"tabular()\" [attr.dir]=\"dir()\"><ng-content /></bdi>\n}\n", styles: ["@charset \"UTF-8\";:host{display:inline}.sce-bidi-isolate__run{unicode-bidi:isolate}.sce-bidi-isolate__run--tabular{font-variant-numeric:tabular-nums lining-nums}\n"] }]
3236
3278
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], tabular: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabular", required: false }] }] } });
3237
3279
 
3280
+ /** Read-only label/value card used throughout profile and review screens, with default, highlight and editable variants. */
3238
3281
  class SceInfoFieldCardComponent {
3239
3282
  label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
3240
3283
  value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
@@ -3260,6 +3303,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3260
3303
  args: [{ host: { class: 'sce-info-field-card' }, selector: 'sce-info-field-card', standalone: true, imports: [SceBidiIsolate], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"cardClasses()\">\n @if (label() != null) {\n <p class=\"label\" [class]=\"labelClassName() ?? ''\">{{ label() }}</p>\n }\n @if (value() != null) {\n <p class=\"value\" [class]=\"valueClassName() ?? ''\">\n <!--\n Isolated because this card is the sink for licence, VAT, IBAN, CR, national-ID, phone,\n and email values, which are Latin runs sitting inside an Arabic-direction card. `dir=\"auto\"`\n leaves Arabic values untouched, so isolation here is unconditionally safe.\n -->\n <sce-bidi-isolate [value]=\"value()\" />\n </p>\n }\n <ng-content />\n</div>\n", styles: ["@charset \"UTF-8\";.card{display:flex;flex-direction:column;gap:var(--space-8);min-width:0;min-height:var(--space-72);padding:var(--space-16);border-radius:var(--space-12);background:var(--app-surface-hover);box-sizing:border-box}.cardHighlight{background:var(--color-base-white)}.cardEditable{background:var(--color-surface);border:1px solid var(--color-neutral-200);cursor:text}.cardCompact{min-height:auto;padding:var(--space-10) var(--space-12);gap:var(--space-4);border-radius:var(--space-8)}.label{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--details-label-weight);font-size:var(--details-label-size);color:var(--details-label-color);text-align:start}.cardHighlight .label{color:var(--color-warning-600)}.cardCompact .label{font-weight:500;font-size:var(--font-size-xs);color:var(--text-text-secondary-700)}.cardHighlight.cardCompact .label{color:var(--color-warning-600)}.value{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--details-value-weight);font-size:var(--details-value-size);color:var(--details-value-color);text-align:start;overflow-wrap:break-word}.cardCompact .value{font-weight:600;font-size:var(--font-size-sm);color:var(--text-text-primary-900)}.grid{display:grid;width:100%;box-sizing:border-box;gap:var(--space-20);grid-template-columns:repeat(2,minmax(0,1fr))}.gridGapSm{gap:var(--space-12)}.columns1{grid-template-columns:1fr}.columns3{grid-template-columns:repeat(3,minmax(0,1fr))}.columns4{grid-template-columns:repeat(4,minmax(0,1fr))}sce-info-field-card:has(.fullWidth){grid-column:1/-1}.fullWidth{grid-column:1/-1}@media(max-width:640px){.grid:not(.columns1){grid-template-columns:1fr}.card{padding:var(--space-14)}.label,.value{text-align:start;overflow-wrap:anywhere}}@media(max-width:992px){.grid.columns3,.grid.columns4{grid-template-columns:1fr}}\n"] }]
3261
3304
  }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], labelClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClassName", required: false }] }], valueClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueClassName", required: false }] }] } });
3262
3305
 
3306
+ /** Layout wrapper that arranges projected info-field cards into a one- to four-column grid. */
3263
3307
  class SceInfoFieldsGridComponent {
3264
3308
  columns = input(2, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
3265
3309
  gap = input('default', ...(ngDevMode ? [{ debugName: "gap" }] : /* istanbul ignore next */ []));
@@ -3370,6 +3414,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3370
3414
  args: [{ host: { class: 'sce-public-legal-prose' }, selector: 'sce-public-legal-prose', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div #root [class]=\"rootClass()\" [attr.dir]=\"rootDir()\" [innerHTML]=\"sanitizedHtml()\"></div>\n", styles: [".sce-public-legal-prose{display:contents}\n"] }]
3371
3415
  }], ctorParameters: () => [], propDecorators: { html: [{ type: i0.Input, args: [{ isSignal: true, alias: "html", required: true }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], root: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }] } });
3372
3416
 
3417
+ /** Table row-action affordance rendering the chevron icon with `alt` as its accessible text; uses `ViewEncapsulation.None`, so its styles are global. */
3373
3418
  class SceRowActionIconComponent {
3374
3419
  alt = input('', ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
3375
3420
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceRowActionIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -3381,6 +3426,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3381
3426
  }], propDecorators: { alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }] } });
3382
3427
 
3383
3428
  const DEFAULT_CLIENT_AVATAR = '/assets/images/Avatar.png';
3429
+ /** Avatar/role icon for a dashboard account; the supplied `photoUrl` is only used for individual client accounts, everything else falls back to the role icon. */
3384
3430
  class SceDashboardAccountRoleIconComponent {
3385
3431
  role = input('client', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
3386
3432
  accountKind = input(...(ngDevMode ? [undefined, { debugName: "accountKind" }] : /* istanbul ignore next */ []));
@@ -3407,6 +3453,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3407
3453
  args: [{ host: { class: 'sce-dashboard-account-role-icon' }, selector: 'sce-dashboard-account-role-icon', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (role()) {\n @case ('manager') {\n <span class=\"iconContainerManager\">\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M12 15a7 7 0 1 0 0-14 7 7 0 0 0 0 14z\" />\n <path d=\"m19.4 15-1.2 5.4a2 2 0 0 1-2 1.6H7.8a2 2 0 0 1-2-1.6L4.6 15\" />\n </svg>\n </span>\n }\n @case ('entity') {\n <span class=\"iconContainerEntity\">\n <svg\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z\" />\n <path d=\"M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2\" />\n <path d=\"M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2\" />\n <path d=\"M10 6h4\" />\n <path d=\"M10 10h4\" />\n <path d=\"M10 14h4\" />\n <path d=\"M10 18h4\" />\n </svg>\n </span>\n }\n @case ('office') {\n <span class=\"iconContainerOffice\">\n <img src=\"/assets/images/Avatar-1.png\" alt=\"\" class=\"officeAvatarImage\" />\n </span>\n }\n @default {\n @if (showClientPhoto()) {\n <img [src]=\"photoUrl() ?? defaultAvatar\" [alt]=\"alt()\" class=\"accountIconImage\" [width]=\"width()\" [height]=\"height()\" />\n } @else {\n <span class=\"iconContainerClient\">\n <svg\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\" />\n <circle cx=\"12\" cy=\"7\" r=\"4\" />\n </svg>\n </span>\n }\n }\n}\n", styles: ["sce-dashboard-account-role-icon{display:inline-flex;align-items:center;justify-content:center}.accountIconImage{width:auto;height:auto;border-radius:var(--radius-full);object-fit:cover}.iconContainerManager,.iconContainerEntity,.iconContainerOffice{display:flex;align-items:center;justify-content:center;width:var(--space-40);height:var(--space-40);border-radius:var(--radius-full)}.iconContainerManager{background:var(--surface-accent-brand);color:var(--background-bg-primary)}.iconContainerEntity{background:var(--color-info-100);color:var(--text-text-primary-900)}.iconContainerOffice{background:var(--surface-muted);overflow:hidden}.iconContainerClient{display:flex;align-items:center;justify-content:center;width:var(--space-40);height:var(--space-40);border-radius:var(--radius-full);background:var(--surface-muted);color:var(--text-text-secondary-700)}.officeAvatarImage{width:100%;height:100%;object-fit:cover}\n"] }]
3408
3454
  }], propDecorators: { role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], accountKind: [{ type: i0.Input, args: [{ isSignal: true, alias: "accountKind", required: false }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }], photoUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "photoUrl", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
3409
3455
 
3456
+ /** Panel rendering a list of label/value review fields as table rows, skipping any item marked `hidden`. */
3410
3457
  class SceReviewFieldTablePanelComponent {
3411
3458
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
3412
3459
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceReviewFieldTablePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -3506,6 +3553,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3506
3553
  args: [{ host: { class: 'sce-engineering-office-card' }, selector: 'sce-engineering-office-card', standalone: true, imports: [RouterLink, SceEngineeringOfficeVerificationBadgeComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (office().href) {\n <a [routerLink]=\"office().href\" [class]=\"wrapperClass()\">\n <div [class]=\"viewMode() === 'list' ? 'mediaList' : 'media'\">\n @if (showCoverSkeleton()) {\n <div class=\"mediaSkeleton\" aria-hidden=\"true\"></div>\n }\n @if (office().imageSrc || office().heroObjectUrl) {\n <img\n [src]=\"office().imageSrc || office().heroObjectUrl\"\n [alt]=\"office().imageAlt\"\n class=\"mediaImg\"\n [class.mediaImgLoaded]=\"coverLoaded()\"\n [class.mediaImgLoading]=\"!coverLoaded()\"\n (load)=\"onCoverLoad()\"\n />\n }\n @if (bookmarkLabel()) {\n <button\n type=\"button\"\n class=\"bookmark\"\n [class.bookmarkActive]=\"bookmarked()\"\n [attr.aria-label]=\"bookmarkLabel()\"\n [attr.aria-pressed]=\"bookmarked()\"\n (click)=\"onBookmarkClick($event)\"\n >\n <img class=\"bookmarkIcon\" src=\"/assets/icons/bookmark-add-02.svg\" alt=\"\" aria-hidden=\"true\" />\n </button>\n }\n <div class=\"logo\" aria-hidden=\"true\">\n <div class=\"logoInner\">\n @if (showLogoSkeleton()) {\n <div class=\"logoPlaceholderSkeleton\" aria-hidden=\"true\"></div>\n }\n @if (office().logoSrc || office().logoObjectUrl) {\n <img\n [src]=\"office().logoSrc || office().logoObjectUrl\"\n alt=\"\"\n class=\"logoPhoto\"\n [class.logoPhotoLoaded]=\"logoLoaded()\"\n [class.logoPhotoLoading]=\"!logoLoaded()\"\n (load)=\"onLogoLoad()\"\n />\n }\n </div>\n </div>\n </div>\n\n <div class=\"body\">\n <div class=\"nameRow\">\n <div class=\"name\">{{ office().name }}</div>\n @if (office().verified) {\n <sce-engineering-office-verification-badge [status]=\"VerifiedStatus\" [size]=\"16\" className=\"verifiedIcon\" />\n }\n </div>\n\n <div class=\"tags\" tabindex=\"0\">\n @for (tag of office().tags; track tag) {\n <span class=\"tag\">{{ tag }}</span>\n }\n @if (office().extraTagsCount > 0) {\n <span class=\"tag\">{{ office().extraTagsCount }} {{ otherLabel() }}</span>\n }\n </div>\n\n <div class=\"meta\">\n <div class=\"metaItem\">\n <span class=\"metaLabel\">{{ ratingLabel() }}</span>\n <span class=\"metaValue\">\n <img class=\"metaIcon\" src=\"/assets/icons/star-rating.svg\" alt=\"\" aria-hidden=\"true\" />\n <span>{{ office().ratingValue }}</span>\n <span class=\"ratingCount\">{{ office().ratingCount }}</span>\n </span>\n </div>\n <div class=\"metaItem\">\n <span class=\"metaLabel\">{{ locationLabel() }}</span>\n <span class=\"metaValue\">\n <img class=\"metaIcon\" src=\"/assets/icons/location.svg\" alt=\"\" aria-hidden=\"true\" />\n <span>{{ office().location }}</span>\n </span>\n </div>\n </div>\n </div>\n </a>\n} @else {\n <article [class]=\"wrapperClass()\">\n <div [class]=\"viewMode() === 'list' ? 'mediaList' : 'media'\">\n @if (showCoverSkeleton()) {\n <div class=\"mediaSkeleton\" aria-hidden=\"true\"></div>\n }\n @if (office().imageSrc || office().heroObjectUrl) {\n <img\n [src]=\"office().imageSrc || office().heroObjectUrl\"\n [alt]=\"office().imageAlt\"\n class=\"mediaImg\"\n [class.mediaImgLoaded]=\"coverLoaded()\"\n [class.mediaImgLoading]=\"!coverLoaded()\"\n (load)=\"onCoverLoad()\"\n />\n }\n @if (bookmarkLabel()) {\n <button\n type=\"button\"\n class=\"bookmark\"\n [class.bookmarkActive]=\"bookmarked()\"\n [attr.aria-label]=\"bookmarkLabel()\"\n [attr.aria-pressed]=\"bookmarked()\"\n (click)=\"onBookmarkClick($event)\"\n >\n <img class=\"bookmarkIcon\" src=\"/assets/icons/bookmark-add-02.svg\" alt=\"\" aria-hidden=\"true\" />\n </button>\n }\n <div class=\"logo\" aria-hidden=\"true\">\n <div class=\"logoInner\">\n @if (showLogoSkeleton()) {\n <div class=\"logoPlaceholderSkeleton\" aria-hidden=\"true\"></div>\n }\n @if (office().logoSrc || office().logoObjectUrl) {\n <img\n [src]=\"office().logoSrc || office().logoObjectUrl\"\n alt=\"\"\n class=\"logoPhoto\"\n [class.logoPhotoLoaded]=\"logoLoaded()\"\n [class.logoPhotoLoading]=\"!logoLoaded()\"\n (load)=\"onLogoLoad()\"\n />\n }\n </div>\n </div>\n </div>\n\n <div class=\"body\">\n <div class=\"nameRow\">\n <div class=\"name\">{{ office().name }}</div>\n @if (office().verified) {\n <sce-engineering-office-verification-badge [status]=\"VerifiedStatus\" [size]=\"16\" className=\"verifiedIcon\" />\n }\n </div>\n\n <div class=\"tags\" tabindex=\"0\">\n @for (tag of office().tags; track tag) {\n <span class=\"tag\">{{ tag }}</span>\n }\n @if (office().extraTagsCount > 0) {\n <span class=\"tag\">{{ office().extraTagsCount }} {{ otherLabel() }}</span>\n }\n </div>\n\n <div class=\"meta\">\n <div class=\"metaItem\">\n <span class=\"metaLabel\">{{ ratingLabel() }}</span>\n <span class=\"metaValue\">\n <img class=\"metaIcon\" src=\"/assets/icons/star-rating.svg\" alt=\"\" aria-hidden=\"true\" />\n <span>{{ office().ratingValue }}</span>\n <span class=\"ratingCount\">{{ office().ratingCount }}</span>\n </span>\n </div>\n <div class=\"metaItem\">\n <span class=\"metaLabel\">{{ locationLabel() }}</span>\n <span class=\"metaValue\">\n <img class=\"metaIcon\" src=\"/assets/icons/location.svg\" alt=\"\" aria-hidden=\"true\" />\n <span>{{ office().location }}</span>\n </span>\n </div>\n </div>\n </div>\n </article>\n}\n", styles: ["@charset \"UTF-8\";sce-engineering-office-card-skeleton,sce-engineering-office-card{display:block}sce-engineering-office-card-skeleton .card,sce-engineering-office-card .card{width:100%;min-height:var(--size-320);border-radius:var(--radius-brand-sm);padding:var(--space-18);background:var(--surface-primary);border:1px solid var(--border-subtle);box-shadow:var(--shadow-card-soft-subtle);text-decoration:none;color:inherit;display:grid;gap:var(--space-8)}sce-engineering-office-card-skeleton .cardList,sce-engineering-office-card .cardList{grid-template-columns:180px minmax(0,1fr);grid-template-areas:\"media content\";align-items:center;min-height:auto;direction:rtl}sce-engineering-office-card-skeleton .cardList[dir=ltr],sce-engineering-office-card .cardList[dir=ltr]{direction:ltr}sce-engineering-office-card-skeleton .media,sce-engineering-office-card .media{position:relative;width:100%;max-width:100%;min-width:0;height:10.5rem;border-radius:var(--radius-brand-sm);overflow:hidden;isolation:isolate;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaList,sce-engineering-office-card .mediaList{grid-area:media;position:relative;width:100%;height:100%;border-radius:var(--radius-brand-sm);overflow:hidden;isolation:isolate;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaImg,sce-engineering-office-card .mediaImg{width:100%;height:100%;object-fit:cover;object-position:center;transition:opacity .35s ease}sce-engineering-office-card-skeleton .mediaImgLoading,sce-engineering-office-card .mediaImgLoading{opacity:0}sce-engineering-office-card-skeleton .mediaImgLoaded,sce-engineering-office-card .mediaImgLoaded{opacity:1}sce-engineering-office-card-skeleton .mediaSkeleton,sce-engineering-office-card-skeleton .logoSkeleton,sce-engineering-office-card-skeleton .lineSkeleton,sce-engineering-office-card-skeleton .tagSkeleton,sce-engineering-office-card .mediaSkeleton,sce-engineering-office-card .logoSkeleton,sce-engineering-office-card .lineSkeleton,sce-engineering-office-card .tagSkeleton{position:relative;overflow:hidden;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaSkeleton,sce-engineering-office-card .mediaSkeleton{position:absolute;inset:0;z-index:1}sce-engineering-office-card-skeleton .mediaSkeleton:after,sce-engineering-office-card-skeleton .logoSkeleton:after,sce-engineering-office-card-skeleton .lineSkeleton:after,sce-engineering-office-card-skeleton .tagSkeleton:after,sce-engineering-office-card .mediaSkeleton:after,sce-engineering-office-card .logoSkeleton:after,sce-engineering-office-card .lineSkeleton:after,sce-engineering-office-card .tagSkeleton:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,transparent 100%);animation:office-card-shimmer 1.35s ease-in-out infinite}sce-engineering-office-card-skeleton .logoSkeleton,sce-engineering-office-card .logoSkeleton{position:absolute;bottom:.9rem;inset-inline-start:.9rem;width:65.3198776245px;height:65.3198776245px;border-radius:var(--radius-full);z-index:2}sce-engineering-office-card-skeleton .cardSkeleton,sce-engineering-office-card .cardSkeleton{pointer-events:none}sce-engineering-office-card-skeleton .lineSkeleton[data-size=title],sce-engineering-office-card .lineSkeleton[data-size=title]{width:72%;height:1.35rem;border-radius:var(--space-8)}sce-engineering-office-card-skeleton .lineSkeleton[data-size=meta],sce-engineering-office-card .lineSkeleton[data-size=meta]{width:55%;height:var(--space-16);border-radius:.4rem}sce-engineering-office-card-skeleton .tagsSkeleton,sce-engineering-office-card .tagsSkeleton{display:flex;gap:var(--space-8)}sce-engineering-office-card-skeleton .tagSkeleton,sce-engineering-office-card .tagSkeleton{width:var(--space-88, var(--size-88));height:1.625rem;border-radius:var(--radius-full)}sce-engineering-office-card-skeleton .metaSkeleton,sce-engineering-office-card .metaSkeleton{margin-block-start:.4rem;padding-block-start:var(--space-12);border-block-start:1px dashed var(--border-subtle);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}@keyframes office-card-shimmer{to{transform:translate(100%)}}sce-engineering-office-card-skeleton .bookmark,sce-engineering-office-card .bookmark{position:absolute;top:.9rem;inset-inline-end:.9rem;width:var(--space-44, var(--size-44));height:var(--space-44, var(--size-44));border-radius:var(--radius-sm);border:0;background:var(--surface-overlay-white-alpha-36);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;z-index:2}sce-engineering-office-card-skeleton .bookmarkIcon,sce-engineering-office-card .bookmarkIcon{width:var(--space-20);height:var(--space-20)}sce-engineering-office-card-skeleton .logo,sce-engineering-office-card .logo{position:absolute;bottom:.9rem;inset-inline-start:.9rem;width:65.3198776245px;height:65.3198776245px;border-radius:var(--radius-full);background:var(--surface-primary);border:2px solid var(--border-chip-light);box-shadow:var(--shadow-card-soft-subtle);overflow:hidden;z-index:2}sce-engineering-office-card-skeleton .logoInner,sce-engineering-office-card .logoInner{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}sce-engineering-office-card-skeleton .logoPhoto,sce-engineering-office-card .logoPhoto{object-fit:cover;object-position:center;transition:opacity .35s ease;height:100%}sce-engineering-office-card-skeleton .logoPhotoLoading,sce-engineering-office-card .logoPhotoLoading{opacity:0}sce-engineering-office-card-skeleton .logoPhotoLoaded,sce-engineering-office-card .logoPhotoLoaded{opacity:1}sce-engineering-office-card-skeleton .logoPlaceholderSkeleton,sce-engineering-office-card .logoPlaceholderSkeleton{position:absolute;inset:0;border-radius:var(--radius-full);overflow:hidden;background:var(--surface-overlay-soft);z-index:1}sce-engineering-office-card-skeleton .logoPlaceholderSkeleton:after,sce-engineering-office-card .logoPlaceholderSkeleton:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,transparent 100%);animation:office-card-shimmer 1.35s ease-in-out infinite}sce-engineering-office-card-skeleton .logoIcon,sce-engineering-office-card .logoIcon{width:58%;height:58%;object-fit:contain;display:block}sce-engineering-office-card-skeleton .body,sce-engineering-office-card .body{padding-block-start:var(--space-12);display:grid;gap:var(--space-8)}sce-engineering-office-card-skeleton .cardList .body,sce-engineering-office-card .cardList .body{grid-area:content;padding-block-start:0}sce-engineering-office-card-skeleton .nameRow,sce-engineering-office-card .nameRow{display:flex;align-items:center;justify-content:flex-start;gap:var(--space-8);margin-block-end:var(--space-6)}sce-engineering-office-card-skeleton .name,sce-engineering-office-card .name{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--text-primary-emphasis);text-align:start;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}sce-engineering-office-card-skeleton .verifiedIcon,sce-engineering-office-card .verifiedIcon{width:var(--space-20);height:var(--space-20)}sce-engineering-office-card-skeleton .tags,sce-engineering-office-card .tags{display:flex;flex-wrap:nowrap;gap:var(--space-8);justify-content:flex-start;align-items:center;overflow-x:auto;scrollbar-width:none;margin-block-end:var(--space-6)}sce-engineering-office-card-skeleton .tag,sce-engineering-office-card .tag{width:fit-content;height:var(--space-26, var(--size-26));padding:var(--space-4) var(--space-12);border-radius:var(--radius-2xl, var(--radius-2xl));background:var(--color-neutral-100);font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);color:var(--text-primary-soft);display:inline-flex;align-items:center;white-space:nowrap}sce-engineering-office-card-skeleton .meta,sce-engineering-office-card .meta{margin-block-start:.4rem;padding-block-start:var(--space-12);border-block-start:1px dashed var(--border-subtle);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}sce-engineering-office-card-skeleton .metaItem,sce-engineering-office-card .metaItem{display:grid;gap:.4rem;justify-items:flex-start;text-align:start;min-width:0}sce-engineering-office-card-skeleton .metaLabel,sce-engineering-office-card .metaLabel{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-primary-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}sce-engineering-office-card-skeleton .metaValue,sce-engineering-office-card .metaValue{display:flex;align-items:flex-start;gap:var(--space-8);font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--text-primary-soft);line-height:1.4;min-width:0}sce-engineering-office-card-skeleton .metaValue>span:not(.ratingCount),sce-engineering-office-card .metaValue>span:not(.ratingCount){display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;overflow-wrap:break-word;flex:1}sce-engineering-office-card-skeleton .ratingCount,sce-engineering-office-card .ratingCount{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-primary-faint);flex-shrink:0;margin-inline-start:-.25rem}sce-engineering-office-card-skeleton .metaIcon,sce-engineering-office-card .metaIcon{width:1.35rem;height:1.35rem;flex-shrink:0;margin-block-start:.15rem}@media(max-width:640px){sce-engineering-office-card-skeleton .card,sce-engineering-office-card .card{min-height:var(--size-320);padding:var(--space-16)}sce-engineering-office-card-skeleton .logo,sce-engineering-office-card .logo{width:var(--space-64);height:var(--space-64)}sce-engineering-office-card-skeleton .logoIcon,sce-engineering-office-card .logoIcon{width:1.8rem;height:1.8rem}sce-engineering-office-card-skeleton .name,sce-engineering-office-card .name{font-size:1.6rem}}\n"] }]
3507
3554
  }], propDecorators: { office: [{ type: i0.Input, args: [{ isSignal: true, alias: "office", required: true }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], bookmarkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookmarkLabel", required: false }] }], bookmarked: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookmarked", required: false }] }], ratingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingLabel", required: false }] }], locationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationLabel", required: false }] }], otherLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "otherLabel", required: false }] }], bookmarkClick: [{ type: i0.Output, args: ["bookmarkClick"] }] } });
3508
3555
 
3556
+ /** Loading placeholder for the engineering office card, mirroring its grid or list layout via `viewMode`. */
3509
3557
  class SceEngineeringOfficeCardSkeletonComponent {
3510
3558
  viewMode = input('grid', ...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
3511
3559
  wrapperClass = computed(() => this.viewMode() === 'list' ? 'card cardList cardSkeleton' : 'card cardSkeleton', ...(ngDevMode ? [{ debugName: "wrapperClass" }] : /* istanbul ignore next */ []));
@@ -3518,6 +3566,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3518
3566
  args: [{ host: { class: 'sce-engineering-office-card-skeleton' }, selector: 'sce-engineering-office-card-skeleton', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SceSkeleton], template: "<article [class]=\"wrapperClass()\" aria-hidden=\"true\">\n <div [class]=\"mediaClass()\">\n <div class=\"mediaSkeleton\">\n <sce-skeleton variant=\"rectangular\" width=\"100%\" height=\"100%\" borderRadius=\"0\" />\n </div>\n <div class=\"logoSkeleton\">\n <sce-skeleton variant=\"circular\" width=\"100%\" height=\"100%\" />\n </div>\n </div>\n <div class=\"body\">\n <sce-skeleton variant=\"header\" width=\"72%\" height=\"1.35rem\" />\n <div class=\"tagsSkeleton\">\n <sce-skeleton variant=\"chip\" width=\"5.5rem\" height=\"1.625rem\" />\n <sce-skeleton variant=\"chip\" width=\"5.5rem\" height=\"1.625rem\" />\n </div>\n <div class=\"metaSkeleton\">\n <sce-skeleton variant=\"text\" width=\"80%\" height=\"1rem\" />\n <sce-skeleton variant=\"text\" width=\"80%\" height=\"1rem\" />\n </div>\n </div>\n</article>\n", styles: ["@charset \"UTF-8\";sce-engineering-office-card-skeleton,sce-engineering-office-card{display:block}sce-engineering-office-card-skeleton .card,sce-engineering-office-card .card{width:100%;min-height:var(--size-320);border-radius:var(--radius-brand-sm);padding:var(--space-18);background:var(--surface-primary);border:1px solid var(--border-subtle);box-shadow:var(--shadow-card-soft-subtle);text-decoration:none;color:inherit;display:grid;gap:var(--space-8)}sce-engineering-office-card-skeleton .cardList,sce-engineering-office-card .cardList{grid-template-columns:180px minmax(0,1fr);grid-template-areas:\"media content\";align-items:center;min-height:auto;direction:rtl}sce-engineering-office-card-skeleton .cardList[dir=ltr],sce-engineering-office-card .cardList[dir=ltr]{direction:ltr}sce-engineering-office-card-skeleton .media,sce-engineering-office-card .media{position:relative;width:100%;max-width:100%;min-width:0;height:10.5rem;border-radius:var(--radius-brand-sm);overflow:hidden;isolation:isolate;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaList,sce-engineering-office-card .mediaList{grid-area:media;position:relative;width:100%;height:100%;border-radius:var(--radius-brand-sm);overflow:hidden;isolation:isolate;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaImg,sce-engineering-office-card .mediaImg{width:100%;height:100%;object-fit:cover;object-position:center;transition:opacity .35s ease}sce-engineering-office-card-skeleton .mediaImgLoading,sce-engineering-office-card .mediaImgLoading{opacity:0}sce-engineering-office-card-skeleton .mediaImgLoaded,sce-engineering-office-card .mediaImgLoaded{opacity:1}sce-engineering-office-card-skeleton .mediaSkeleton,sce-engineering-office-card-skeleton .logoSkeleton,sce-engineering-office-card-skeleton .lineSkeleton,sce-engineering-office-card-skeleton .tagSkeleton,sce-engineering-office-card .mediaSkeleton,sce-engineering-office-card .logoSkeleton,sce-engineering-office-card .lineSkeleton,sce-engineering-office-card .tagSkeleton{position:relative;overflow:hidden;background:var(--surface-overlay-soft)}sce-engineering-office-card-skeleton .mediaSkeleton,sce-engineering-office-card .mediaSkeleton{position:absolute;inset:0;z-index:1}sce-engineering-office-card-skeleton .mediaSkeleton:after,sce-engineering-office-card-skeleton .logoSkeleton:after,sce-engineering-office-card-skeleton .lineSkeleton:after,sce-engineering-office-card-skeleton .tagSkeleton:after,sce-engineering-office-card .mediaSkeleton:after,sce-engineering-office-card .logoSkeleton:after,sce-engineering-office-card .lineSkeleton:after,sce-engineering-office-card .tagSkeleton:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,transparent 100%);animation:office-card-shimmer 1.35s ease-in-out infinite}sce-engineering-office-card-skeleton .logoSkeleton,sce-engineering-office-card .logoSkeleton{position:absolute;bottom:.9rem;inset-inline-start:.9rem;width:65.3198776245px;height:65.3198776245px;border-radius:var(--radius-full);z-index:2}sce-engineering-office-card-skeleton .cardSkeleton,sce-engineering-office-card .cardSkeleton{pointer-events:none}sce-engineering-office-card-skeleton .lineSkeleton[data-size=title],sce-engineering-office-card .lineSkeleton[data-size=title]{width:72%;height:1.35rem;border-radius:var(--space-8)}sce-engineering-office-card-skeleton .lineSkeleton[data-size=meta],sce-engineering-office-card .lineSkeleton[data-size=meta]{width:55%;height:var(--space-16);border-radius:.4rem}sce-engineering-office-card-skeleton .tagsSkeleton,sce-engineering-office-card .tagsSkeleton{display:flex;gap:var(--space-8)}sce-engineering-office-card-skeleton .tagSkeleton,sce-engineering-office-card .tagSkeleton{width:var(--space-88, var(--size-88));height:1.625rem;border-radius:var(--radius-full)}sce-engineering-office-card-skeleton .metaSkeleton,sce-engineering-office-card .metaSkeleton{margin-block-start:.4rem;padding-block-start:var(--space-12);border-block-start:1px dashed var(--border-subtle);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}@keyframes office-card-shimmer{to{transform:translate(100%)}}sce-engineering-office-card-skeleton .bookmark,sce-engineering-office-card .bookmark{position:absolute;top:.9rem;inset-inline-end:.9rem;width:var(--space-44, var(--size-44));height:var(--space-44, var(--size-44));border-radius:var(--radius-sm);border:0;background:var(--surface-overlay-white-alpha-36);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;z-index:2}sce-engineering-office-card-skeleton .bookmarkIcon,sce-engineering-office-card .bookmarkIcon{width:var(--space-20);height:var(--space-20)}sce-engineering-office-card-skeleton .logo,sce-engineering-office-card .logo{position:absolute;bottom:.9rem;inset-inline-start:.9rem;width:65.3198776245px;height:65.3198776245px;border-radius:var(--radius-full);background:var(--surface-primary);border:2px solid var(--border-chip-light);box-shadow:var(--shadow-card-soft-subtle);overflow:hidden;z-index:2}sce-engineering-office-card-skeleton .logoInner,sce-engineering-office-card .logoInner{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}sce-engineering-office-card-skeleton .logoPhoto,sce-engineering-office-card .logoPhoto{object-fit:cover;object-position:center;transition:opacity .35s ease;height:100%}sce-engineering-office-card-skeleton .logoPhotoLoading,sce-engineering-office-card .logoPhotoLoading{opacity:0}sce-engineering-office-card-skeleton .logoPhotoLoaded,sce-engineering-office-card .logoPhotoLoaded{opacity:1}sce-engineering-office-card-skeleton .logoPlaceholderSkeleton,sce-engineering-office-card .logoPlaceholderSkeleton{position:absolute;inset:0;border-radius:var(--radius-full);overflow:hidden;background:var(--surface-overlay-soft);z-index:1}sce-engineering-office-card-skeleton .logoPlaceholderSkeleton:after,sce-engineering-office-card .logoPlaceholderSkeleton:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,transparent 100%);animation:office-card-shimmer 1.35s ease-in-out infinite}sce-engineering-office-card-skeleton .logoIcon,sce-engineering-office-card .logoIcon{width:58%;height:58%;object-fit:contain;display:block}sce-engineering-office-card-skeleton .body,sce-engineering-office-card .body{padding-block-start:var(--space-12);display:grid;gap:var(--space-8)}sce-engineering-office-card-skeleton .cardList .body,sce-engineering-office-card .cardList .body{grid-area:content;padding-block-start:0}sce-engineering-office-card-skeleton .nameRow,sce-engineering-office-card .nameRow{display:flex;align-items:center;justify-content:flex-start;gap:var(--space-8);margin-block-end:var(--space-6)}sce-engineering-office-card-skeleton .name,sce-engineering-office-card .name{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--text-primary-emphasis);text-align:start;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}sce-engineering-office-card-skeleton .verifiedIcon,sce-engineering-office-card .verifiedIcon{width:var(--space-20);height:var(--space-20)}sce-engineering-office-card-skeleton .tags,sce-engineering-office-card .tags{display:flex;flex-wrap:nowrap;gap:var(--space-8);justify-content:flex-start;align-items:center;overflow-x:auto;scrollbar-width:none;margin-block-end:var(--space-6)}sce-engineering-office-card-skeleton .tag,sce-engineering-office-card .tag{width:fit-content;height:var(--space-26, var(--size-26));padding:var(--space-4) var(--space-12);border-radius:var(--radius-2xl, var(--radius-2xl));background:var(--color-neutral-100);font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);color:var(--text-primary-soft);display:inline-flex;align-items:center;white-space:nowrap}sce-engineering-office-card-skeleton .meta,sce-engineering-office-card .meta{margin-block-start:.4rem;padding-block-start:var(--space-12);border-block-start:1px dashed var(--border-subtle);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}sce-engineering-office-card-skeleton .metaItem,sce-engineering-office-card .metaItem{display:grid;gap:.4rem;justify-items:flex-start;text-align:start;min-width:0}sce-engineering-office-card-skeleton .metaLabel,sce-engineering-office-card .metaLabel{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-primary-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}sce-engineering-office-card-skeleton .metaValue,sce-engineering-office-card .metaValue{display:flex;align-items:flex-start;gap:var(--space-8);font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--text-primary-soft);line-height:1.4;min-width:0}sce-engineering-office-card-skeleton .metaValue>span:not(.ratingCount),sce-engineering-office-card .metaValue>span:not(.ratingCount){display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;overflow-wrap:break-word;flex:1}sce-engineering-office-card-skeleton .ratingCount,sce-engineering-office-card .ratingCount{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-primary-faint);flex-shrink:0;margin-inline-start:-.25rem}sce-engineering-office-card-skeleton .metaIcon,sce-engineering-office-card .metaIcon{width:1.35rem;height:1.35rem;flex-shrink:0;margin-block-start:.15rem}@media(max-width:640px){sce-engineering-office-card-skeleton .card,sce-engineering-office-card .card{min-height:var(--size-320);padding:var(--space-16)}sce-engineering-office-card-skeleton .logo,sce-engineering-office-card .logo{width:var(--space-64);height:var(--space-64)}sce-engineering-office-card-skeleton .logoIcon,sce-engineering-office-card .logoIcon{width:1.8rem;height:1.8rem}sce-engineering-office-card-skeleton .name,sce-engineering-office-card .name{font-size:1.6rem}}\n"] }]
3519
3567
  }], propDecorators: { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }] } });
3520
3568
 
3569
+ /** Single office metric tile rendering a title, subtitle and optional icon in an accent or soft variant. */
3521
3570
  class SceOfficeMetricCardComponent {
3522
3571
  item = input.required(...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
3523
3572
  variant = input('accent', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -3528,6 +3577,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3528
3577
  type: Component,
3529
3578
  args: [{ host: { class: 'sce-office-metric-card' }, selector: 'sce-office-metric-card', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"metricCard\">\n <div class=\"metricIconWrap\" [class.metricIconAccent]=\"variant() === 'accent'\" [class.metricIconSoft]=\"variant() === 'soft'\">\n @if (item().icon) {\n <img [src]=\"item().icon\" width=\"28\" height=\"28\" alt=\"\" aria-hidden=\"true\" class=\"metricIconImg\" />\n }\n </div>\n <div class=\"metricBody\">\n <p class=\"metricTitle\">{{ item().title }}</p>\n <p class=\"metricSubtitle\">{{ item().subtitle }}</p>\n </div>\n</article>\n", styles: ["sce-office-metric-card{display:block;min-width:0;flex:1}.metricCard{display:flex;min-width:0;flex:1;align-items:center;gap:var(--space-12);border-radius:var(--space-12);border:1px solid var(--pagination-surface-hover, var(--color-neutral-200));background:var(--public-surface, var(--background-bg-primary));padding:var(--space-16)}.metricIconWrap{display:flex;height:53.58px;width:53.58px;flex-shrink:0;align-items:center;justify-content:center;border-radius:15.31px}.metricIconAccent{background:var(--surface-accent-brand)}.metricIconAccent .metricIconImg{filter:brightness(0) invert(1)}.metricIconSoft{background:var(--color-info-100)}.metricBody{display:flex;min-width:0;flex:1;flex-direction:column;gap:var(--space-4);text-align:start}.metricTitle{font-size:var(--font-size-lg);font-weight:600;color:var(--text-text-secondary-700);margin:0}.metricSubtitle{font-size:var(--font-size-lg);font-weight:400;color:var(--text-text-primary-900);margin:0}.metricCardsRow{display:grid;width:100%;gap:var(--space-16);grid-template-columns:repeat(2,1fr)}.metricCardsRow3{grid-template-columns:repeat(3,1fr)}@media(max-width:640px){.metricCardsRow,.metricCardsRow3{grid-template-columns:1fr}}\n"] }]
3530
3579
  }], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
3580
+ /** Row of office metric tiles laid out in two or three columns, sharing one variant across all items. */
3531
3581
  class SceOfficeMetricCardsRowComponent {
3532
3582
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
3533
3583
  variant = input('accent', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -3540,6 +3590,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3540
3590
  args: [{ host: { class: 'sce-office-metric-cards-row' }, selector: 'sce-office-metric-cards-row', standalone: true, imports: [SceOfficeMetricCardComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"metricCardsRow\" [class.metricCardsRow3]=\"columns() === 3\">\n @for (item of items(); track item.subtitle) {\n <sce-office-metric-card [item]=\"item\" [variant]=\"variant()\" />\n }\n</div>\n", styles: ["sce-office-metric-card{display:block;min-width:0;flex:1}.metricCard{display:flex;min-width:0;flex:1;align-items:center;gap:var(--space-12);border-radius:var(--space-12);border:1px solid var(--pagination-surface-hover, var(--color-neutral-200));background:var(--public-surface, var(--background-bg-primary));padding:var(--space-16)}.metricIconWrap{display:flex;height:53.58px;width:53.58px;flex-shrink:0;align-items:center;justify-content:center;border-radius:15.31px}.metricIconAccent{background:var(--surface-accent-brand)}.metricIconAccent .metricIconImg{filter:brightness(0) invert(1)}.metricIconSoft{background:var(--color-info-100)}.metricBody{display:flex;min-width:0;flex:1;flex-direction:column;gap:var(--space-4);text-align:start}.metricTitle{font-size:var(--font-size-lg);font-weight:600;color:var(--text-text-secondary-700);margin:0}.metricSubtitle{font-size:var(--font-size-lg);font-weight:400;color:var(--text-text-primary-900);margin:0}.metricCardsRow{display:grid;width:100%;gap:var(--space-16);grid-template-columns:repeat(2,1fr)}.metricCardsRow3{grid-template-columns:repeat(3,1fr)}@media(max-width:640px){.metricCardsRow,.metricCardsRow3{grid-template-columns:1fr}}\n"] }]
3541
3591
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }] } });
3542
3592
 
3593
+ /** Loading placeholder matching `sce-info-fields-grid`: `count` info-field cards (default 6) with an optional section-title bar. */
3543
3594
  class SceInfoFieldsSkeletonComponent {
3544
3595
  /** Number of info-field cards to render */
3545
3596
  count = input(6, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
@@ -3556,6 +3607,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3556
3607
  args: [{ host: { class: 'sce-info-fields-skeleton' }, selector: 'sce-info-fields-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-info-fields-skeleton\" [class.sce-info-fields-skeleton--gap-md]=\"gap() === 'md'\" role=\"status\" aria-busy=\"true\">\n @if (showSectionTitle()) {\n <sce-skeleton variant=\"header\" width=\"12rem\" height=\"1.25rem\" animation=\"wave\" />\n }\n\n <div class=\"sce-info-fields-skeleton__grid\">\n @for (i of slots(); track i) {\n <div class=\"sce-info-fields-skeleton__card\">\n <sce-skeleton variant=\"text\" width=\"42%\" height=\"0.75rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"72%\" height=\"1rem\" animation=\"wave\" />\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.sce-info-fields-skeleton{display:grid;gap:var(--space-12);width:100%}.sce-info-fields-skeleton--gap-md{gap:var(--space-20)}.sce-info-fields-skeleton__grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12);width:100%}.sce-info-fields-skeleton--gap-md .sce-info-fields-skeleton__grid{gap:var(--space-20)}.sce-info-fields-skeleton__card{display:flex;flex-direction:column;gap:var(--space-8);min-height:var(--space-72);padding:var(--space-16);border-radius:var(--radius-lg);background:var(--app-surface-hover);box-sizing:border-box}@media(max-width:640px){.sce-info-fields-skeleton__grid{grid-template-columns:1fr}}\n"] }]
3557
3608
  }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], showSectionTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSectionTitle", required: false }] }] } });
3558
3609
 
3610
+ /** Loading placeholder for a form: `count` label-plus-input pairs (default 6) laid out in one or two `columns`. */
3559
3611
  class SceFormFieldsSkeletonComponent {
3560
3612
  count = input(6, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
3561
3613
  columns = input(2, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
@@ -3568,6 +3620,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3568
3620
  args: [{ host: { class: 'sce-form-fields-skeleton' }, selector: 'sce-form-fields-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-form-fields-skeleton\" [class.sce-form-fields-skeleton--cols-1]=\"columns() === 1\" role=\"status\" aria-busy=\"true\">\n @for (i of slots(); track i) {\n <sce-skeleton variant=\"input\" animation=\"wave\" />\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-form-fields-skeleton{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-16);width:100%}.sce-form-fields-skeleton--cols-1{grid-template-columns:1fr}@media(max-width:768px){.sce-form-fields-skeleton{grid-template-columns:1fr}}\n"] }]
3569
3621
  }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }] } });
3570
3622
 
3623
+ /** Loading placeholder for a notification list: `count` rows (default 5), with `compact` tightening the padding for dropdown menus. */
3571
3624
  class SceNotificationListSkeletonComponent {
3572
3625
  count = input(5, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
3573
3626
  /** Compact padding for dropdown menus */
@@ -3581,6 +3634,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3581
3634
  args: [{ host: { class: 'sce-notification-list-skeleton' }, selector: 'sce-notification-list-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-notification-list-skeleton\" [class.sce-notification-list-skeleton--compact]=\"compact()\" role=\"status\" aria-busy=\"true\">\n @for (i of slots(); track i) {\n <article class=\"sce-notification-list-skeleton__item\">\n <div class=\"sce-notification-list-skeleton__top\">\n <div class=\"sce-notification-list-skeleton__meta\">\n <sce-skeleton variant=\"circular\" width=\"0.5rem\" height=\"0.5rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"0.875rem\" animation=\"wave\" />\n <sce-skeleton variant=\"chip\" width=\"4.5rem\" height=\"1.25rem\" animation=\"wave\" />\n </div>\n <sce-skeleton variant=\"text\" width=\"5rem\" height=\"0.75rem\" animation=\"wave\" />\n </div>\n <sce-skeleton variant=\"text\" width=\"100%\" height=\"0.875rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"88%\" height=\"0.875rem\" animation=\"wave\" />\n </article>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-notification-list-skeleton{display:grid;gap:var(--space-12);width:100%}.sce-notification-list-skeleton--compact{gap:var(--space-8)}.sce-notification-list-skeleton__item{display:grid;gap:var(--space-8);padding:var(--space-16);border:1px solid var(--color-neutral-200);border-radius:var(--radius-lg);background:var(--surface-primary);box-sizing:border-box;min-height:var(--space-96)}.sce-notification-list-skeleton--compact .sce-notification-list-skeleton__item{padding:var(--space-12);min-height:var(--space-72)}.sce-notification-list-skeleton__top{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-12)}.sce-notification-list-skeleton__meta{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-8);min-width:0;flex:1}\n"] }]
3582
3635
  }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }] } });
3583
3636
 
3637
+ /** Loading placeholder for a profile page: a hero banner of `heroHeight` (default `230px`) above `fieldCount` info-field placeholders. */
3584
3638
  class SceProfileHeroSkeletonComponent {
3585
3639
  heroHeight = input('230px', ...(ngDevMode ? [{ debugName: "heroHeight" }] : /* istanbul ignore next */ []));
3586
3640
  fieldCount = input(4, ...(ngDevMode ? [{ debugName: "fieldCount" }] : /* istanbul ignore next */ []));
@@ -3592,6 +3646,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3592
3646
  args: [{ host: { class: 'sce-profile-hero-skeleton' }, selector: 'sce-profile-hero-skeleton', standalone: true, imports: [SceSkeleton, SceInfoFieldsSkeletonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"sce-profile-hero-skeleton\" role=\"status\" aria-busy=\"true\">\n <sce-skeleton variant=\"rectangular\" [height]=\"heroHeight()\" animation=\"wave\" borderRadius=\"0\" aria-hidden=\"true\" />\n <div class=\"sce-profile-hero-skeleton__body\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"45%\" />\n <sce-skeleton variant=\"text\" animation=\"wave\" width=\"30%\" />\n <sce-info-fields-skeleton [count]=\"fieldCount()\" />\n </div>\n</section>\n", styles: [":host{display:block;width:100%}.sce-profile-hero-skeleton{display:grid;gap:var(--space-16);width:100%}.sce-profile-hero-skeleton__body{display:grid;gap:var(--space-12);padding-inline:var(--space-24);padding-block-end:var(--space-24)}\n"] }]
3593
3647
  }], propDecorators: { heroHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "heroHeight", required: false }] }], fieldCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldCount", required: false }] }] } });
3594
3648
 
3649
+ /** Loading placeholder for a data table (`columns` x `rows`, default 5x5), cycling a fixed set of column widths and treating the last column as a status pill; `wrapInCard` defaults to true. */
3595
3650
  class SceTableSkeletonComponent {
3596
3651
  columns = input(5, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
3597
3652
  rows = input(5, ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
@@ -3659,6 +3714,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3659
3714
  args: [{ host: { class: 'sce-featured-office-card-skeleton' }, selector: 'sce-featured-office-card-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"sce-featured-office-card-skeleton\" role=\"status\" aria-busy=\"true\">\n <div class=\"sce-featured-office-card-skeleton__lead\">\n <sce-skeleton variant=\"rounded\" width=\"4rem\" height=\"4rem\" borderRadius=\"var(--radius-lg)\" animation=\"wave\" />\n <div class=\"sce-featured-office-card-skeleton__meta\">\n <sce-skeleton variant=\"header\" width=\"12rem\" height=\"1rem\" animation=\"wave\" />\n <sce-skeleton variant=\"text\" width=\"16rem\" height=\"0.875rem\" animation=\"wave\" />\n </div>\n </div>\n <div class=\"sce-featured-office-card-skeleton__tags\">\n <sce-skeleton variant=\"chip\" width=\"4.5rem\" height=\"1.5rem\" animation=\"wave\" />\n <sce-skeleton variant=\"chip\" width=\"5rem\" height=\"1.5rem\" animation=\"wave\" />\n <sce-skeleton variant=\"chip\" width=\"4rem\" height=\"1.5rem\" animation=\"wave\" />\n </div>\n <sce-skeleton variant=\"button\" width=\"6.5rem\" height=\"2rem\" borderRadius=\"999px\" animation=\"wave\" />\n</article>\n", styles: [":host{display:block;width:100%}.sce-featured-office-card-skeleton{display:flex;align-items:center;justify-content:space-between;gap:var(--space-24);background:var(--surface-primary);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:var(--space-16) var(--space-24);box-sizing:border-box;pointer-events:none;min-width:0}.sce-featured-office-card-skeleton__lead{display:flex;align-items:center;gap:var(--space-16);flex:1;min-width:0}.sce-featured-office-card-skeleton__meta{display:flex;flex-direction:column;gap:var(--space-24);min-width:0;flex:1}.sce-featured-office-card-skeleton__tags{display:flex;flex-wrap:wrap;gap:var(--space-8);justify-content:center}@media(max-width:768px){.sce-featured-office-card-skeleton{flex-direction:column;align-items:stretch}.sce-featured-office-card-skeleton__tags{justify-content:flex-start}}\n"] }]
3660
3715
  }] });
3661
3716
 
3717
+ /** Fixed loading placeholder for the service-detail page; takes no inputs. */
3662
3718
  class SceServiceDetailSkeletonComponent {
3663
3719
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceServiceDetailSkeletonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3664
3720
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SceServiceDetailSkeletonComponent, isStandalone: true, selector: "sce-service-detail-skeleton", host: { classAttribute: "sce-service-detail-skeleton" }, ngImport: i0, template: "<div class=\"sce-service-detail-skeleton\" role=\"status\" aria-busy=\"true\">\n <div class=\"sce-service-detail-skeleton__main\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"50%\" />\n <sce-skeleton variant=\"paragraph\" animation=\"wave\" [count]=\"4\" />\n </div>\n <div class=\"sce-service-detail-skeleton__sidebar\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"60%\" />\n @for (i of [1, 2, 3, 4, 5]; track i) {\n <sce-skeleton variant=\"text\" animation=\"wave\" />\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.sce-service-detail-skeleton{display:grid;grid-template-columns:minmax(0,1fr) minmax(280px,360px);gap:var(--space-24);width:100%}.sce-service-detail-skeleton__main,.sce-service-detail-skeleton__sidebar{display:grid;gap:var(--space-16);background:var(--surface-primary);border:1px solid var(--color-primary-100);border-radius:var(--radius-lg);padding:var(--space-24);box-sizing:border-box}@media(max-width:992px){.sce-service-detail-skeleton{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "component", type: SceSkeleton, selector: "sce-skeleton", inputs: ["variant", "animation", "width", "height", "borderRadius", "count", "gap", "shrinkLastLine", "aspectRatio"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -3668,6 +3724,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3668
3724
  args: [{ host: { class: 'sce-service-detail-skeleton' }, selector: 'sce-service-detail-skeleton', standalone: true, imports: [SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-service-detail-skeleton\" role=\"status\" aria-busy=\"true\">\n <div class=\"sce-service-detail-skeleton__main\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"50%\" />\n <sce-skeleton variant=\"paragraph\" animation=\"wave\" [count]=\"4\" />\n </div>\n <div class=\"sce-service-detail-skeleton__sidebar\">\n <sce-skeleton variant=\"header\" animation=\"wave\" width=\"60%\" />\n @for (i of [1, 2, 3, 4, 5]; track i) {\n <sce-skeleton variant=\"text\" animation=\"wave\" />\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.sce-service-detail-skeleton{display:grid;grid-template-columns:minmax(0,1fr) minmax(280px,360px);gap:var(--space-24);width:100%}.sce-service-detail-skeleton__main,.sce-service-detail-skeleton__sidebar{display:grid;gap:var(--space-16);background:var(--surface-primary);border:1px solid var(--color-primary-100);border-radius:var(--radius-lg);padding:var(--space-24);box-sizing:border-box}@media(max-width:992px){.sce-service-detail-skeleton{grid-template-columns:1fr}}\n"] }]
3669
3725
  }] });
3670
3726
 
3727
+ /** Loading placeholder for the office-details panel — `count` repeated blocks (minimum 1); uses `ViewEncapsulation.None` and shares its styles with the office-projects skeleton. */
3671
3728
  class SceOfficeDetailsSkeletonComponent {
3672
3729
  count = input(2, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
3673
3730
  countArray = computed(() => Array.from({ length: Math.max(1, this.count()) }, (_, i) => i), ...(ngDevMode ? [{ debugName: "countArray" }] : /* istanbul ignore next */ []));
@@ -3678,6 +3735,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3678
3735
  type: Component,
3679
3736
  args: [{ host: { class: 'sce-office-details-skeleton' }, selector: 'sce-office-details-skeleton', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"projectsSkeletonStack\">\n @for (i of countArray(); track i) {\n <div class=\"panelSkeleton shimmerPanel projectPanelSkeleton\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock projectHeroSkeleton\"></div>\n <div class=\"projectThumbsSkeletonRow\">\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n </div>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";sce-office-details-skeleton,sce-office-projects-skeleton{display:block}\n", "@charset \"UTF-8\";.shimmerBlock,.shimmerPanel{position:relative;overflow:hidden;background:#ffffff2e;border-radius:var(--space-8)}.shimmerPanel{background:var(--public-surface, var(--background-bg-primary));border-radius:var(--space-16);padding:var(--space-16) var(--space-20)}.shimmerBlock:after,.shimmerPanel:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.42) 45%,transparent 100%);animation:office-detail-shimmer 1.35s ease-in-out infinite}.shimmerPanel:after{background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.65) 45%,transparent 100%)}@keyframes office-detail-shimmer{to{transform:translate(100%)}}.contentSkeletonLayout{display:flex;width:100%;max-width:var(--size-1220);flex-direction:column;gap:var(--space-24);padding-inline:var(--space-16)}.contentSkeletonColumn{display:flex;flex:1;flex-direction:column;gap:var(--space-24)}.panelSkeleton{display:grid;gap:var(--space-12)}.panelTitleSkeleton{width:8rem;height:1.35rem}.panelLineSkeleton{width:100%;height:var(--space-16)}.panelLineSkeleton:last-child{width:82%}.metricSkeletonRow{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-16);margin-block-start:var(--space-8)}.metricSkeleton{height:var(--space-88, var(--size-88));border-radius:var(--space-16)}.mapPanelSkeleton{min-height:var(--size-280)}.mapSkeleton{width:100%;height:var(--size-220);border-radius:var(--space-16);margin-block-start:var(--space-8)}.projectsSkeletonStack{flex-direction:column;gap:var(--space-24)}.projectPanelSkeleton{width:100%}.projectHeroSkeleton{width:100%;height:var(--size-220);border-radius:var(--space-16);margin-block-start:var(--space-8)}.projectThumbsSkeletonRow{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-16);margin-block-start:var(--space-16)}.projectThumbSkeleton{width:100%;aspect-ratio:379/213;border-radius:var(--space-16)}@media(min-width:1024px){.contentSkeletonLayout{flex-direction:row;align-items:flex-start;padding-inline:0}.mapPanelSkeleton{width:min(596.5px,42%);flex-shrink:0}}\n"] }]
3680
3737
  }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }] } });
3738
+ /** Office-projects loading placeholder; reuses the office-details skeleton template but carries no styles of its own, so it inherits them from an office-details skeleton rendered elsewhere on the page (`ViewEncapsulation.None`). */
3681
3739
  class SceOfficeProjectsSkeletonComponent {
3682
3740
  count = input(2, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
3683
3741
  countArray = computed(() => Array.from({ length: Math.max(1, this.count()) }, (_, i) => i), ...(ngDevMode ? [{ debugName: "countArray" }] : /* istanbul ignore next */ []));
@@ -3912,6 +3970,7 @@ var osmOfficesMap_component = /*#__PURE__*/Object.freeze({
3912
3970
  SceOsmOfficesMapComponent: SceOsmOfficesMapComponent
3913
3971
  });
3914
3972
 
3973
+ /** Renders the small leading `<img>` icon inside a filter control, sized 20x20 by default and omitted entirely when `iconSrc` is unset. */
3915
3974
  class SceFilterFieldIconComponent {
3916
3975
  iconSrc = input(...(ngDevMode ? [undefined, { debugName: "iconSrc" }] : /* istanbul ignore next */ []));
3917
3976
  iconAlt = input('', ...(ngDevMode ? [{ debugName: "iconAlt" }] : /* istanbul ignore next */ []));
@@ -3926,6 +3985,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3926
3985
  args: [{ host: { class: 'sce-filter-field-icon' }, selector: 'sce-filter-field-icon', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (iconSrc()) {\n <img [src]=\"iconSrc()\" [alt]=\"iconAlt()\" [width]=\"width()\" [height]=\"height()\" [class]=\"className()\" />\n}\n", styles: [":host{display:block}.sce-filter-field-icon{display:contents}\n"] }]
3927
3986
  }], propDecorators: { iconSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSrc", required: false }] }], iconAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconAlt", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }] } });
3928
3987
 
3988
+ /** Filter-bar select built on PrimeNG `Select` with an optional leading icon, clear button, and type-ahead `filter`; controlled when `value` is bound and self-managing when it is left `undefined`, and uses `ViewEncapsulation.None`. */
3929
3989
  class SceFilterDropdownComponent {
3930
3990
  id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
3931
3991
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -3960,6 +4020,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3960
4020
  args: [{ host: { class: 'sce-filter-dropdown' }, selector: 'sce-filter-dropdown', standalone: true, imports: [Select, FormsModule, SceFilterFieldIconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"rootClass()\" [attr.data-locale]=\"locale()\" [dir]=\"dir()\">\n <sce-filter-field-icon [iconSrc]=\"iconSrc()\" [iconAlt]=\"iconAlt()\" [width]=\"20\" [height]=\"20\" className=\"icon\" />\n <p-select\n [showClear]=\"showClear()\"\n [inputId]=\"id()\"\n [ngModel]=\"currentValue()\"\n (ngModelChange)=\"onSelectionChange({ value: $event })\"\n [options]=\"options()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"placeholder()\"\n styleClass=\"dropdown\"\n [filter]=\"filter()\"\n appendTo=\"body\"\n />\n</div>\n", styles: ["@charset \"UTF-8\";.root{position:relative;width:100%}.icon{position:absolute;top:50%;transform:translateY(-50%);inset-inline-start:var(--space-12);z-index:2;pointer-events:none}.dropdown{width:100%;height:auto;border-radius:var(--radius-xl);border:1px solid var(--color-neutral-300);display:flex;align-items:center}.dropdown .p-select-label{display:flex;align-items:center;align-self:stretch;flex:1 1 auto;min-width:0;margin:0;padding-block:0;padding-inline-start:var(--space-40);padding-inline-end:var(--space-8);font-family:var(--font-family-arabic-primary);font-weight:500;font-size:var(--font-size-xs);line-height:normal;text-align:start}.dropdown .p-select-label.p-inputtext{height:auto;min-height:100%;border:0;background:transparent;box-shadow:none}.dropdown .p-select-label.p-placeholder{color:var(--color-neutral-500);font-weight:500}.dropdown .p-select-label:not(.p-placeholder){color:var(--text-text-primary-900)}.dropdown .p-select-clear-icon{position:static;inset:unset;inset-inline-start:unset;inset-inline-end:unset;margin:0;flex-shrink:0;align-self:center;color:var(--color-neutral-500);font-weight:500}.dropdown .p-select-dropdown{display:flex;align-items:center;justify-content:center;align-self:stretch;width:var(--space-40);flex-shrink:0;color:var(--color-neutral-500);font-weight:500}.root[dir=rtl] .icon{inset-inline-end:auto;inset-inline-start:var(--space-12)}\n"] }]
3961
4021
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], iconSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSrc", required: false }] }], iconAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconAlt", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
3962
4022
 
4023
+ /** Filter-bar single-date picker with a leading icon and a clear button; controlled when `value` is bound and self-managing when it is left `undefined`, and uses `ViewEncapsulation.None`. */
3963
4024
  class SceFilterCalendarComponent {
3964
4025
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
3965
4026
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
@@ -3999,6 +4060,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3999
4060
  }], propDecorators: { locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], iconSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSrc", required: false }] }], iconAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconAlt", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
4000
4061
 
4001
4062
  const EMPTY_RANGE = { from: null, to: null };
4063
+ /** Filter-bar date-range picker with a leading icon and a clear button; works controlled when `value` is bound and falls back to its own internal state when it is left `undefined`, and uses `ViewEncapsulation.None`. */
4002
4064
  class SceFilterCalendarRangeComponent {
4003
4065
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
4004
4066
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
@@ -4088,6 +4150,7 @@ function clearField(field) {
4088
4150
  break;
4089
4151
  }
4090
4152
  }
4153
+ /** Renders a dashboard table's filter row from a declarative `fields` array and exposes `hasActiveSearch`/`hasActiveFilters` plus `clearSearch()`/`clearFilters()` for a page to drive via a template reference; uses `ViewEncapsulation.None`. */
4091
4154
  class SceDashboardTableFiltersComponent {
4092
4155
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
4093
4156
  idPrefix = input('', ...(ngDevMode ? [{ debugName: "idPrefix" }] : /* istanbul ignore next */ []));
@@ -4140,6 +4203,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4140
4203
  ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"filters\" [dir]=\"dir()\" [attr.data-locale]=\"locale()\">\n @for (field of fields(); track field.id) {\n @switch (field.kind) {\n @case ('search') {\n <div class=\"field\">\n <input class=\"input\" [placeholder]=\"field.placeholder\" [value]=\"field.value\" (input)=\"onSearchInput($any(field), $event)\" />\n @if (field.iconSrc) {\n <sce-filter-field-icon\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [width]=\"20\"\n [height]=\"20\"\n className=\"trailingImageIcon\"\n />\n } @else {\n <i class=\"pi pi-search trailingIcon\" aria-hidden=\"true\"></i>\n }\n </div>\n }\n @case ('text') {\n <div class=\"field\">\n <input\n class=\"input\"\n [placeholder]=\"field.placeholder\"\n [value]=\"field.value\"\n [attr.maxlength]=\"field.maxLength ?? null\"\n [attr.inputmode]=\"field.inputMode ?? null\"\n (input)=\"onTextInput($any(field), $event)\"\n />\n <sce-filter-field-icon\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [width]=\"20\"\n [height]=\"20\"\n className=\"trailingImageIcon\"\n />\n </div>\n }\n @case ('select') {\n <div class=\"field\">\n <sce-filter-dropdown\n [id]=\"idPrefix() + '-' + field.id\"\n [locale]=\"locale()\"\n className=\"control\"\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [options]=\"field.options\"\n [placeholder]=\"field.placeholder\"\n [value]=\"field.value\"\n [showClear]=\"field.showClear ?? false\"\n [filter]=\"field.filter ?? false\"\n (valueChange)=\"field.onChange($event)\"\n />\n </div>\n }\n @case ('date') {\n <div class=\"field\">\n <sce-filter-calendar\n [locale]=\"locale()\"\n className=\"control\"\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [placeholder]=\"field.placeholder\"\n [id]=\"idPrefix() + '-' + field.id\"\n [value]=\"field.value\"\n (valueChange)=\"field.onChange($event)\"\n />\n </div>\n }\n @case ('dateRange') {\n <div class=\"field\">\n <sce-filter-calendar-range\n [locale]=\"locale()\"\n className=\"control\"\n [iconSrc]=\"field.iconSrc\"\n [iconAlt]=\"field.iconAlt ?? ''\"\n [placeholder]=\"field.placeholder\"\n [id]=\"idPrefix() + '-' + field.id\"\n [value]=\"field.value\"\n (valueChange)=\"field.onChange($event)\"\n />\n </div>\n }\n }\n }\n</div>\n", styles: ["@charset \"UTF-8\";.filters{display:grid;grid-template-columns:minmax(0,2fr) repeat(3,minmax(0,1fr));gap:var(--space-12);margin-block-end:var(--space-16)}.field{position:relative}.trailingIcon{position:absolute;inset-inline-start:var(--space-12);top:50%;transform:translateY(-50%);z-index:2;color:var(--color-neutral-500);pointer-events:none;font-weight:500;font-size:var(--font-size-xs)}.trailingImageIcon{position:absolute;inset-inline-start:var(--space-12);top:50%;transform:translateY(-50%);z-index:2;pointer-events:none}.input{width:100%;height:var(--space-48);border-radius:var(--radius-xl);border:1px solid var(--color-neutral-300);padding-block:0;padding-inline-start:var(--space-40);padding-inline-end:var(--space-14);font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-medium);font-size:var(--font-size-xs);line-height:var(--space-48);color:var(--text-text-primary-900);text-align:start}.input::placeholder{color:var(--color-neutral-500);font-family:inherit;font-weight:500;font-size:var(--font-size-xs);opacity:1}.control{width:100%}.field .p-dropdown{display:flex;align-items:center;height:var(--space-48)}.field .p-dropdown-label{display:flex;align-items:center;align-self:stretch;flex:1 1 auto;min-width:0;margin:0;padding-block:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-medium);font-size:var(--font-size-xs);line-height:normal;text-align:start}.field .p-dropdown-label.p-inputtext{height:auto;min-height:100%;border:0;background:transparent;box-shadow:none}.field .p-dropdown-label.p-placeholder{color:var(--color-neutral-500);font-weight:500}.field .p-dropdown-label:not(.p-placeholder){color:var(--text-text-primary-900)}.field .p-dropdown-clear-icon{position:static;inset:unset;inset-inline-start:unset;inset-inline-end:unset;margin:0;flex-shrink:0;align-self:center}.field .p-dropdown-trigger{display:flex;align-items:center;justify-content:center;align-self:stretch;flex-shrink:0}.field .p-inputtext:not(.p-dropdown-label){margin:0;padding-block:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-medium);font-size:var(--font-size-xs);line-height:var(--space-48);color:var(--text-text-primary-900)}.field .p-inputtext:not(.p-dropdown-label)::placeholder{color:var(--color-neutral-500);font-family:inherit;font-weight:500;font-size:inherit;opacity:1}.filters[data-locale=ar] .input{padding-inline-start:var(--space-40);padding-inline-end:var(--space-12)}@media(max-width:1200px){.filters{grid-template-columns:repeat(1,minmax(0,1fr))}}@media(max-width:768px){.filters{grid-template-columns:1fr}}\n"] }]
4141
4204
  }], propDecorators: { locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], idPrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "idPrefix", required: false }] }], fields: [{ type: i0.Input, args: [{ isSignal: true, alias: "fields", required: false }] }] } });
4142
4205
 
4206
+ /** Filter bar for the public services and offices listings, rendering a search box plus category, target, extra and sort dropdowns and emitting the resolved filter state via `filtersChange`. */
4143
4207
  class SceServicesTopFiltersComponent {
4144
4208
  language = inject(LanguageService);
4145
4209
  translate = inject(TranslateService);
@@ -4304,6 +4368,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4304
4368
  args: [{ host: { class: 'sce-services-top-filters' }, selector: 'sce-services-top-filters', standalone: true, imports: [NgTemplateOutlet, FormsModule, TranslatePipe, Select, InputText, Button], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n The three dropdown columns are identical apart from their label, icon, options, selected value\n and change handler, so they share one template rendered three times. ng-container adds no\n element, so each column stays a direct child of .services-top-filters-row.\n-->\n<ng-template #filterColumn let-field=\"field\" let-labelKey=\"labelKey\" let-icon=\"icon\" let-options=\"options\" let-selected=\"selected\">\n <div class=\"services-top-filter-col\">\n <p class=\"services-top-filter-label\">{{ labelKey | translate }}</p>\n <div class=\"sce-services-top-filters__control\">\n <img [src]=\"icon\" class=\"services-filter-value-icon\" alt=\"\" aria-hidden=\"true\" />\n <p-select\n [options]=\"options\"\n optionLabel=\"label\"\n dataKey=\"value\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"onFilterChange(field, $event)\"\n [filter]=\"true\"\n [filterPlaceholder]=\"filterPlaceholderKey() | translate\"\n [emptyFilterMessage]=\"emptyFilterMessageKey() | translate\"\n styleClass=\"services-filter-dropdown\"\n panelStyleClass=\"services-filter-dropdown-panel\"\n [attr.dir]=\"dir()\"\n appendTo=\"body\"\n >\n <ng-template #selectedItem let-option>\n @if (option) {\n <span class=\"services-filter-value-item\">\n <span class=\"services-filter-value-text\">{{ option.label }}</span>\n </span>\n }\n </ng-template>\n <ng-template #item let-option>\n <div class=\"services-filter-option-item\">\n <span class=\"services-filter-option-icon-wrap\">\n <img [src]=\"option.icon\" class=\"services-filter-option-icon\" alt=\"\" aria-hidden=\"true\" />\n </span>\n <div class=\"services-filter-option-text\">\n <span class=\"services-filter-option-title\">{{ option.label }}</span>\n <span class=\"services-filter-option-subtitle\">{{ option.subtitle | translate }}</span>\n </div>\n </div>\n </ng-template>\n </p-select>\n </div>\n </div>\n</ng-template>\n\n<div class=\"relative z-20\">\n <div [class]=\"wrapClass()\" [attr.dir]=\"dir()\">\n <div class=\"services-top-filters-badge\">\n <span class=\"sce-services-top-filters__badge-text\">\n {{ badgeKey() | translate }}\n </span>\n </div>\n\n <div class=\"services-top-filters-card\">\n <div class=\"services-top-filters-row\">\n <ng-container\n *ngTemplateOutlet=\"\n filterColumn;\n context: {\n field: 'category',\n labelKey: categoryLabelKey(),\n icon: categoryIcon(),\n options: categoryOptions(),\n selected: selectedCategory(),\n }\n \"\n />\n\n <ng-container\n *ngTemplateOutlet=\"\n filterColumn;\n context: {\n field: 'target',\n labelKey: targetLabelKey(),\n icon: targetIcon(),\n options: targetOptions(),\n selected: selectedTarget(),\n }\n \"\n />\n\n @if (extraOptions().length > 0) {\n <ng-container\n *ngTemplateOutlet=\"\n filterColumn;\n context: {\n field: 'extra',\n labelKey: extraLabelKey(),\n icon: extraIcon(),\n options: extraFilterOptions(),\n selected: selectedExtra(),\n }\n \"\n />\n }\n\n <div class=\"services-top-filter-col services-top-filter-col-search\">\n <p class=\"services-top-filter-label\">{{ searchLabelKey() | translate }}</p>\n <div class=\"services-filter-search-row\">\n <input\n pInputText\n type=\"search\"\n class=\"services-filter-input\"\n [placeholder]=\"searchPlaceholderKey() | translate\"\n [attr.aria-label]=\"searchAriaKey() | translate\"\n [(ngModel)]=\"localQ\"\n (keydown.enter)=\"submitSearch()\"\n />\n <p-button\n type=\"button\"\n styleClass=\"services-search-icon-btn\"\n (onClick)=\"submitSearch()\"\n [ariaLabel]=\"searchAriaKey() | translate\"\n >\n <img src=\"/assets/icons/search-01-spaced.svg\" alt=\"\" aria-hidden=\"true\" class=\"sce-services-top-filters__search-icon\" />\n </p-button>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".sce-services-top-filters__control{display:flex;align-items:center;gap:var(--space-8)}.sce-services-top-filters__badge-text{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--search-badge-text)}.sce-services-top-filters__search-icon{width:var(--space-24);height:var(--space-24)}\n"] }]
4305
4369
  }], propDecorators: { q: [{ type: i0.Input, args: [{ isSignal: true, alias: "q", required: false }] }], category: [{ type: i0.Input, args: [{ isSignal: true, alias: "category", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], targets: [{ type: i0.Input, args: [{ isSignal: true, alias: "targets", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], extra: [{ type: i0.Input, args: [{ isSignal: true, alias: "extra", required: false }] }], extraOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraOptions", required: false }] }], extraParamName: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraParamName", required: false }] }], filtersChange: [{ type: i0.Output, args: ["filtersChange"] }] } });
4306
4370
 
4371
+ /** Landing-page navigation bar that renders the required `items` as router links with route prefetching and active-route highlighting. */
4307
4372
  class SceLandingNavComponent {
4308
4373
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
4309
4374
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceLandingNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -4389,6 +4454,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4389
4454
  args: [{ host: { class: 'sce-landing-mobile-menu' }, selector: 'sce-landing-mobile-menu', standalone: true, imports: [RouterLink, TranslatePipe, RoutePrefetchDirective, SceRouteActiveDirective], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n type=\"button\"\n class=\"sce-mobile-menu__trigger\"\n [attr.aria-label]=\"'nav.openMenu' | translate\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"isOpen()\"\n (click)=\"open()\"\n>\n <svg class=\"sce-mobile-menu__trigger-icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M3 6h18M3 12h18M3 18h18\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n</button>\n\n<ng-template #menuOverlay>\n <!-- Click-outside-to-close overlay (role=\"presentation\" \u2014 not an interactive control).\n Keyboard: the component binds a document Escape listener and renders a labelled close button. -->\n <div class=\"sce-mobile-menu__overlay\" role=\"presentation\" [attr.data-locale]=\"locale()\" (click)=\"close()\">\n <!-- stopPropagation keeps a click INSIDE the panel from closing the menu. It is not an\n interactive control, so a key handler here would be meaningless; Escape closes it. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n <aside\n class=\"sce-mobile-menu__panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-label]=\"'nav.menu' | translate\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"sce-mobile-menu__panel-header\">\n <span class=\"sce-mobile-menu__panel-title\">{{ 'nav.menu' | translate }}</span>\n <button type=\"button\" class=\"sce-mobile-menu__close-btn\" [attr.aria-label]=\"'nav.closeMenu' | translate\" (click)=\"close()\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M6 6l12 12M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" />\n </svg>\n </button>\n </div>\n\n <nav class=\"sce-mobile-menu__nav\" [attr.aria-label]=\"'aria.primaryNavigation' | translate\">\n @for (item of items(); track item.href) {\n <a\n [routerLink]=\"item.href\"\n sceRouteActive=\"sce-mobile-menu__nav-link--active\"\n [sceRouteActiveOptions]=\"{ exact: true }\"\n class=\"sce-mobile-menu__nav-link\"\n sceRoutePrefetch\n (click)=\"close()\"\n >\n {{ item.label }}\n </a>\n }\n </nav>\n </aside>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";sce-landing-mobile-menu{display:inline-flex;align-items:center}.sce-mobile-menu__trigger{display:inline-flex;align-items:center;justify-content:center;width:var(--space-40);height:var(--space-40);padding:0;border:1px solid var(--landing-header-theme-border, var(--border-subtle, var(--color-border)));border-radius:var(--radius-lg);background:var(--landing-header-theme-bg, transparent);color:var(--header-fg, var(--color-fg));cursor:pointer;flex-shrink:0}.sce-mobile-menu__trigger:hover{background:var(--landing-header-theme-bg-hover, var(--surface-section-soft, rgba(0, 0, 0, .04)))}.sce-mobile-menu__trigger:focus-visible{outline:2px solid var(--color-brand-secondary-400);outline-offset:2px}.sce-mobile-menu__trigger-icon{width:var(--space-24);height:var(--space-24);color:inherit}@media(max-width:640px){.sce-mobile-menu__trigger{width:var(--space-32);height:var(--space-32)}.sce-mobile-menu__trigger-icon{width:1.15rem;height:1.15rem}}@media(max-width:400px){.sce-mobile-menu__trigger{width:var(--space-28);height:var(--space-28)}.sce-mobile-menu__trigger-icon{width:var(--space-16);height:var(--space-16)}}.sce-mobile-menu__overlay{position:fixed;inset:0;z-index:1200;display:block;margin:0;padding:0;border:0;background:var(--color-overlay-strong, rgba(0, 0, 0, .5));animation:sce-lmm-overlay-in .16s ease-out}.sce-mobile-menu__panel{position:fixed;inset-block:0;inset-inline-start:0;inset-inline-end:auto;width:min(var(--space-320, 20rem),82vi);max-width:var(--space-320, 20rem);height:100dvb;max-height:100dvb;display:flex;flex-direction:column;gap:var(--space-8);padding:var(--space-16);box-sizing:border-box;background:var(--color-surface, var(--color-bg, var(--background-bg-primary)));color:var(--color-fg);border-inline-end:1px solid var(--color-border);box-shadow:var(--shadow-overlay-lg, 0 12px 40px rgba(0, 0, 0, .25));animation:sce-lmm-panel-in .2s ease-out;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.sce-mobile-menu__panel-header{display:flex;align-items:center;justify-content:space-between;padding-block-end:var(--space-12);margin-block-end:var(--space-4);border-block-end:1px solid var(--color-border)}.sce-mobile-menu__panel-title{font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);color:var(--color-fg)}.sce-mobile-menu__close-btn{display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;border:0;border-radius:var(--radius-lg);background:transparent;color:var(--color-fg);cursor:pointer}.sce-mobile-menu__close-btn:hover{background:var(--surface-section-soft, rgba(0, 0, 0, .06))}.sce-mobile-menu__close-btn:focus-visible{outline:2px solid var(--color-brand-secondary-400);outline-offset:2px}.sce-mobile-menu__nav{display:flex;flex-direction:column;gap:var(--space-4)}.sce-mobile-menu__nav-link{display:block;padding:var(--space-12) .75rem;border-radius:var(--radius-lg);text-decoration:none;font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);color:var(--color-fg);opacity:var(--opacity-85)}.sce-mobile-menu__nav-link:hover{opacity:1;background:var(--surface-section-soft, rgba(0, 0, 0, .04))}.sce-mobile-menu__nav-link--active{opacity:1;color:var(--color-brand-secondary-600);background:var(--surface-section-soft, rgba(0, 0, 0, .04))}.sce-mobile-menu__nav-link:focus-visible{outline:2px solid var(--color-brand-secondary-400);outline-offset:2px;opacity:1}@keyframes sce-lmm-overlay-in{0%{opacity:0}to{opacity:1}}@keyframes sce-lmm-panel-in{0%{transform:translate(calc(var(--dir) * -100%))}to{transform:translate(0)}}\n"] }]
4390
4455
  }], ctorParameters: () => [], propDecorators: { overlayTpl: [{ type: i0.ViewChild, args: ['menuOverlay', { isSignal: true }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }] } });
4391
4456
 
4457
+ /** Button that switches the app between Arabic and English through LanguageService, labelled with the language it will switch to rather than the current one. */
4392
4458
  class SceLangToggleComponent {
4393
4459
  language = inject(LanguageService);
4394
4460
  translate = inject(TranslateService);
@@ -4411,6 +4477,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4411
4477
  args: [{ host: { class: 'sce-lang-toggle' }, selector: 'sce-lang-toggle', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button type=\"button\" class=\"langToggle\" [class.langToggle--lab]=\"lightContext()\" [attr.aria-label]=\"ariaLabel()\" (click)=\"toggle()\">\n {{ nextLabel() }}\n</button>\n", styles: ["@charset \"UTF-8\";.langToggle{border:0;background:transparent;padding:0;cursor:pointer;font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-md);font-weight:700;font-style:normal;line-height:1.4;color:var(--header-fg)}.langToggle--lab{color:var(--text-text-primary-900)}@media(max-width:640px){.langToggle{font-size:var(--font-size-sm)}}\n"] }]
4412
4478
  }], propDecorators: { lightContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "lightContext", required: false }] }] } });
4413
4479
 
4480
+ /** Light/dark theme switcher backed by ThemeService, with labels falling back to translated defaults. */
4414
4481
  class SceThemeSwitcherComponent {
4415
4482
  themeService = inject(ThemeService);
4416
4483
  translate = inject(TranslateService);
@@ -4459,6 +4526,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4459
4526
  args: [{ host: { class: 'sce-theme-toggle-button' }, selector: 'sce-theme-toggle-button', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button type=\"button\" class=\"sce-theme-toggle\" [attr.aria-label]=\"ariaLabel()\" [title]=\"ariaLabel()\" (click)=\"toggle()\">\n <i class=\"pi\" [class.pi-moon]=\"theme() === 'light'\" [class.pi-sun]=\"theme() === 'dark'\" aria-hidden=\"true\"></i>\n</button>\n", styles: ["sce-theme-toggle-button{display:inline-flex}sce-theme-toggle-button .sce-theme-toggle{flex-shrink:0;width:var(--space-40);height:var(--space-40);border-radius:var(--radius-pill);border:1px solid var(--account-switcher-menu-theme-border, var(--border-subtle));background:var(--account-switcher-menu-theme-bg, var(--surface-primary));color:var(--account-switcher-menu-theme-color, var(--text-text-primary-900));display:inline-flex;align-items:center;justify-content:center;cursor:pointer;font-size:var(--font-size-lg-18);line-height:1;padding:0;transition:background .15s ease,border-color .15s ease}sce-theme-toggle-button .sce-theme-toggle:hover{background:var(--account-switcher-menu-theme-bg-hover, var(--surface-section-soft));border-color:var(--account-switcher-menu-theme-border-hover, var(--control-border))}\n"] }]
4460
4527
  }] });
4461
4528
 
4529
+ /** Thin wrapper over `sce-confirm-dialog` for approve/reject actions, offering a convenience reason-textarea API (`showReasonInput` and friends) alongside the legacy `field` config, which wins when both are supplied. */
4462
4530
  class SceActionDialogComponent {
4463
4531
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
4464
4532
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -4540,6 +4608,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4540
4608
  }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: true }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: true }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], confirmDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmDisabled", required: false }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], showReasonInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "showReasonInput", required: false }] }], reasonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonLabel", required: false }] }], reasonPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonPlaceholder", required: false }] }], reasonValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonValue", required: false }] }], reasonRequired: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonRequired", required: false }] }], reasonError: [{ type: i0.Input, args: [{ isSignal: true, alias: "reasonError", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], confirm: [{ type: i0.Output, args: ["confirm"] }], reasonChange: [{ type: i0.Output, args: ["reasonChange"] }], fieldChange: [{ type: i0.Output, args: ["fieldChange"] }] } });
4541
4609
 
4542
4610
  let nextFormDialogId = 0;
4611
+ /** Dialog shell for forms, with submit/cancel footer buttons, an optional secondary action and an error banner; the footer submit button lives outside the projected `<form>` and is wired to it by a generated id, so submission goes through the native form submit event. */
4543
4612
  class SceFormDialogComponent {
4544
4613
  translate = inject(TranslateService);
4545
4614
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
@@ -4605,6 +4674,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4605
4674
  args: [{ host: { class: 'sce-form-dialog' }, selector: 'sce-form-dialog', standalone: true, imports: [SceDialogShellComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"title()\"\n [subtitle]=\"subtitle()\"\n [size]=\"size()\"\n [locked]=\"isSubmitting()\"\n [dismissableMask]=\"dismissableMask() ?? !isSubmitting()\"\n (close)=\"onClose()\"\n>\n <form [id]=\"formId\" class=\"form\" (submit)=\"onSubmit($event)\" novalidate>\n <div class=\"bodySections\">\n @if (errorMessage()) {\n <p class=\"errorBanner\">{{ errorMessage() }}</p>\n }\n <ng-content />\n </div>\n </form>\n\n <div dialogFooter [class]=\"secondaryAction() ? 'footerActions' : 'footerActionsPair'\">\n @if (secondaryAction(); as secondary) {\n @if (secondaryActionPosition() === 'first') {\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"isSubmitting() || secondary.disabled\" (click)=\"onSecondaryAction()\">\n {{ secondary.label }}\n </button>\n }\n @if (secondaryActionPosition() === 'last') {\n <button type=\"submit\" [attr.form]=\"formId\" [class]=\"submitBtnClass()\" [disabled]=\"isSubmitting()\">\n {{ resolvedSubmitLabel() }}\n </button>\n }\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"isSubmitting()\" (click)=\"onClose()\">\n {{ resolvedCancelLabel() }}\n </button>\n @if (secondaryActionPosition() === 'last') {\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"isSubmitting() || secondary.disabled\" (click)=\"onSecondaryAction()\">\n {{ secondary.label }}\n </button>\n } @else {\n <button type=\"submit\" [attr.form]=\"formId\" [class]=\"submitBtnClass()\" [disabled]=\"isSubmitting()\">\n {{ resolvedSubmitLabel() }}\n </button>\n }\n } @else {\n <button type=\"button\" class=\"btn cancel\" [disabled]=\"isSubmitting()\" (click)=\"onClose()\">\n {{ resolvedCancelLabel() }}\n </button>\n <button type=\"submit\" [attr.form]=\"formId\" [class]=\"submitBtnClass()\" [disabled]=\"isSubmitting()\">\n {{ resolvedSubmitLabel() }}\n </button>\n }\n </div>\n</sce-dialog-shell>\n", styles: ["@charset \"UTF-8\";.form{display:contents}.bodySections{display:grid;gap:var(--space-20)}.section{display:grid;gap:var(--space-12)}.sectionTitle{margin:0;color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--font-weight-semibold)}.row{display:grid;grid-template-columns:1fr;gap:var(--space-12)}@media(min-width:520px){.row{grid-template-columns:repeat(2,minmax(0,1fr))}}.errorBanner{margin:0;padding:var(--space-10) var(--space-14);border-radius:var(--radius-10);border:1px solid var(--color-red-200);background:var(--color-red-100);color:var(--color-red-800);font-size:var(--font-size-sm);font-weight:500}.btn{width:100%;min-height:var(--space-48);border-radius:var(--radius-10);padding:var(--space-10) var(--space-20);font-family:var(--font-family-arabic-primary);font-weight:600;font-size:var(--font-size-md-15);text-align:center;border:1px solid transparent;cursor:pointer;transition:background .15s ease,border-color .15s ease,color .15s ease,opacity .15s ease}.btn:disabled{opacity:.55;cursor:not-allowed}.cancel{border-color:var(--background-bg-brand-solid);color:var(--text-text-brand-primary);background:var(--color-surface)}.cancel:hover:not(:disabled){background:var(--app-surface-hover);border-color:var(--background-bg-brand-solid)}.submitPrimary{background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.submitPrimary:hover:not(:disabled){background:var(--button-background-primary-bg-hover)}.submitDanger{background:var(--button-background-destructive-bg-primary);color:var(--text-text-primaryon-brand)}.submitDanger:hover:not(:disabled){background:var(--button-background-destructive-bg-hover)}.submitSuccess{background:var(--color-kiwi-700);color:var(--text-text-primaryon-brand)}.sce-form-dialog .footerActions,.sce-form-dialog .footerActionsPair{grid-column:1/-1;display:grid;gap:var(--space-12);width:100%}.sce-form-dialog .footerActions{grid-template-columns:repeat(3,minmax(0,1fr))}.sce-form-dialog .footerActionsPair{grid-template-columns:repeat(2,minmax(0,1fr))}.sce-form-dialog .footerActions .btn,.sce-form-dialog .footerActionsPair .btn{display:block;width:100%;min-height:var(--space-48);box-sizing:border-box}\n"] }]
4606
4675
  }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], isSubmitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmitting", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], dismissableMask: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissableMask", required: false }] }], secondaryAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryAction", required: false }] }], secondaryActionPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryActionPosition", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], submitForm: [{ type: i0.Output, args: ["submitForm"] }], submitValues: [{ type: i0.Output, args: ["submitValues"] }], secondaryActionClick: [{ type: i0.Output, args: ["secondaryActionClick"] }] } });
4607
4676
 
4677
+ /** Optionally-titled section wrapper for grouping projected fields inside `sce-form-dialog`, laid out in one or two columns. */
4608
4678
  class SceFormDialogSectionComponent {
4609
4679
  title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : /* istanbul ignore next */ []));
4610
4680
  twoColumn = input(false, ...(ngDevMode ? [{ debugName: "twoColumn" }] : /* istanbul ignore next */ []));
@@ -4616,6 +4686,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4616
4686
  args: [{ host: { class: 'sce-form-dialog-section' }, selector: 'sce-form-dialog-section', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"section\">\n @if (title()) {\n <h3 class=\"sectionTitle\">{{ title() }}</h3>\n }\n <div [class]=\"twoColumn() ? 'row' : 'section'\">\n <ng-content />\n </div>\n</section>\n", styles: [":host{display:block}.sce-form-dialog-section{display:contents}\n"] }]
4617
4687
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], twoColumn: [{ type: i0.Input, args: [{ isSignal: true, alias: "twoColumn", required: false }] }] } });
4618
4688
 
4689
+ /** Single-expand accordion that renders a list of title/content items, toggling one open panel at a time. */
4619
4690
  class SceAccordionComponent {
4620
4691
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
4621
4692
  className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
@@ -4634,6 +4705,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4634
4705
  args: [{ host: { class: 'sce-accordion' }, selector: 'sce-accordion', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"accordion\" [class]=\"className()\">\n @for (item of items(); track item.id) {\n <div class=\"accordion__item\" [class]=\"itemClassName()\">\n <button type=\"button\" (click)=\"toggle(item.id)\" class=\"accordion__header\" [class]=\"headerClassName()\">\n <span class=\"accordion__title\">{{ item.title }}</span>\n <span class=\"accordion__icon\">\n {{ openId() === item.id ? '\u2212' : '+' }}\n </span>\n </button>\n @if (openId() === item.id) {\n <div class=\"accordion__content\" [class]=\"contentClassName()\">\n <p class=\"accordion__text\">{{ item.content }}</p>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".accordion{display:flex;flex-direction:column;gap:var(--space-12)}.accordion__item{border-radius:var(--space-16);overflow:hidden;background:var(--color-surface)}.accordion__header{width:100%;padding:var(--space-16) var(--space-24);display:flex;align-items:center;justify-content:space-between;background:transparent;border:0;cursor:pointer;font-family:inherit;text-align:inherit;transition:background-color .2s ease}.accordion__header:hover{background-color:#00000005}.accordion__title{color:var(--text-text-primary-900);font-weight:var(--font-weight-semibold);font-size:var(--font-size-lg)}.accordion__icon{font-size:var(--space-20);line-height:1;color:var(--text-text-primary-900);display:inline-flex;align-items:center;justify-content:center;transition:transform .2s ease}.accordion__content{padding:var(--space-16) var(--space-24);background:var(--color-surface)}.accordion__text{color:var(--text-text-secondary-700);font-size:var(--font-size-md, .875rem);line-height:1.5;margin:0}\n"] }]
4635
4706
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], itemClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClassName", required: false }] }], headerClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerClassName", required: false }] }], contentClassName: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentClassName", required: false }] }] } });
4636
4707
 
4708
+ /** Horizontal wizard progress indicator with three `variant`s (numbered `steps`, a `progress` bar, or `pills`), optional per-step error markers, and click-to-navigate gated by `clickable` (off by default) plus an `isStepClickable` predicate; uses `ViewEncapsulation.None`. */
4637
4709
  class SceHorizontalWizardStepperComponent {
4638
4710
  translate = inject(TranslateService);
4639
4711
  steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
@@ -4725,6 +4797,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4725
4797
  args: [{ host: { class: 'sce-horizontal-wizard-stepper' }, selector: 'sce-horizontal-wizard-stepper', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (variant() === 'steps') {\n <div class=\"mobileRoot\">\n <div class=\"mobileHeader\">\n <h2 class=\"mobileHeaderTitle\">{{ activeStep().title }}</h2>\n <p class=\"mobileHeaderSubtitle\">\n {{ 'stepper.fillRequiredData' | translate }}\n </p>\n <span class=\"mobileProgress\">\n {{ 'stepper.stepProgress' | translate: { current: currentStep(), total: steps().length } }}\n </span>\n </div>\n\n <div class=\"horizontalTrack\" role=\"list\" [attr.aria-label]=\"'stepper.formSteps' | translate\">\n <div [class]=\"'horizontalStepsRow ' + rowDirClass()\">\n @for (step of stepViews(); track step.id; let i = $index; let first = $first; let last = $last) {\n <div class=\"horizontalStepItem\" role=\"listitem\">\n <div class=\"horizontalStepTrack\">\n @if (!first) {\n <div\n [class]=\"'horizontalLine horizontalLineBefore' + (currentStep() > steps()[i - 1].id ? ' horizontalLineCompleted' : '')\"\n aria-hidden=\"true\"\n ></div>\n } @else {\n <span class=\"horizontalLineSpacer\" aria-hidden=\"true\"></span>\n }\n\n @if (errorSet().has(step.id) && showErrors()) {\n <button\n type=\"button\"\n [class]=\"step.circleClass\"\n (click)=\"showError.emit(step.id)\"\n [attr.aria-label]=\"showErrorLabel() + ': ' + step.title\"\n [attr.aria-invalid]=\"true\"\n [title]=\"showErrorLabel()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n } @else if (step.isClickable) {\n <button\n type=\"button\"\n [class]=\"step.circleClass + ' horizontalCircleButton'\"\n (click)=\"stepClick.emit(step.id)\"\n [attr.aria-current]=\"currentStep() === step.id ? 'step' : null\"\n [attr.aria-label]=\"step.title\"\n [attr.aria-invalid]=\"errorSet().has(step.id) ? true : null\"\n >\n {{ step.stepContent }}\n </button>\n } @else {\n <div [class]=\"step.circleClass\">\n {{ step.stepContent }}\n </div>\n }\n\n @if (!last) {\n <div\n [class]=\"'horizontalLine horizontalLineAfter' + (currentStep() > step.id ? ' horizontalLineCompleted' : '')\"\n aria-hidden=\"true\"\n ></div>\n } @else {\n <span class=\"horizontalLineSpacer\" aria-hidden=\"true\"></span>\n }\n </div>\n\n @if (step.isClickable) {\n <button\n type=\"button\"\n [attr.data-step-id]=\"step.id\"\n class=\"horizontalStepButton horizontalStepClickable\"\n (click)=\"stepClick.emit(step.id)\"\n [attr.aria-current]=\"currentStep() === step.id ? 'step' : null\"\n [attr.aria-label]=\"step.title\"\n [attr.aria-invalid]=\"errorSet().has(step.id) ? true : null\"\n >\n <span [class]=\"step.labelClass\">{{ step.title }}</span>\n </button>\n } @else {\n <div\n [attr.data-step-id]=\"step.id\"\n class=\"horizontalStepButton\"\n [attr.aria-current]=\"currentStep() === step.id ? 'step' : null\"\n [attr.aria-invalid]=\"errorSet().has(step.id) ? true : null\"\n >\n <span [class]=\"step.labelClass\">{{ step.title }}</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n} @else if (isProgressVariant()) {\n <div\n class=\"stepper-progress\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"progressPercent()\"\n [attr.aria-label]=\"progressPercent() + '%'\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <div class=\"stepper-progress__header\">\n <span class=\"stepper-progress__label\">{{ activeStep().title }}</span>\n <span class=\"stepper-progress__percent\">{{ progressPercent() }}%</span>\n </div>\n <div class=\"stepper-progress__track\">\n <div class=\"stepper-progress__fill\" [style.width.%]=\"progressPercent()\"></div>\n </div>\n <span class=\"stepper-progress__step-count\">\n {{ 'stepper.stepProgress' | translate: { current: currentStep(), total: steps().length } }}\n </span>\n </div>\n} @else if (isPillsVariant()) {\n <div class=\"stepper-pills\" role=\"list\" [attr.aria-label]=\"'stepper.formSteps' | translate\">\n @for (step of stepViews(); track step.id) {\n <button\n type=\"button\"\n class=\"stepper-pills__pill\"\n [class.stepper-pills__pill--active]=\"currentStep() === step.id\"\n [class.stepper-pills__pill--completed]=\"step.isCompleted\"\n [class.stepper-pills__pill--error]=\"errorSet().has(step.id)\"\n [disabled]=\"!step.isClickable\"\n (click)=\"stepClick.emit(step.id)\"\n role=\"listitem\"\n [attr.aria-current]=\"currentStep() === step.id ? 'step' : null\"\n >\n @if (step.isCompleted && !errorSet().has(step.id)) {\n <span class=\"stepper-pills__check\" aria-hidden=\"true\">\u2713</span>\n }\n {{ step.title }}\n </button>\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";.mobileRoot{width:100%;min-width:0;box-sizing:border-box;border-radius:var(--space-16);background:var(--color-surface);padding:var(--space-16)}@media(min-width:1024px){.mobileRoot{display:none}}.mobileHeader{margin-block-end:var(--space-12)}.mobileHeaderTitle{margin:0;font-family:var(--font-family-arabic-primary);font-size:var(--font-size-lg);font-weight:700;color:var(--text-text-display)}.mobileHeaderSubtitle{margin:.35rem 0 0;font-family:var(--font-family-arabic-primary);font-size:var(--font-size-sm);color:var(--text-text-secondary-600)}.mobileProgress{display:inline-block;margin-block-start:.35rem;font-family:var(--font-family-arabic-primary);font-size:var(--font-size-xs);font-weight:600;color:var(--text-text-secondary-600)}.horizontalTrack{width:100%;min-width:0}.horizontalStepsRow{display:flex;width:100%;align-items:flex-start;direction:rtl}.horizontalRowLtr{direction:ltr}.horizontalStepItem{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center}.horizontalStepTrack{display:flex;width:100%;align-items:center;min-height:var(--space-32)}.horizontalLine{flex:1 1 auto;min-width:0;height:var(--space-2);align-self:center;background:var(--color-neutral-300);z-index:0}.horizontalLineBefore{margin-inline-end:-1rem}.horizontalLineAfter{margin-inline-start:-1rem}.horizontalLineCompleted{background:var(--color-success-600)}.horizontalLineSpacer{flex:1 1 auto;min-width:0;height:var(--space-2);visibility:hidden}.horizontalCircleButton,.circleErrorAction{padding:0;border-width:var(--space-2);border-style:solid;cursor:pointer;font:inherit}.horizontalCircleButton:focus-visible,.circleErrorAction:focus-visible{outline:2px solid var(--color-success-600);outline-offset:2px}.circleErrorAction:focus-visible{outline-color:var(--color-red-700)}.circleErrorAction:hover{background:var(--color-red-300)}.horizontalStepButton{display:flex;width:100%;min-width:0;flex-direction:column;align-items:center;margin-block-start:var(--space-8);padding:.125rem .2rem;border:0;background:transparent;text-align:center;cursor:default;border-radius:var(--space-8);transition:background .15s ease}.horizontalStepClickable{cursor:pointer}.horizontalStepClickable:hover{background:var(--color-neutral-100)}.horizontalStepButton:focus-visible{outline:2px solid var(--color-success-600);outline-offset:2px}.horizontalLabel{display:-webkit-box;width:100%;margin:0;font-family:var(--font-family-arabic-primary);font-size:var(--space-10);font-weight:600;line-height:1.25;color:var(--color-neutral-400);-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;text-align:center}.horizontalLabelActive{color:var(--text-text-primary-900)}.horizontalLabelError{color:var(--color-red-700)}.circle{position:relative;z-index:1;display:flex;height:var(--space-32);width:var(--space-32);flex:0 0 2rem;flex-shrink:0;box-sizing:border-box;align-items:center;justify-content:center;border-radius:var(--radius-full);border:2px solid var(--color-neutral-300);background:var(--color-surface);font-size:var(--font-size-md);font-weight:600;color:var(--color-neutral-400)}.circleActive{border-color:var(--color-success-600);background:var(--color-surface);color:var(--text-text-primary-900)}.circleCompleted{border-color:var(--color-success-600);background:var(--color-success-600);color:var(--color-base-white)}.circleError{border-color:var(--color-red-600);background:var(--color-red-200);color:var(--color-red-700)}@media(max-width:380px){.horizontalTrack{overflow-x:auto;-webkit-overflow-scrolling:touch;padding-block-end:var(--space-4)}.horizontalStepsRow{min-width:22rem}}.stepper-progress{width:100%;padding:var(--space-md);box-sizing:border-box}.stepper-progress__header{display:flex;align-items:center;justify-content:space-between;margin-block-end:var(--space-sm)}.stepper-progress__label{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-sm, .875rem);font-weight:600;color:var(--text-text-primary-900)}.stepper-progress__percent{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-sm, .875rem);font-weight:700;color:var(--color-success-600)}.stepper-progress__track{width:100%;height:var(--space-8);border-radius:var(--radius-full);background:var(--color-neutral-200);overflow:hidden}.stepper-progress__fill{height:100%;border-radius:var(--radius-full);background:var(--color-success-600);transition:width .3s ease}.stepper-progress__step-count{display:block;margin-block-start:var(--space-xs);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-xs, .75rem);font-weight:600;color:var(--text-text-secondary-600)}.stepper-pills{display:flex;flex-wrap:wrap;gap:var(--space-sm);width:100%;padding:var(--space-md) 0}.stepper-pills__pill{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--space-sm) var(--space-lg);border:2px solid var(--color-neutral-300);border-radius:var(--radius-full);background:var(--color-surface);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-sm, .875rem);font-weight:600;color:var(--color-neutral-500);cursor:pointer;transition:background .15s,border-color .15s,color .15s}.stepper-pills__pill:disabled{cursor:default}.stepper-pills__pill:not(:disabled):hover{background:var(--color-neutral-100)}.stepper-pills__pill:focus-visible{outline:2px solid var(--color-success-600);outline-offset:2px}.stepper-pills__pill--active{border-color:var(--color-success-600);background:var(--color-surface);color:var(--text-text-primary-900)}.stepper-pills__pill--completed{border-color:var(--color-success-600);background:var(--color-success-600);color:var(--color-base-white)}.stepper-pills__pill--error{border-color:var(--color-red-600);background:var(--color-red-200);color:var(--color-red-700)}.stepper-pills__check{font-size:var(--font-size-xs, .75rem)}\n"] }]
4726
4798
  }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], currentStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentStep", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], errorStepIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStepIds", required: false }] }], isStepClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isStepClickable", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], stepClick: [{ type: i0.Output, args: ["stepClick"] }], showError: [{ type: i0.Output, args: ["showError"] }] } });
4727
4799
 
4800
+ /** Vertical wizard stepper sharing `StepItem` with the horizontal one; unlike that component `clickable` defaults to true, and `errorStepIds` marks steps whose `showError` link is emitted on click. */
4728
4801
  class SceVerticalStepperComponent {
4729
4802
  translate = inject(TranslateService);
4730
4803
  steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
@@ -4833,6 +4906,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4833
4906
  }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], currentStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentStep", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], errorStepIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStepIds", required: false }] }], isStepClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isStepClickable", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], stepClick: [{ type: i0.Output, args: ["stepClick"] }], showError: [{ type: i0.Output, args: ["showError"] }] } });
4834
4907
 
4835
4908
  const SIZE_PX$2 = { sm: 28, md: 42, lg: 56 };
4909
+ /** Branded loading indicator that animates the app logo at a small/medium/large size preset, rendered inline or as a fullscreen overlay. */
4836
4910
  class SceBrandLoaderComponent {
4837
4911
  translate = inject(TranslateService);
4838
4912
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
@@ -4852,6 +4926,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4852
4926
 
4853
4927
  const SIZE_PX$1 = { sm: 24, md: 40, lg: 64 };
4854
4928
  const THICKNESS_PX = { sm: 2.5, md: 3.5, lg: 5 };
4929
+ /** Spinning ring loading indicator drawn with a radial-gradient mask at a size preset, rendered inline or as a fullscreen overlay. */
4855
4930
  class SceRingLoaderComponent {
4856
4931
  translate = inject(TranslateService);
4857
4932
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
@@ -4925,6 +5000,7 @@ function buildGearPath(geo, cx = 32, cy = 32) {
4925
5000
  }
4926
5001
  const PRIMARY_PATH = buildGearPath(PRIMARY_GEAR);
4927
5002
  const SECONDARY_PATH = buildGearPath(SECONDARY_GEAR);
5003
+ /** Loading indicator that renders two meshed, counter-rotating SVG gears whose paths are generated at module load, sized by preset and shown inline or as a fullscreen overlay. */
4928
5004
  class SceGearsLoaderComponent {
4929
5005
  translate = inject(TranslateService);
4930
5006
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
@@ -4948,6 +5024,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4948
5024
  args: [{ host: { class: 'sce-gears-loader' }, selector: 'sce-gears-loader', standalone: true, imports: [NgTemplateOutlet], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #spinnerTpl>\n <span dir=\"ltr\" class=\"sce-gears-loader__spinner\" [style.width.px]=\"containerWidth()\" [style.height.px]=\"primaryPx()\">\n <svg\n viewBox=\"0 0 64 64\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"sce-gears-loader__gear sce-gears-loader__gear--primary\"\n [style.width.px]=\"primaryPx()\"\n [style.height.px]=\"primaryPx()\"\n aria-hidden=\"true\"\n >\n <path [attr.d]=\"primaryPath\" fill=\"currentColor\" fill-rule=\"evenodd\" clip-rule=\"evenodd\" />\n </svg>\n <svg\n viewBox=\"0 0 64 64\"\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"sce-gears-loader__gear sce-gears-loader__gear--secondary\"\n [style.width.px]=\"secondaryPx()\"\n [style.height.px]=\"secondaryPx()\"\n [style.left.px]=\"secondaryLeft()\"\n [style.top.px]=\"secondaryTop()\"\n aria-hidden=\"true\"\n >\n <path [attr.d]=\"secondaryPath\" fill=\"currentColor\" fill-rule=\"evenodd\" clip-rule=\"evenodd\" />\n </svg>\n </span>\n</ng-template>\n\n@if (variant() === 'fullscreen') {\n <div class=\"sce-gears-loader__overlay\" role=\"status\" aria-live=\"polite\" [attr.aria-label]=\"label()\">\n <ng-container *ngTemplateOutlet=\"spinnerTpl\" />\n @if (hintText()) {\n <div class=\"sce-gears-loader__hint\">{{ hintText() }}</div>\n }\n </div>\n} @else {\n <span class=\"sce-gears-loader__inline\" role=\"status\" aria-live=\"polite\" [attr.aria-label]=\"label()\">\n <ng-container *ngTemplateOutlet=\"spinnerTpl\" />\n </span>\n}\n", styles: [".sce-gears-loader{display:contents}.sce-gears-loader__overlay{position:fixed;inset:0;max-height:100svb;z-index:9999;display:flex;align-items:center;justify-content:center;background:var(--overlay-backdrop)}.sce-gears-loader__hint{position:absolute;inset-inline-start:var(--space-16);inset-inline-end:var(--space-16);bottom:var(--space-16);text-align:center;color:color-mix(in srgb,var(--text-text-primaryon-brand) 80%,transparent);font-size:var(--font-size-sm)}.sce-gears-loader__inline{display:inline-flex;align-items:center;justify-content:center}.sce-gears-loader__spinner{position:relative;display:inline-block;color:var(--background-bg-brand-solid)}.sce-gears-loader__gear{position:absolute;transform-origin:50% 50%}.sce-gears-loader__gear--primary{inset-inline-start:0;top:0;animation:spin 3s linear infinite}.sce-gears-loader__gear--secondary{opacity:.7;animation:spin 2.1s linear infinite reverse}\n"] }]
4949
5025
  }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hintText: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintText", required: false }] }] } });
4950
5026
 
5027
+ /** Design-system button that renders an `<a>` when `routerLink` or `href` is set and a `<button>` otherwise; note `fullWidth` defaults to true. */
4951
5028
  class SceButton {
4952
5029
  variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
4953
5030
  type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
@@ -4991,6 +5068,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
4991
5068
  args: [{ host: { class: 'sce-button' }, selector: 'sce-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SceIcon, SceSkeleton, RouterLink, NgTemplateOutlet], template: "<ng-template #inner>\n @if (loading()) {\n <sce-skeleton variant=\"rounded\" width=\"var(--size-18)\" height=\"var(--size-18)\" borderRadius=\"50%\" animation=\"wave\" aria-hidden=\"true\" />\n }\n @if (icon() && iconPosition() === 'start') {\n <sce-icon [name]=\"icon()\" [size]=\"iconSize()\" />\n }\n <ng-content></ng-content>\n @if (icon() && iconPosition() === 'end') {\n <sce-icon [name]=\"icon()\" [size]=\"iconSize()\" />\n }\n</ng-template>\n\n@if (routerLink() !== null) {\n <!-- Anchor mode keeps real link semantics (middle-click, open-in-new-tab). -->\n <a\n [class]=\"classes()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.tabindex]=\"isDisabled() ? -1 : null\"\n [routerLink]=\"routerLink()\"\n >\n <ng-container [ngTemplateOutlet]=\"inner\" />\n </a>\n} @else if (href() !== null) {\n <a\n [class]=\"classes()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.tabindex]=\"isDisabled() ? -1 : null\"\n [href]=\"href()\"\n >\n <ng-container [ngTemplateOutlet]=\"inner\" />\n </a>\n} @else {\n <button [class]=\"classes()\" [attr.aria-label]=\"ariaLabel() || null\" [type]=\"type()\" [disabled]=\"isDisabled()\">\n <ng-container [ngTemplateOutlet]=\"inner\" />\n </button>\n}\n", styles: [":host{display:block}.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-sm);height:var(--size-50);padding:0 var(--space-xl);font-size:var(--font-size-md);font-weight:var(--font-weight-medium);letter-spacing:.01em;border-radius:var(--radius-md);border:none;cursor:pointer;font-family:inherit;text-decoration:none;transition:background-color var(--transition-base),transform var(--transition-fast),box-shadow var(--transition-base)}.btn:active:not(:disabled){transform:scale(.985)}.btn--disabled{pointer-events:none;opacity:.6;cursor:not-allowed}.btn--primary{background-color:var(--color-brand-primary-800);color:var(--color-white)}.btn--secondary{background-color:var(--color-neutral-200);color:var(--color-text)}.btn--secondary:hover:not(:disabled){background-color:var(--color-neutral-300)}.btn--secondary:active:not(:disabled){background-color:var(--color-neutral-400)}.btn--transparent{background-color:transparent;color:var(--color-text)}.btn--transparent:hover:not(:disabled){background-color:var(--color-neutral)}.btn--transparent:active:not(:disabled){background-color:var(--color-neutral-500)}.btn--outline{background-color:transparent;color:var(--color-text);border:1px solid var(--color-border-primary)}.btn--outline:hover:not(:disabled){background-color:var(--color-brand-primary-800);color:var(--color-white)}.btn--outline:active:not(:disabled){background-color:var(--color-brand-primary-900);color:var(--color-white)}.btn--danger{background-color:transparent;color:var(--text-text-error-primary);border:1px solid var(--text-text-error-primary)}.btn--danger:hover:not(:disabled){background-color:var(--color-red-100)}.btn--danger:active:not(:disabled){background-color:var(--color-red-200)}.btn--link{background:none;color:var(--Border-border-success);text-decoration:underline;border:none;height:auto;padding:0;min-height:var(--size-32)}.btn--link:hover:not(:disabled){color:var(--color-primary)}.btn--link:active:not(:disabled){transform:none}.btn--text{background:none;color:var(--color-brand-primary-800);text-decoration:none;border:none;height:auto;padding:0;min-height:var(--size-32);font-weight:var(--font-weight-semibold)}.btn--text:hover:not(:disabled){color:var(--color-brand-primary-900)}.btn--text:active:not(:disabled){transform:none}.btn--black{background-color:var(--color-black);color:var(--color-white)}.btn--black:hover:not(:disabled){color:var(--color-white);background-color:var(--color-neutral-800);box-shadow:var(--shadow-md)}.btn--black:active:not(:disabled){background-color:var(--color-neutral-900);color:var(--color-white)}.btn--neutral{background-color:var(--color-neutral);color:var(--color-text-display)}.btn--neutral:hover:not(:disabled){background-color:var(--color-neutral-300)}.btn--neutral:active:not(:disabled){background-color:var(--color-neutral-400)}.btn--full-width{width:100%}.btn--loading{pointer-events:none;opacity:.8}.btn--compact{height:var(--size-24);padding:0 var(--space-xs)}.btn--mini{height:var(--size-32);font-size:var(--font-size-xs);padding:0 var(--space-sm)}.btn--extra-small{height:var(--size-32);font-size:var(--font-size-xs);padding:0 var(--space-12)}.btn--small-icon-only{height:var(--size-40);font-size:var(--font-size-xs);padding:0 var(--space-10)}.btn--small{height:var(--size-40);font-size:var(--font-size-sm);padding:0 var(--space-lg)}.btn--medium{height:var(--size-52);font-size:var(--font-size-md);padding:0 var(--space-xl)}.btn--large{height:var(--size-56);font-size:var(--font-size-lg);padding:0 var(--space-2xl)}.btn:disabled:not(.btn--loading){opacity:.45;cursor:not-allowed}.btn__spinner{display:inline-block;width:var(--size-18);height:var(--size-18);border:var(--space-2) solid var(--color-white-overlay-30);border-block-start-color:currentColor;border-radius:var(--radius-full);animation:spin .6s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}\n"] }]
4992
5069
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], routerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLink", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }] } });
4993
5070
 
5071
+ /** Labelled checkbox implementing `ControlValueAccessor`, so it works with `formControl`/`ngModel` as well as the `changed` output. */
4994
5072
  class SceCheckbox {
4995
5073
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
4996
5074
  inputId = input(undefined, ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
@@ -5041,6 +5119,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5041
5119
  args: ['class.disabled']
5042
5120
  }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5043
5121
 
5122
+ /** Wraps projected content in a PrimeNG tooltip with the required `text` and a configurable position and z-index. */
5044
5123
  class SceTooltip {
5045
5124
  text = input.required(...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
5046
5125
  position = input('top', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
@@ -5055,6 +5134,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5055
5134
  args: [{ host: { class: 'sce-tooltip' }, selector: 'sce-tooltip', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [Tooltip], template: "<span\n class=\"sce-tooltip__trigger\"\n [pTooltip]=\"text()\"\n [tooltipPosition]=\"position()\"\n [tooltipDisabled]=\"disabled()\"\n appendTo=\"body\"\n [tooltipZIndex]=\"zIndex()\"\n>\n <ng-content />\n</span>\n", styles: [":host{display:block;display:inline-block}.sce-tooltip__trigger{display:inline-block}\n"] }]
5056
5135
  }], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }] } });
5057
5136
 
5137
+ /** Linear progress bar whose fill direction follows the app locale, with an optional label and a leading thumb that is on by default. */
5058
5138
  class SceProgressBar {
5059
5139
  languageService = inject(LanguageService);
5060
5140
  /** Matches app language: Arabic -> rtl (fill from the right), English -> ltr (fill from the left). */
@@ -5080,6 +5160,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5080
5160
  args: [{ host: { class: 'sce-progress-bar' }, selector: 'sce-progress-bar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"progress-bar\"\n [attr.dir]=\"barDir()\"\n [attr.aria-valuenow]=\"progress()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-label]=\"ariaLabel() || percentage() + '%'\"\n role=\"progressbar\"\n>\n <div class=\"progress-bar__track\">\n <div class=\"progress-bar__fill\" [style.width.%]=\"percentage()\" [style.background]=\"color()\"></div>\n </div>\n @if (showThumb()) {\n <span\n class=\"progress-bar__thumb\"\n [style.--progress-bar-thumb-position]=\"percentage() + '%'\"\n [style.background]=\"color()\"\n aria-hidden=\"true\"\n ></span>\n }\n @if (showLabel()) {\n <span class=\"progress-bar__label\">{{ roundedPercentage() }}%</span>\n }\n</div>\n", styles: [":host.sce-progress-bar{display:block}.progress-bar{--progress-bar-thumb-size: var(--size-18);position:relative;display:flex;align-items:center;width:100%;min-height:var(--progress-bar-thumb-size);overflow:visible}.progress-bar__track{width:100%;height:var(--progress-bar-height, var(--size-8));background:var(--color-progress-bar-bg);border-radius:var(--rail-radius)}.progress-bar__fill{height:100%;background:var(--color-primary);border-radius:var(--rail-radius);transition:width .3s ease}.progress-bar__thumb{position:absolute;top:50%;width:var(--progress-bar-thumb-size);height:var(--progress-bar-thumb-size);border-radius:var(--radius-full);background:var(--color-primary);transform:translate(-50%,-50%);transition:inset-inline-start .3s ease,background .2s ease;pointer-events:none;inset-inline-start:var(--progress-bar-thumb-position, 0%)}[dir=rtl] .progress-bar__thumb{margin-inline-start:-var(--space-15,var(--space-15))}.progress-bar__label{position:absolute;top:calc(-1 * var(--space-24));inset-inline-end:0;font-size:var(--font-size-sm);color:var(--color-text-secondary);font-weight:var(--font-weight-medium)}\n"] }]
5081
5161
  }], propDecorators: { progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], showThumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "showThumb", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
5082
5162
 
5163
+ /** SVG ring showing step progress (current of total) with an optional custom label, falling back to the COMMON.STEP_OF translation. */
5083
5164
  class SceCircularProgress {
5084
5165
  /** Current step (1-based). */
5085
5166
  current = input(1, ...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
@@ -5128,6 +5209,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5128
5209
  args: [{ host: { class: 'sce-circular-progress' }, selector: 'sce-circular-progress', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"circular-progress\"\n [style.width.px]=\"size()\"\n [style.height.px]=\"size()\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"current()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"total()\"\n [attr.aria-label]=\"displayLabel()\"\n>\n <svg class=\"circular-progress__svg\" [attr.viewBox]=\"viewBox()\" [attr.width]=\"size()\" [attr.height]=\"size()\">\n <!-- Background track -->\n <circle\n class=\"circular-progress__track\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"strokeWidth()\"\n [attr.stroke]=\"trackColor()\"\n fill=\"none\"\n />\n <!-- Progress segment (clockwise from top) -->\n <circle\n class=\"circular-progress__fill\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"strokeWidth()\"\n [attr.stroke]=\"progressColor()\"\n fill=\"none\"\n [attr.stroke-dasharray]=\"circumference()\"\n [attr.stroke-dashoffset]=\"strokeDashOffset()\"\n [attr.transform]=\"'rotate(-90 ' + center() + ' ' + center() + ')'\"\n />\n </svg>\n <span class=\"circular-progress__label\" [style.font-size.px]=\"labelFontSize()\">\n @if (label()) {\n {{ displayLabel() }}\n } @else {\n {{ 'COMMON.STEP_OF' | translate: stepOfParams() }}\n }\n </span>\n</div>\n", styles: [":host{display:inline-flex}.circular-progress{position:relative;display:flex;align-items:center;justify-content:center}.circular-progress__svg{display:block}.circular-progress__track{transition:stroke .2s}.circular-progress__fill{transition:stroke-dashoffset .3s ease}.circular-progress__label{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-weight:var(--font-weight-semibold);color:var(--color-text-display);line-height:1;text-align:center}\n"] }]
5129
5210
  }], propDecorators: { current: [{ type: i0.Input, args: [{ isSignal: true, alias: "current", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], progressColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "progressColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
5130
5211
 
5212
+ /** Form field label with optional sub-text and a required-marker; `text` is a required input. */
5131
5213
  class SceFormLabel {
5132
5214
  text = input.required(...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
5133
5215
  subText = input(...(ngDevMode ? [undefined, { debugName: "subText" }] : /* istanbul ignore next */ []));
@@ -5140,6 +5222,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5140
5222
  args: [{ host: { class: 'sce-form-label' }, selector: 'sce-form-label', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (text()) {\n <span class=\"form-label\">\n {{ text() }}\n @if (required()) {\n <span class=\"form-label__required\">*</span>\n }\n </span>\n}\n@if (subText()) {\n <span class=\"form-label__sub text-secondary\">{{ subText() }}</span>\n}\n", styles: [":host{display:block}.form-label{display:block;font-size:var(--label-font-size, var(--font-size-sm));font-weight:var(--label-font-weight, var(--font-weight-medium));color:var(--label-color, var(--Form-field-text-label));margin-block-end:var(--space-sm)}.form-label__required{color:var(--color-danger);margin-inline-start:var(--space-xs)}.form-label__sub{display:block;font-size:var(--font-size-md);font-weight:var(--font-weight-regular);margin-block-end:var(--space-sm)}.text-secondary{color:var(--text-secondary-paragraph)}\n"] }]
5141
5223
  }], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], subText: [{ type: i0.Input, args: [{ isSignal: true, alias: "subText", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }] } });
5142
5224
 
5225
+ /** Inline form validation message rendered from a translation key; both `show` and `messageKey` are required inputs. */
5143
5226
  class SceFormError {
5144
5227
  show = input.required(...(ngDevMode ? [{ debugName: "show" }] : /* istanbul ignore next */ []));
5145
5228
  messageKey = input.required(...(ngDevMode ? [{ debugName: "messageKey" }] : /* istanbul ignore next */ []));
@@ -5172,6 +5255,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5172
5255
  * React source: layout/scroll-to-top-button/scroll-to-top-button.tsx
5173
5256
  */
5174
5257
  const SCROLL_THRESHOLD = 280;
5258
+ /** Floating button that appears once the window is scrolled past 280px and scrolls back to the top, using an instant jump when `prefers-reduced-motion` is set. */
5175
5259
  class SceScrollToTopButtonComponent {
5176
5260
  translate = inject(TranslateService);
5177
5261
  ariaLabelOverride = input('', ...(ngDevMode ? [{ debugName: "ariaLabelOverride" }] : /* istanbul ignore next */ []));
@@ -5208,6 +5292,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5208
5292
  args: [{ host: { class: 'sce-scroll-to-top-button' }, selector: 'sce-scroll-to-top-button', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n type=\"button\"\n class=\"button\"\n [attr.data-visible]=\"visible() ? 'true' : 'false'\"\n (click)=\"scrollToTop()\"\n [attr.aria-label]=\"ariaLabel()\"\n>\n <svg class=\"icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M18.5293 13.0298L11.999 19.5601L5.46875 13.0298L6.5293 11.9692L11.999 17.439L17.4688 11.9692L18.5293 13.0298ZM18.5293 6.02979L11.999 12.5601L5.46875 6.02979L6.5293 4.96924L11.999 10.439L17.4688 4.96924L18.5293 6.02979Z\"\n fill=\"currentColor\"\n />\n </svg>\n</button>\n", styles: ["@charset \"UTF-8\";.button{position:fixed;z-index:45;inset-inline-end:max(1rem,env(safe-area-inset-right,0px));bottom:max(5.5rem,1rem + env(safe-area-inset-bottom,0px));width:var(--space-44);height:var(--space-44);border:0;border-radius:var(--radius-full);background:var(--color-brand-primary-800);color:var(--text-on-brand-highlight, var(--background-bg-primary));cursor:pointer;display:inline-flex;align-items:center;justify-content:center;box-shadow:0 8px 24px #00344947;opacity:0;visibility:hidden;pointer-events:none;transform:translateY(.5rem);transition:opacity .25s ease,visibility .25s ease,transform .25s ease,background-color .2s ease}.button[data-visible=true]{opacity:1;visibility:visible;pointer-events:auto;transform:translateY(0)}.button:hover,.button:focus-visible{background:var(--color-brand-primary-700);outline:none}.icon{transform:rotate(180deg)}.icon :where(path,circle,rect,line,polyline,polygon){fill:currentColor}\n"] }]
5209
5293
  }], propDecorators: { ariaLabelOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelOverride", required: false }] }] } });
5210
5294
 
5295
+ /** Full-screen image lightbox with prev/next navigation, arrow-key and Escape handling and body-scroll locking; supplying `activeIndex` switches it from self-managed to parent-controlled paging. */
5211
5296
  class SceImageGallerySwapperComponent {
5212
5297
  open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
5213
5298
  images = input([], ...(ngDevMode ? [{ debugName: "images" }] : /* istanbul ignore next */ []));
@@ -5319,6 +5404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5319
5404
  args: [{ host: { class: 'sce-image-gallery-swapper' }, selector: 'sce-image-gallery-swapper', standalone: true, imports: [TranslatePipe], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open() && total()) {\n <div class=\"overlay\" [dir]=\"dir()\" role=\"dialog\" aria-modal=\"true\" [attr.aria-label]=\"dialogLabel()\">\n <header class=\"header\">\n <button type=\"button\" class=\"closeButton\" (click)=\"onClose()\" [attr.aria-label]=\"'common.close' | translate\">\n <span class=\"closeIcon\" aria-hidden=\"true\">\u00D7</span>\n </button>\n <div class=\"titleBlock\">\n @if (title()?.trim()) {\n <h2 class=\"title\">{{ title() }}</h2>\n }\n <p class=\"counter\">{{ counter() }}</p>\n </div>\n </header>\n\n <div class=\"stage\">\n @if (closeOnBackdropClick()) {\n <button\n type=\"button\"\n class=\"backdropClick\"\n [attr.aria-label]=\"'common.close' | translate\"\n (click)=\"onClose()\"\n tabindex=\"-1\"\n ></button>\n }\n\n @if (showNav()) {\n <button type=\"button\" class=\"navButton navPrev\" (click)=\"prev()\" [attr.aria-label]=\"'gallery.previousImage' | translate\">\n <span class=\"navIcon\" aria-hidden=\"true\">\u2039</span>\n </button>\n }\n\n <div class=\"mainImageWrap\">\n <img [src]=\"current().src\" [alt]=\"current().alt ?? title() ?? ''\" class=\"mainImage\" draggable=\"false\" />\n </div>\n\n @if (showNav()) {\n <button type=\"button\" class=\"navButton navNext\" (click)=\"next()\" [attr.aria-label]=\"'gallery.nextImage' | translate\">\n <span class=\"navIcon\" aria-hidden=\"true\">\u203A</span>\n </button>\n }\n </div>\n\n @if (showNav()) {\n <div class=\"thumbs\" role=\"tablist\" [attr.aria-label]=\"'gallery.thumbnails' | translate\">\n @for (item of items(); track item.src + '-' + $index) {\n <button\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"$index === currentIndex()\"\n [attr.aria-label]=\"('gallery.imageNumber' | translate) + ' ' + ($index + 1)\"\n [class]=\"'thumbButton' + ($index === currentIndex() ? ' thumbActive' : '')\"\n (click)=\"setIndex($index)\"\n >\n <img [src]=\"item.src\" alt=\"\" class=\"thumbImage\" draggable=\"false\" />\n </button>\n }\n </div>\n }\n </div>\n}\n", styles: ["@charset \"UTF-8\";.overlay{position:fixed;inset:0;z-index:1100;display:flex;flex-direction:column;background:var(--color-fg);color:var(--color-base-white)}.header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-16);padding:var(--space-20) var(--space-24) .75rem;flex-shrink:0;flex-direction:row-reverse}.titleBlock{display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-4);min-width:0;text-align:end}.title{margin:0;font-size:var(--font-size-lg-18);font-weight:700;line-height:1.35;color:var(--color-base-white)}.counter{margin:0;font-size:var(--font-size-md);color:var(--color-muted-fg)}.closeButton{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:var(--space-40);height:var(--space-40);border:none;border-radius:var(--radius-pill);background:var(--surface-on-brand-soft);color:var(--color-base-white);cursor:pointer;transition:background .15s ease}.closeButton:hover{background:var(--surface-on-brand-strong)}.closeIcon{font-size:var(--space-20);line-height:1}.stage{position:relative;flex:1;display:flex;align-items:center;justify-content:center;min-height:0;padding:var(--space-8) 4.5rem}.mainImageWrap{max-width:min(var(--size-920),100%);max-height:100%;width:100%;display:flex;align-items:center;justify-content:center}.mainImage{max-width:100%;max-height:min(72vb,var(--size-640));width:auto;height:auto;object-fit:contain;border-radius:var(--radius-14);-webkit-user-select:none;user-select:none}.navButton{position:absolute;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:var(--space-44);height:var(--space-44);border:none;border-radius:var(--radius-pill);background:var(--color-base-white);color:var(--color-fg);cursor:pointer;box-shadow:var(--shadow-image-gallery);transition:transform .15s ease,opacity .15s ease}.navButton:hover:not(:disabled){transform:translateY(-50%) scale(1.04)}.navButton:disabled{opacity:.35;cursor:not-allowed}.navPrev{inset-inline-start:var(--space-20)}.navNext{inset-inline-end:var(--space-20)}.navIcon{font-size:var(--font-size-lg-18);line-height:1;font-weight:700}html[dir=rtl] .navIcon{display:inline-block;transform:scaleX(-1)}.thumbs{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:.65rem;padding:var(--space-16) var(--space-24) var(--space-24);overflow-x:auto}.thumbButton{flex-shrink:0;padding:0;border:2px solid transparent;border-radius:var(--radius-10);background:transparent;cursor:pointer;opacity:.55;transition:opacity .15s ease,border-color .15s ease}.thumbButton:hover{opacity:.85}.thumbActive{border-color:var(--color-base-white);opacity:1}.thumbImage{display:block;width:var(--space-72);height:var(--space-52, var(--size-52));object-fit:cover;border-radius:var(--radius-lg)}.backdropClick{position:absolute;inset:0;z-index:-1}@media(max-width:640px){.stage{padding:var(--space-8) 3.25rem}.navButton{width:2.25rem;height:2.25rem}.thumbImage{width:var(--space-56);height:var(--space-42, var(--size-42))}}\n"] }]
5320
5405
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], images: [{ type: i0.Input, args: [{ isSignal: true, alias: "images", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], initialIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialIndex", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], activeIndexChange: [{ type: i0.Output, args: ["activeIndexChange"] }] } });
5321
5406
 
5407
+ /** Thumbnail grid of an office project's images that opens `sce-image-gallery-swapper` at the clicked index; `imageUrls` and `title` are required. */
5322
5408
  class SceOfficeProjectGalleryComponent {
5323
5409
  imageUrls = input.required(...(ngDevMode ? [{ debugName: "imageUrls" }] : /* istanbul ignore next */ []));
5324
5410
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
@@ -5352,6 +5438,7 @@ var officeProjectGallery_component = /*#__PURE__*/Object.freeze({
5352
5438
  /**
5353
5439
  * React source: feedback/async-page-gate.tsx
5354
5440
  */
5441
+ /** Wraps a page in its loading/error/ready states, showing a skeleton variant while loading and a `sce-result-state` on failure; with the default `recovery` it emits `reloadRequested` and calls `Location.back()` itself. */
5355
5442
  class SceAsyncPageGateComponent {
5356
5443
  translate = inject(TranslateService);
5357
5444
  location = inject(Location);
@@ -5438,6 +5525,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5438
5525
  args: [{ selector: 'sce-offline-banner', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-offline-banner' }, template: "@if (visible()) {\n <div class=\"sce-offline-banner__bar\" role=\"alert\">\n <i class=\"pi pi-wifi sce-offline-banner__icon\" aria-hidden=\"true\"></i>\n <span class=\"sce-offline-banner__text\">\n {{ 'STATUS_PAGES.STATES.NETWORK_OFFLINE.TITLE' | translate }} \u2014\n {{ 'STATUS_PAGES.STATES.NETWORK_OFFLINE.SUBTITLE' | translate }}\n </span>\n </div>\n}\n", styles: [":host{display:block}.sce-offline-banner__bar{position:sticky;inset-block-start:0;z-index:var(--z-index-banner, 1000);display:flex;align-items:center;justify-content:center;gap:var(--space-8);padding:var(--space-8) var(--space-16);background:var(--color-warning-100, var(--color-surface-secondary));color:var(--color-warning-900, var(--color-text-default));border-block-end:var(--border-width-1) solid var(--color-warning-300, var(--color-border-subtle));font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);text-align:center}.sce-offline-banner__icon{font-size:var(--font-size-md);flex-shrink:0}.sce-offline-banner__text{min-width:0}\n"] }]
5439
5526
  }], propDecorators: { forceVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "forceVisible", required: false }] }] } });
5440
5527
 
5528
+ /** Radio group rendering a required list of options with optional descriptions, where a parent can veto a selection through the `onBeforeChange` guard input. */
5441
5529
  class SceRadioButtonComponent {
5442
5530
  options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
5443
5531
  value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -5466,6 +5554,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5466
5554
  args: [{ host: { class: 'sce-radio-button' }, selector: 'sce-radio-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (title()) {\n <h3 class=\"radioGroupTitle\" [id]=\"groupTitleId\">{{ title() }}</h3>\n}\n\n<div class=\"radioGroupGrid\" role=\"radiogroup\" [attr.aria-labelledby]=\"title() ? groupTitleId : null\">\n @for (item of options(); track item.value) {\n <div\n class=\"radioCard\"\n [class.radioCardChecked]=\"value() === item.value\"\n [class.radioCardDisabled]=\"disabled()\"\n role=\"radio\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n [attr.aria-checked]=\"value() === item.value\"\n [attr.aria-disabled]=\"disabled()\"\n (click)=\"tryChange(item.value)\"\n (keydown.enter)=\"tryChange(item.value)\"\n (keydown.space)=\"tryChange(item.value)\"\n >\n <span class=\"radioCircle\" [class.radioCircleChecked]=\"value() === item.value\">\n @if (value() === item.value) {\n <span class=\"radioCircleDot\"></span>\n }\n </span>\n <span class=\"radioContent\">\n <span class=\"radioLabel\" [class.radioLabelChecked]=\"value() === item.value\">\n {{ item.label }}\n </span>\n @if (item.description) {\n <p class=\"radioDescription\">{{ item.description }}</p>\n }\n </span>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.radioGroupTitle{margin:0 0 var(--space-12, var(--space-12));text-align:start;font-size:var(--font-size-md);font-weight:600}.radioGroupGrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}.radioCard{display:flex;align-items:center;gap:var(--space-12);border-radius:var(--radius-xl);border:1px solid var(--color-neutral-200);background:var(--color-surface);padding:var(--space-12) var(--space-16);cursor:pointer;transition:border-color .2s,box-shadow .2s}.radioCard:hover:not(.radioCardDisabled){border-color:var(--color-neutral-300)}.radioCardChecked{border-color:var(--color-success-500)}.radioCardDisabled{opacity:.6;cursor:not-allowed}.radioCircle{display:flex;align-items:center;justify-content:center;width:var(--space-20);height:var(--space-20);flex-shrink:0;border-radius:var(--radius-full);border:2px solid var(--color-neutral-400);transition:border-color .2s}.radioCircleChecked{border-color:var(--color-success-500)}.radioCircleDot{width:var(--space-10);height:var(--space-10);border-radius:var(--radius-full);background-color:var(--color-success-500)}.radioContent{flex:1;text-align:start}.radioLabel{display:block;font-size:var(--font-size-md);font-weight:500;color:var(--color-neutral-400)}.radioLabelChecked{color:var(--text-text-primary-900)}.radioDescription{margin:var(--space-4) 0 0;font-size:var(--font-size-xs);color:var(--form-field-text-placeholder)}\n"] }]
5467
5555
  }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], onBeforeChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "onBeforeChange", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
5468
5556
 
5557
+ /** Dashboard shell that projects a sidebar, header, and main content into a grid; `sidebarCollapsed` narrows the sidebar column, and it uses `ViewEncapsulation.None`. */
5469
5558
  class SceDashboardLayoutComponent {
5470
5559
  sidebarCollapsed = input(false, ...(ngDevMode ? [{ debugName: "sidebarCollapsed" }] : /* istanbul ignore next */ []));
5471
5560
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceDashboardLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -5476,6 +5565,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5476
5565
  args: [{ host: { class: 'sce-dashboard-layout' }, selector: 'sce-dashboard-layout', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-dashboard-layout\" [class.sce-dashboard-layout--collapsed]=\"sidebarCollapsed()\">\n <aside class=\"sce-dashboard-layout__sidebar\">\n <ng-content select=\"[sidebar]\" />\n </aside>\n <div class=\"sce-dashboard-layout__main\">\n <header class=\"sce-dashboard-layout__header\">\n <ng-content select=\"[header]\" />\n </header>\n <main class=\"sce-dashboard-layout__content\">\n <ng-content />\n </main>\n </div>\n</div>\n", styles: [".sce-dashboard-layout{display:flex;min-height:100vb}.sce-dashboard-layout__sidebar{width:var(--size-260);flex-shrink:0;background:var(--sce-sidebar-bg, var(--sce-bg));border-inline-end:1px solid var(--sce-border);transition:width .3s ease}.sce-dashboard-layout--collapsed .sce-dashboard-layout__sidebar{width:var(--space-64)}.sce-dashboard-layout__main{flex:1;display:flex;flex-direction:column;min-width:0}.sce-dashboard-layout__header{height:var(--space-64);display:flex;align-items:center;padding:0 var(--space-24);background:var(--sce-bg);border-block-end:1px solid var(--sce-border)}.sce-dashboard-layout__content{flex:1;padding:var(--space-24);overflow-y:auto}\n"] }]
5477
5566
  }], propDecorators: { sidebarCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarCollapsed", required: false }] }] } });
5478
5567
 
5568
+ /** Page shell for a form: `title`/`subtitle` header, a projected form body, and an action footer; it owns the `<form>` element and re-emits its submit as `submitted`, and uses `ViewEncapsulation.None`. */
5479
5569
  class SceFormPageLayoutComponent {
5480
5570
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
5481
5571
  subtitle = input(...(ngDevMode ? [undefined, { debugName: "subtitle" }] : /* istanbul ignore next */ []));
@@ -5488,6 +5578,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5488
5578
  args: [{ host: { class: 'sce-form-page-layout' }, selector: 'sce-form-page-layout', standalone: true, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-form-page-layout\">\n <header class=\"sce-form-page-layout__header\">\n <h1 class=\"sce-form-page-layout__title\">{{ title() }}</h1>\n @if (subtitle(); as sub) {\n <p class=\"sce-form-page-layout__subtitle\">{{ sub }}</p>\n }\n </header>\n <div class=\"sce-form-page-layout__body\">\n <ng-content />\n </div>\n <footer class=\"sce-form-page-layout__footer\">\n <ng-content select=\"[actions]\" />\n </footer>\n</div>\n", styles: [".sce-form-page-layout{max-width:var(--size-800);margin:0 auto}.sce-form-page-layout__header{margin-block-end:var(--space-32)}.sce-form-page-layout__title{font-size:var(--space-24);font-weight:600;color:var(--sce-text-primary)}.sce-form-page-layout__subtitle{margin-block-start:var(--space-8);font-size:var(--font-size-md);color:var(--sce-text-secondary)}.sce-form-page-layout__body{display:flex;flex-direction:column;gap:var(--space-24)}.sce-form-page-layout__footer{margin-block-start:var(--space-32);display:flex;justify-content:flex-end;gap:var(--space-12);padding-block-start:var(--space-24);border-block-start:1px solid var(--sce-border)}\n"] }]
5489
5579
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
5490
5580
 
5581
+ /** Page shell for a list/table screen: `title` header plus projected filter, toolbar, and content slots; `showFilters` defaults to true, and it uses `ViewEncapsulation.None`. */
5491
5582
  class SceListPageLayoutComponent {
5492
5583
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
5493
5584
  showFilters = input(true, ...(ngDevMode ? [{ debugName: "showFilters" }] : /* istanbul ignore next */ []));
@@ -5510,6 +5601,7 @@ function truncateWords(text, maxWords) {
5510
5601
  }
5511
5602
  return `${words.slice(0, maxWords).join(' ')}...`;
5512
5603
  }
5604
+ /** Header trigger plus popover listing the user's accounts, emitting select/enter-dashboard/logout; requires `selectedAccountId`. */
5513
5605
  class SceAccountSwitcherComponent {
5514
5606
  language = inject(LanguageService);
5515
5607
  elRef = inject(ElementRef);
@@ -5758,6 +5850,7 @@ function placePopover(spotlight, popoverSize) {
5758
5850
  const left = Math.min(maxLeft, Math.max(VIEWPORT_PAD, centeredLeft));
5759
5851
  return { top, left };
5760
5852
  }
5853
+ /** Guided product tour overlay that scrolls to and spotlights each step's target selector and positions a popover beside it, emitting `complete` on the last step and `skip` on Escape. */
5761
5854
  class SceGuidedTourComponent {
5762
5855
  platformId = inject(PLATFORM_ID);
5763
5856
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -5873,6 +5966,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
5873
5966
  args: [{ host: { class: 'sce-guided-tour' }, selector: 'sce-guided-tour', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (active() && currentStep()) {\n <div class=\"root\" [attr.data-locale]=\"locale()\" role=\"presentation\">\n <button type=\"button\" class=\"backdrop\" [attr.aria-label]=\"'landing.tour.skip' | translate\" (click)=\"skip.emit()\"></button>\n\n @if (spotlight()) {\n <div\n class=\"spotlight\"\n [style.top.px]=\"spotlight()!.top\"\n [style.left.px]=\"spotlight()!.left\"\n [style.width.px]=\"spotlight()!.width\"\n [style.height.px]=\"spotlight()!.height\"\n ></div>\n }\n\n <div\n #popoverEl\n class=\"popover\"\n [style.top.px]=\"popoverPos()?.top\"\n [style.left.px]=\"popoverPos()?.left\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"guided-tour-title\"\n aria-describedby=\"guided-tour-body\"\n >\n <h3 class=\"popoverTitle\" id=\"guided-tour-title\">\n {{ currentStep()!.titleKey | translate }}\n </h3>\n <p class=\"popoverBody\" id=\"guided-tour-body\">\n {{ currentStep()!.bodyKey | translate }}\n </p>\n <p class=\"popoverMeta\">\n {{ 'landing.tour.stepOf' | translate: { current: stepIndex() + 1, total: steps().length } }}\n </p>\n\n <div class=\"popoverActions\">\n <button type=\"button\" class=\"skipButton\" (click)=\"skip.emit()\">\n {{ 'landing.tour.skip' | translate }}\n </button>\n <div class=\"popoverActionsEnd\">\n @if (stepIndex() > 0) {\n <button type=\"button\" class=\"backButton\" (click)=\"goBack()\">\n {{ 'landing.tour.back' | translate }}\n </button>\n }\n <button type=\"button\" class=\"nextButton\" (click)=\"goNext()\">\n {{ (isLastStep() ? 'landing.tour.finish' : 'landing.tour.next') | translate }}\n </button>\n </div>\n </div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.root{position:fixed;inset:0;z-index:10000;pointer-events:none}.backdrop{position:fixed;inset:0;background:#0818206b;pointer-events:auto;animation:tourFadeIn .35s ease both}.spotlight{position:fixed;border-radius:var(--radius-lg);box-shadow:0 0 0 9999px #0818209e;border:2px solid var(--color-brand-secondary-500, var(--color-brand-secondary-500));pointer-events:none;transition:top .45s cubic-bezier(.22,1,.36,1),left .45s cubic-bezier(.22,1,.36,1),width .45s cubic-bezier(.22,1,.36,1),height .45s cubic-bezier(.22,1,.36,1);animation:tourPulse 2.4s ease-in-out infinite}.popover{position:fixed;width:min(22rem,100vi - 2rem);padding:var(--space-20) var(--space-20) 1rem;border-radius:var(--radius-lg);background:var(--color-base-white, var(--background-bg-primary));color:var(--text-primary-emphasis);box-shadow:0 18px 48px #00000038;pointer-events:auto;animation:tourFadeUp .35s ease both}.popoverTitle{margin:0;font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-lg, 1.125rem);font-weight:var(--font-weight-bold, 700);line-height:1.4}.popoverBody{margin:var(--space-8) 0 0;font-family:var(--font-almarai),var(--font-family-arabic-secondary),Arial,sans-serif;font-size:var(--font-size-md, 1rem);line-height:1.65;color:var(--text-primary-muted)}.popoverMeta{margin:.85rem 0 0;font-size:var(--font-size-sm, .875rem);color:var(--color-brand-primary-600)}.popoverActions{display:flex;align-items:center;justify-content:space-between;gap:var(--space-12);margin-block-start:var(--space-16)}.popoverActionsEnd{display:flex;align-items:center;gap:var(--space-8)}.skipButton,.backButton{appearance:none;border:0;background:transparent;padding:.35rem .5rem;font-family:inherit;font-size:var(--font-size-sm, .875rem);color:var(--text-primary-muted);cursor:pointer}.skipButton:hover,.backButton:hover{color:var(--text-primary-emphasis)}.nextButton{appearance:none;border:0;border-radius:var(--radius-lg);padding:.55rem 1rem;background:var(--color-brand-secondary-600, var(--color-brand-secondary-600));color:var(--text-on-brand-primary, var(--background-bg-primary));font-family:inherit;font-size:var(--font-size-sm, .875rem);font-weight:var(--font-weight-semibold, 600);cursor:pointer}.nextButton:hover{background:var(--color-brand-secondary-700)}.root[data-locale=en] .popoverTitle,.root[data-locale=en] .popoverBody,.root[data-locale=en] .popoverMeta,.root[data-locale=en] .skipButton,.root[data-locale=en] .backButton,.root[data-locale=en] .nextButton{font-family:var(--font-geist-sans),Arial,sans-serif}@keyframes tourFadeIn{0%{opacity:0}to{opacity:1}}@keyframes tourFadeUp{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes tourPulse{0%,to{box-shadow:0 0 0 9999px #0818209e,0 0 #2fcdc200}50%{box-shadow:0 0 0 9999px #0818209e,0 0 0 4px #2fcdc259}}@media(prefers-reduced-motion:reduce){.backdrop,.popover{animation:none}.spotlight{animation:none;transition:none}}\n"] }]
5874
5967
  }], ctorParameters: () => [], propDecorators: { locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], tourId: [{ type: i0.Input, args: [{ isSignal: true, alias: "tourId", required: false }] }], steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], complete: [{ type: i0.Output, args: ["complete"] }], skip: [{ type: i0.Output, args: ["skip"] }], popoverElRef: [{ type: i0.ViewChild, args: ['popoverEl', { isSignal: true }] }] } });
5875
5968
 
5969
+ /** Dialog that lets the user crop, zoom and rotate a profile photo and emits the result as a JPEG `File`; binding the `applying` input keeps the dialog open for an async upload instead of auto-closing on apply. */
5876
5970
  class SceProfilePhotoEditDialogComponent {
5877
5971
  translate = inject(TranslateService);
5878
5972
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
@@ -6067,6 +6161,7 @@ const DEFAULT_CENTER = isGeoLookupRestricted()
6067
6161
  ? [JEDDAH_MAP_CENTER.lat, JEDDAH_MAP_CENTER.lng]
6068
6162
  : [24.7136, 46.6753];
6069
6163
  const DEFAULT_ZOOM = 6;
6164
+ /** Modal Leaflet map dialog for picking a coordinate, bounded to Saudi Arabia, which validates each click or marker drag, reverse-geocodes the position to an address via Nominatim, and reverts to the last valid point when validation fails. */
6070
6165
  class SceLocationPickerDialogComponent {
6071
6166
  visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
6072
6167
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -6241,6 +6336,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
6241
6336
  args: [{ host: { class: 'sce-location-picker-dialog' }, selector: 'sce-location-picker-dialog', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (visible()) {\n <!-- Click-outside-to-dismiss backdrop. Keyboard users dismiss via the labelled close button\n below, so a key handler here would be cargo-cult, not accessibility. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div class=\"sce-location-picker-overlay\" (click)=\"onOverlayClick($event)\">\n <div class=\"sce-location-picker-dialog\">\n <div class=\"sce-location-picker-dialog__header\">\n <h3>{{ 'GEO.PICKER_TITLE' | translate }}</h3>\n <button\n type=\"button\"\n class=\"sce-location-picker-dialog__close\"\n [attr.aria-label]=\"'common.close' | translate\"\n (click)=\"dialogClose.emit()\"\n >\n &times;\n </button>\n </div>\n <div class=\"sce-location-picker-dialog__map\" #mapContainer></div>\n <div class=\"sce-location-picker-dialog__address\">\n @if (resolvedAddress()) {\n <span>{{ resolvedAddress() }}</span>\n } @else if (isResolving()) {\n <span>...</span>\n }\n </div>\n <div class=\"sce-location-picker-dialog__footer\">\n <button type=\"button\" class=\"sce-location-picker-dialog__cancel\" (click)=\"dialogClose.emit()\">\n {{ 'common.cancel' | translate }}\n </button>\n <button type=\"button\" class=\"sce-location-picker-dialog__confirm\" [disabled]=\"!selectedLat()\" (click)=\"confirmLocation()\">\n {{ 'GEO.CONFIRM_LOCATION' | translate }}\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [".sce-location-picker-overlay{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;background:#00000080}.sce-location-picker-dialog{width:90vi;max-width:var(--size-700);background:var(--color-surface-white);border-radius:var(--radius-lg);overflow:hidden;display:flex;flex-direction:column}.sce-location-picker-dialog__header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-4) var(--space-5);border-block-end:1px solid var(--color-border-light)}.sce-location-picker-dialog__header h3{font-size:var(--font-size-md);font-weight:600;margin:0}.sce-location-picker-dialog__close{background:none;border:none;font-size:var(--font-size-xl);cursor:pointer;color:var(--color-text-secondary);line-height:1}.sce-location-picker-dialog__map{height:var(--size-400);width:100%}.sce-location-picker-dialog__address{padding:var(--space-3) var(--space-5);font-size:var(--font-size-sm);color:var(--color-text-secondary);min-height:var(--space-40);display:flex;align-items:center;border-block-start:1px solid var(--color-border-light)}.sce-location-picker-dialog__footer{display:flex;justify-content:flex-end;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-block-start:1px solid var(--color-border-light)}.sce-location-picker-dialog__cancel{padding:var(--space-2) var(--space-5);font-size:var(--font-size-sm);border:1px solid var(--color-border-default);border-radius:var(--radius-md);background:transparent;cursor:pointer}.sce-location-picker-dialog__confirm{padding:var(--space-2) var(--space-5);font-size:var(--font-size-sm);border:none;border-radius:var(--radius-md);background:var(--color-primary);color:var(--color-text-white);cursor:pointer}.sce-location-picker-dialog__confirm:disabled{opacity:.5;cursor:not-allowed}\n"] }]
6242
6337
  }], ctorParameters: () => [], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], initialLat: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLat", required: false }] }], initialLng: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLng", required: false }] }], dialogClose: [{ type: i0.Output, args: ["dialogClose"] }], confirm: [{ type: i0.Output, args: ["confirm"] }], mapContainer: [{ type: i0.ViewChild, args: ['mapContainer', { isSignal: true }] }] } });
6243
6338
 
6339
+ /** Geo-location field that displays the currently selected coordinates and address and opens `sce-location-picker-dialog` to choose a new one. */
6244
6340
  class SceGeoLocationFieldComponent {
6245
6341
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
6246
6342
  value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -6274,6 +6370,7 @@ var geoLocationField_component = /*#__PURE__*/Object.freeze({
6274
6370
  SceGeoLocationFieldComponent: SceGeoLocationFieldComponent
6275
6371
  });
6276
6372
 
6373
+ /** Dashboard page heading rendering a single translated `<h1>` from `titleKey`; the whole header is omitted when `titleKey` is empty. */
6277
6374
  class DashboardPageHeaderComponent {
6278
6375
  titleKey = input('nav.enterDashboard', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
6279
6376
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: DashboardPageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -6284,6 +6381,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
6284
6381
  args: [{ host: { class: 'sce-dashboard-page-header' }, selector: 'sce-dashboard-page-header', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (titleKey()) {\n <header class=\"pageTop\">\n <div class=\"pageTopHeading\">\n <h1 class=\"pageTopTitle\">{{ titleKey() | translate }}</h1>\n </div>\n </header>\n}\n", styles: [":host{display:block}.sce-dashboard-page-header{display:contents}\n"] }]
6285
6382
  }], propDecorators: { titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
6286
6383
 
6384
+ /** OpenStreetMap Leaflet map that lazily loads Leaflet, renders the given markers and emits map clicks and marker drag-ends; setting `interactive` to false disables panning, zooming, the zoom control and click events. */
6287
6385
  class SceOsmLeafletMapComponent {
6288
6386
  latitude = input(24.7136, ...(ngDevMode ? [{ debugName: "latitude" }] : /* istanbul ignore next */ []));
6289
6387
  longitude = input(46.6753, ...(ngDevMode ? [{ debugName: "longitude" }] : /* istanbul ignore next */ []));
@@ -6397,6 +6495,7 @@ function buildGoogleEmbedUrl(lat, lng, address) {
6397
6495
  }
6398
6496
  return null;
6399
6497
  }
6498
+ /** Read-only map of an office's location: a Leaflet map with a marker when valid coordinates are given, a Google Maps embed built from the address when they are not, and a "not specified" fallback when neither is available. */
6400
6499
  class SceOfficeLocationMapComponent {
6401
6500
  sanitizer = inject(DomSanitizer);
6402
6501
  latitude = input(...(ngDevMode ? [undefined, { debugName: "latitude" }] : /* istanbul ignore next */ []));
@@ -6470,6 +6569,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
6470
6569
  args: ['mapContainer']
6471
6570
  }] } });
6472
6571
 
6572
+ /** Location picker pairing an OSM Leaflet map with a Nominatim search box, which validates every clicked, dragged or searched position before placing a draggable pin and emitting it with its reverse-geocoded address. */
6473
6573
  class SceOsmLocationPickerComponent {
6474
6574
  initialLat = input(isGeoLookupRestricted() ? JEDDAH_MAP_CENTER.lat : 24.7136, ...(ngDevMode ? [{ debugName: "initialLat" }] : /* istanbul ignore next */ []));
6475
6575
  initialLng = input(isGeoLookupRestricted() ? JEDDAH_MAP_CENTER.lng : 46.6753, ...(ngDevMode ? [{ debugName: "initialLng" }] : /* istanbul ignore next */ []));
@@ -6558,6 +6658,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
6558
6658
  args: [{ host: { class: 'sce-osm-location-picker' }, selector: 'sce-osm-location-picker', standalone: true, imports: [FormsModule, TranslatePipe, SceSkeleton, SceOsmLeafletMapComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div>\n <div class=\"searchRow\">\n <input\n class=\"searchInput\"\n type=\"text\"\n [placeholder]=\"'MAPS.SEARCH_PLACEHOLDER' | translate\"\n [(ngModel)]=\"searchQuery\"\n (keydown.enter)=\"onSearch()\"\n />\n <button type=\"button\" class=\"searchButton\" [disabled]=\"isSearching()\" (click)=\"onSearch()\">\n @if (isSearching()) {\n <sce-skeleton variant=\"rounded\" width=\"1.25rem\" height=\"1.25rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'MAPS.SEARCH' | translate }}\n }\n </button>\n </div>\n <p class=\"providerNote\">{{ 'MAPS.PROVIDER_NOTE' | translate }}</p>\n\n <div style=\"height: 300px; margin-top: 0.75rem; border-radius: 0.75rem; overflow: hidden\">\n <sce-osm-leaflet-map\n [latitude]=\"currentLat()\"\n [longitude]=\"currentLng()\"\n [zoom]=\"zoom()\"\n [markers]=\"currentMarkers()\"\n [interactive]=\"true\"\n (mapClick)=\"onMapClick($event)\"\n (markerDragEnd)=\"onMarkerDragEnd($event)\"\n />\n </div>\n\n @if (selectedLocation()) {\n <p style=\"margin: 0.5rem 0 0; font-size: 0.8rem; color: var(--color-text-secondary)\">\n <span dir=\"ltr\">{{ selectedLocation()!.lat.toFixed(6) }}, {{ selectedLocation()!.lng.toFixed(6) }}</span>\n @if (selectedLocation()!.address) {\n \u2014 {{ selectedLocation()!.address }}\n }\n </p>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host.sce-osm-location-picker{display:block}.providerNote{margin:var(--space-4) 0 0;font-size:var(--font-size-xs);color:var(--color-neutral-500)}.searchRow{display:flex;gap:var(--space-8);align-items:stretch}.searchRow .searchInput{flex:1;min-width:0}.searchButton{flex-shrink:0;min-height:var(--space-44, var(--size-44));padding:0 1rem;border:0;border-radius:var(--radius-10);background:var(--button-background-primary-bg-primary);color:var(--color-base-white);font-size:.9rem;font-weight:600;cursor:pointer}.searchButton:disabled{opacity:.55;cursor:not-allowed}.searchFeedback{margin:0;font-size:.8rem;color:var(--color-neutral-600)}.searchResults{margin:0;padding:0;list-style:none;max-height:var(--size-160);overflow:auto;border:1px solid var(--color-neutral-200);border-radius:var(--radius-10)}.searchResultButton{width:100%;padding:.65rem .85rem;border:0;border-block-end:1px solid var(--color-neutral-100);background:var(--color-base-white);text-align:start;font-size:.85rem;color:var(--text-text-primary-900);cursor:pointer}.searchResultButton:hover{background:var(--color-neutral-50)}.searchResults li:last-child .searchResultButton{border-block-end:0}.mapWrapper{position:relative;width:100%;height:var(--size-360);border-radius:var(--radius-xl);overflow:hidden}.inlineMapWrapper{position:relative;width:100%;border-radius:var(--radius-xl);overflow:hidden;border:1px solid var(--color-neutral-200);background:var(--color-neutral-200)}.mapHost{position:absolute;inset:0;z-index:1}.mapHost .leaflet-container{width:100%;height:100%;font-family:inherit;background:var(--color-neutral-200)}.mapHost .leaflet-container img.leaflet-tile.leaflet-tile,.mapHost .leaflet-container img.leaflet-marker-icon.leaflet-marker-icon,.mapHost .leaflet-container img.leaflet-marker-shadow.leaflet-marker-shadow{max-width:none;max-height:none;width:auto;height:auto}.mapHost .leaflet-pane,.mapHost .leaflet-tile-pane,.mapHost .leaflet-overlay-pane{z-index:auto}.mapLoadingOverlay{position:absolute;inset:0;z-index:2;pointer-events:none;background:linear-gradient(90deg,var(--color-neutral-100) 25%,var(--color-neutral-300) 50%,var(--color-neutral-100) 75%);background-size:200% 100%;animation:mapLoadingShimmer 1.2s ease-in-out infinite}.inlineMapShell{position:relative;width:100%}.fullscreenButton{position:absolute;top:.65rem;inset-inline-start:.65rem;z-index:1001;display:inline-flex;align-items:center;justify-content:center;gap:.35rem;min-width:2.25rem;height:2.25rem;padding:0 .55rem;border:0;border-radius:var(--radius-lg);background:#fffffff2;color:var(--text-text-primary-900);box-shadow:0 2px 10px #0000002e;cursor:pointer;pointer-events:auto}.fullscreenButton:hover{background:var(--color-base-white)}.fullscreenButton:focus-visible{outline:2px solid var(--button-background-primary-bg-primary);outline-offset:2px}.fullscreenButtonLabel{font-size:var(--font-size-xs);font-weight:600;line-height:1}.expandedMapWrapper{position:relative;width:100%;height:min(70vb,var(--size-520));border-radius:var(--radius-xl);overflow:hidden}@keyframes mapLoadingShimmer{0%{background-position:100% 0}to{background-position:-100% 0}}\n"] }]
6559
6659
  }], ctorParameters: () => [], propDecorators: { initialLat: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLat", required: false }] }], initialLng: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLng", required: false }] }], zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], locationSelect: [{ type: i0.Output, args: ["locationSelect"] }] } });
6560
6660
 
6661
+ /** Google Maps location picker that lazily injects the Maps JS API, drops a marker where the user clicks and emits the coordinate; it stays blank unless an `apiKey` is supplied. */
6561
6662
  class SceGoogleMapsLocationPickerComponent {
6562
6663
  apiKey = input('', ...(ngDevMode ? [{ debugName: "apiKey" }] : /* istanbul ignore next */ []));
6563
6664
  initialLat = input(24.7136, ...(ngDevMode ? [{ debugName: "initialLat" }] : /* istanbul ignore next */ []));
@@ -6668,6 +6769,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
6668
6769
  args: [{ host: { class: 'sce-overview-stat-sparkline' }, selector: 'sce-overview-stat-sparkline', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg\n [class]=\"className()\"\n width=\"100%\"\n height=\"100%\"\n viewBox=\"0 0 128 29\"\n fill=\"none\"\n preserveAspectRatio=\"none\"\n aria-hidden=\"true\"\n [style.color]=\"color()\"\n>\n <defs>\n <linearGradient [attr.id]=\"gradientId()\" x1=\"64\" y1=\"-13\" x2=\"64.0833\" y2=\"29\" gradientUnits=\"userSpaceOnUse\">\n <stop stop-color=\"currentColor\" />\n <stop offset=\"1\" stop-color=\"currentColor\" stop-opacity=\"0\" />\n </linearGradient>\n <clipPath [attr.id]=\"clipId()\">\n <rect width=\"128\" height=\"29\" fill=\"white\" />\n </clipPath>\n </defs>\n <g [attr.clip-path]=\"'url(#' + clipId() + ')'\">\n <path [attr.d]=\"areaPath\" [attr.fill]=\"'url(#' + gradientId() + ')'\" />\n <path [attr.d]=\"linePath\" stroke=\"currentColor\" stroke-width=\"1.20912\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <circle cx=\"125.167\" cy=\"2.90261\" r=\"1.93459\" fill=\"currentColor\" stroke=\"white\" stroke-width=\"0.967296\" />\n </g>\n</svg>\n", styles: [":host{display:block}.sce-overview-stat-sparkline{display:contents}\n", ":host{display:inline-flex}svg{display:block}\n"] }]
6669
6770
  }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }] } });
6670
6771
 
6772
+ /** Standalone chart legend rendering colour markers and labels in a row or column — used instead of the built-in ECharts legend. */
6671
6773
  class SceChartLegendComponent {
6672
6774
  /** List of legend items to display */
6673
6775
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
@@ -6801,6 +6903,7 @@ function formatItemTooltip(params, valueSuffix = '') {
6801
6903
  </div>`;
6802
6904
  }
6803
6905
 
6906
+ /** ECharts bar chart with optional stacking, overlay line series and a custom legend; axis side auto-detects RTL unless `isRtl` overrides it. */
6804
6907
  class SceBarChartComponent {
6805
6908
  el = inject(ElementRef);
6806
6909
  /** Manual direction override; null auto-detects from computed style (RTL-first default). */
@@ -6914,6 +7017,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
6914
7017
  args: [{ host: { class: 'sce-bar-chart' }, selector: 'sce-bar-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, SceChartLegendComponent], providers: [provideEchartsCore({ echarts })], template: "<div class=\"bar-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div class=\"bar-chart__body\">\n <div echarts [options]=\"chartOptions()\" class=\"bar-chart__canvas\"></div>\n </div>\n @if (showLegend()) {\n <div class=\"bar-chart__legend\">\n <sce-chart-legend [items]=\"legendItems()\" [justifyContent]=\"'start'\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.bar-chart{width:100%;height:100%;position:relative;display:flex;flex-direction:column}.bar-chart__body{flex:1;min-height:0;position:relative}.bar-chart__canvas{width:100%;height:100%}.bar-chart__legend{flex-shrink:0}\n"] }]
6915
7018
  }], ctorParameters: () => [], propDecorators: { isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], overlayLineSeries: [{ type: i0.Input, args: [{ isSignal: true, alias: "overlayLineSeries", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], barWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "barWidth", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }] } });
6916
7019
 
7020
+ /** Pure-CSS horizontal bar chart (no ECharts) where each bar is split into `segments` that fill proportionally to its value. */
6917
7021
  class SceHorizontalBarChartComponent {
6918
7022
  /** Data items for horizontal bars */
6919
7023
  data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -6965,6 +7069,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
6965
7069
  args: [{ host: { class: 'sce-horizontal-bar-chart' }, selector: 'sce-horizontal-bar-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SceIcon], template: "<div class=\"horizontal-bar-chart\">\n @for (item of computedItems(); track item.label; let last = $last) {\n <div class=\"horizontal-bar-chart__item\" [style.margin-bottom.px]=\"last ? 0 : gap()\">\n <div class=\"horizontal-bar-chart__header\">\n <span class=\"horizontal-bar-chart__label\">{{ item.label }}</span>\n @if (showValues()) {\n <span class=\"horizontal-bar-chart__value\" [style.color]=\"item.barColor\">\n {{ item.value }}\n <sce-icon name=\"arrow-left\" [size]=\"18\" [style.color]=\"item.barColor\"></sce-icon>\n </span>\n }\n </div>\n <div class=\"horizontal-bar-chart__segments\">\n <!-- track $index: fixed number of chart segments, derived from the segments() count -->\n @for (fill of item.segmentFills; track $index) {\n <div class=\"horizontal-bar-chart__segment\" [style.height.px]=\"barHeight()\" [style.background-color]=\"trackColor()\">\n <div class=\"horizontal-bar-chart__fill\" [style.width.%]=\"fill\" [style.background-color]=\"item.barColor\"></div>\n </div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.horizontal-bar-chart{width:100%;height:100%;overflow-y:auto}.horizontal-bar-chart__header{display:flex;justify-content:space-between;align-items:center;margin-block-end:var(--space-sm)}.horizontal-bar-chart__label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-neutral-800)}.horizontal-bar-chart__value{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);display:flex;align-items:center;gap:var(--space-xs)}.horizontal-bar-chart__chevron{font-size:var(--font-size-xs);opacity:.7}.horizontal-bar-chart__segments{display:flex;gap:var(--space-xs)}.horizontal-bar-chart__segment{flex:1;border-radius:var(--radius-sm);overflow:hidden;position:relative}.horizontal-bar-chart__fill{height:100%;border-radius:var(--radius-sm);transition:width var(--motion-duration-slow) ease}\n"] }]
6966
7070
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }], defaultColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], barHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "barHeight", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }] } });
6967
7071
 
7072
+ /** ECharts multi-series line chart with optional area fill and a highlight bar/marker at `highlightIndex`; axis side auto-detects RTL unless `isRtl` overrides it. */
6968
7073
  class SceLineChartComponent {
6969
7074
  el = inject(ElementRef);
6970
7075
  /** Manual direction override; null auto-detects from computed style (RTL-first default). */
@@ -7090,6 +7195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7090
7195
  args: [{ host: { class: 'sce-line-chart' }, selector: 'sce-line-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, SceChartLegendComponent], providers: [provideEchartsCore({ echarts })], template: "<div class=\"line-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div class=\"line-chart__wrapper\">\n <div echarts [options]=\"chartOptions()\" class=\"line-chart__canvas\"></div>\n </div>\n @if (showLegend()) {\n <div>\n <sce-chart-legend [items]=\"legendItems()\" [justifyContent]=\"'start'\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.line-chart{display:flex;flex-direction:column;width:100%;height:100%;position:relative}.line-chart__wrapper{flex:1;min-height:0;position:relative}.line-chart__canvas{width:100%;height:100%}\n"] }]
7091
7196
  }], ctorParameters: () => [], propDecorators: { isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }], series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], showArea: [{ type: i0.Input, args: [{ isSignal: true, alias: "showArea", required: false }] }], smooth: [{ type: i0.Input, args: [{ isSignal: true, alias: "smooth", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showXAxisLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showXAxisLabels", required: false }] }], highlightIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightIndex", required: false }] }] } });
7092
7197
 
7198
+ /** ECharts gradient area chart with hidden axes and an optional highlighted point marker at `highlightIndex`. */
7093
7199
  class SceAreaChartComponent {
7094
7200
  /** Data points for the chart */
7095
7201
  data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -7221,6 +7327,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7221
7327
  args: [{ host: { class: 'sce-area-chart' }, selector: 'sce-area-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"area-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div echarts [options]=\"chartOptions()\" class=\"area-chart__canvas\"></div>\n</div>\n", styles: [":host{display:block}.area-chart{width:100%;height:100%;position:relative}.area-chart__canvas{width:100%;height:100%}\n"] }]
7222
7328
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], startColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "startColor", required: false }] }], endColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "endColor", required: false }] }], smooth: [{ type: i0.Input, args: [{ isSignal: true, alias: "smooth", required: false }] }], tooltipLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipLabel", required: false }] }], highlightIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightIndex", required: false }] }] } });
7223
7329
 
7330
+ /** ECharts pie chart with optional in-slice percentage labels, an optional centre hole and a custom legend. */
7224
7331
  class ScePieChartComponent {
7225
7332
  /** Data items for the pie segments */
7226
7333
  data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -7304,6 +7411,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7304
7411
  args: [{ host: { class: 'sce-pie-chart' }, selector: 'sce-pie-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, SceChartLegendComponent], providers: [provideEchartsCore({ echarts })], template: "<div class=\"pie-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div class=\"pie-chart__wrapper\">\n <div echarts [options]=\"chartOptions()\" class=\"pie-chart__canvas\"></div>\n </div>\n @if (showLegend()) {\n <div>\n <sce-chart-legend [items]=\"legendItems()\" [justifyContent]=\"'start'\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}.pie-chart{display:flex;flex-direction:column;width:100%;height:100%;position:relative}.pie-chart__wrapper{flex:1;min-height:0;position:relative}.pie-chart__canvas{width:100%;height:100%}\n"] }]
7305
7412
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], radius: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], showLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabels", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], showCenterHole: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCenterHole", required: false }] }], innerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerRadius", required: false }] }], itemRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemRadius", required: false }] }] } });
7306
7413
 
7414
+ /** Concentric ring ("donut") chart where each data item gets its own gauge ring sized against `maxRingValue`, with optional centred value and label. */
7307
7415
  class SceDonutChartComponent {
7308
7416
  /** Data items for the donut rings */
7309
7417
  data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -7469,6 +7577,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7469
7577
  args: [{ host: { class: 'sce-donut-chart' }, selector: 'sce-donut-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective, SceChartLegendComponent], providers: [provideEchartsCore({ echarts })], template: "<div class=\"donut-chart\" [style.height.px]=\"height()\">\n <div class=\"donut-chart__wrapper\">\n <div echarts [options]=\"chartOptions()\" class=\"donut-chart__canvas\"></div>\n </div>\n @if (showLegend()) {\n <div>\n <sce-chart-legend [items]=\"legendItems()\" [justifyContent]=\"'start'\" />\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.donut-chart{display:flex;flex-direction:column;width:100%;height:100%;position:relative}.donut-chart__wrapper{flex:1;min-height:0;position:relative}.donut-chart__canvas{width:100%;height:100%}\n"] }]
7470
7578
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], centerValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerValue", required: false }] }], centerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerLabel", required: false }] }], innerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerRadius", required: false }] }], outerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "outerRadius", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGap", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], maxRingValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRingValue", required: false }] }] } });
7471
7579
 
7580
+ /** ECharts donut ring with a centred label/value and a legend that also shows each item's value; the tooltip unit is hard-coded to Arabic "طلبات". */
7472
7581
  class SceRingChartComponent {
7473
7582
  /** Data items for the ring segments */
7474
7583
  data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -7533,6 +7642,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7533
7642
  args: [{ host: { class: 'sce-ring-chart' }, selector: 'sce-ring-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"sce-ring-chart\">\n <div class=\"sce-ring-chart__canvas-wrap\" [style.height.px]=\"height()\">\n <div echarts [options]=\"chartOptions()\" class=\"sce-ring-chart__canvas\"></div>\n\n @if (centerValue() !== null) {\n <div class=\"sce-ring-chart__overlay\" aria-hidden=\"true\">\n @if (centerLabel()) {\n <span class=\"sce-ring-chart__center-label\">{{ centerLabel() }}</span>\n }\n <span class=\"sce-ring-chart__center-value\">{{ centerValue() }}</span>\n </div>\n }\n </div>\n\n @if (showLegend() && legendItems().length) {\n <div class=\"sce-ring-chart__legend\">\n @for (item of legendItems(); track item.name) {\n <div class=\"sce-ring-chart__legend-row\">\n <div class=\"sce-ring-chart__legend-marker\" [style.background-color]=\"item.color\"></div>\n <span class=\"sce-ring-chart__legend-name\">{{ item.name }}</span>\n <span class=\"sce-ring-chart__legend-value\">{{ item.value }}</span>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-ring-chart{display:flex;flex-direction:column;width:100%}.sce-ring-chart__canvas-wrap{position:relative;width:100%;flex-shrink:0}.sce-ring-chart__canvas{width:100%;height:100%}.sce-ring-chart__overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.sce-ring-chart__center-label{font-size:var(--font-size-sm);color:var(--color-text-muted);line-height:1.375}.sce-ring-chart__center-value{font-size:var(--font-size-4xl);font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:1}.sce-ring-chart__legend{display:flex;flex-direction:column;gap:var(--space-16);padding-block-start:var(--space-sm)}.sce-ring-chart__legend-row{display:flex;align-items:center;gap:var(--space-sm)}.sce-ring-chart__legend-name{flex:1;font-size:var(--font-size-sm);color:var(--color-text-muted);font-weight:var(--font-weight-medium);text-align:start}.sce-ring-chart__legend-marker{inline-size:var(--space-sm);block-size:var(--space-sm);border-radius:var(--radius-md);width:var(--space-20);height:var(--space-20);flex-shrink:0}.sce-ring-chart__legend-value{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}\n"] }]
7534
7643
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], centerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerLabel", required: false }] }], centerValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerValue", required: false }] }], innerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "innerRadius", required: false }] }], outerRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "outerRadius", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }] } });
7535
7644
 
7645
+ /** Semicircular tick-mark gauge for a 0-100 value; when `isRtl` is set the chart's own text is hidden so the caller can overlay it unmirrored. */
7536
7646
  class SceGaugeChartComponent {
7537
7647
  /** Current value (0-100) */
7538
7648
  value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -7633,6 +7743,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7633
7743
  args: [{ host: { class: 'sce-gauge-chart' }, selector: 'sce-gauge-chart', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"gauge-chart\" [style.height.px]=\"height()\" [style.width.px]=\"width()\">\n <div class=\"gauge-chart__canvas\" [class.gauge-chart__canvas--rtl]=\"isRtl()\">\n <div echarts [options]=\"chartOptions()\" class=\"gauge-chart__canvas-inner\"></div>\n </div>\n @if (isRtl() && showValue()) {\n <div class=\"gauge-chart__label-overlay\" aria-hidden=\"true\">\n <span class=\"gauge-chart__value\">%{{ value() }}</span>\n @if (label()) {\n <span class=\"gauge-chart__label\">{{ label() }}</span>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.gauge-chart{width:100%;height:100%;position:relative}.gauge-chart__canvas{width:100%;height:100%}.gauge-chart__canvas--rtl{transform:scaleX(-1)}.gauge-chart__canvas-inner{width:100%;height:100%}.gauge-chart__label-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;font-family:var(--font-family-base);transform:translateY(-8%)}.gauge-chart__value{font-size:var(--font-size-4xl);font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:1}.gauge-chart__label{font-size:var(--font-size-sm);color:var(--color-text-muted);margin-block-start:var(--space-xs)}\n"] }]
7634
7744
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], endAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "endAngle", required: false }] }], isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }] } });
7635
7745
 
7746
+ /** Pure-CSS horizontal bars (no ECharts), each split into `segmentCount` sub-segments that fill against the item's own `maxValue`. */
7636
7747
  class SceMultiSegmentBarChartComponent {
7637
7748
  el = inject(ElementRef);
7638
7749
  /** Data items for the bar chart */
@@ -7695,6 +7806,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7695
7806
  args: [{ host: { class: 'sce-multi-segment-bar-chart' }, selector: 'sce-multi-segment-bar-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-multi-segment-bar-chart\" [style.row-gap.px]=\"rowGap()\">\n @for (bar of computedBars(); track bar.label) {\n <div class=\"sce-multi-segment-bar-chart__item\">\n <!-- Segmented Bar -->\n <div class=\"sce-multi-segment-bar-chart__bar\" [style.height.px]=\"barHeight()\" [style.gap.px]=\"segmentGap()\">\n <!-- track $index: fixed number of chart segments, derived from the segmentCount() input -->\n @for (seg of bar.segments; track $index; let first = $first; let last = $last) {\n <div\n class=\"sce-multi-segment-bar-chart__segment\"\n [class.sce-multi-segment-bar-chart__segment--first]=\"first\"\n [class.sce-multi-segment-bar-chart__segment--last]=\"last\"\n [style.background-color]=\"trackColor()\"\n >\n <div class=\"sce-multi-segment-bar-chart__fill\" [style.width.%]=\"seg.fill\" [style.background-color]=\"bar.color\"></div>\n </div>\n }\n </div>\n\n <!-- Info Row -->\n <div class=\"sce-multi-segment-bar-chart__row\">\n <div class=\"sce-multi-segment-bar-chart__meta\">\n <span class=\"sce-multi-segment-bar-chart__marker\" [style.background-color]=\"bar.color\" [attr.aria-hidden]=\"true\"></span>\n <span class=\"sce-multi-segment-bar-chart__label\">{{ bar.label }}</span>\n </div>\n <span class=\"sce-multi-segment-bar-chart__value\">{{ bar.value }}</span>\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-multi-segment-bar-chart{display:flex;flex-direction:column;width:100%}.sce-multi-segment-bar-chart__item{display:flex;flex-direction:column;gap:var(--space-md)}.sce-multi-segment-bar-chart__bar{display:flex;width:100%}.sce-multi-segment-bar-chart__segment{flex:1;position:relative;overflow:hidden}.sce-multi-segment-bar-chart__segment--first{border-start-start-radius:var(--radius-2xl);border-end-start-radius:var(--radius-2xl)}.sce-multi-segment-bar-chart__segment--last{border-start-end-radius:var(--radius-2xl);border-end-end-radius:var(--radius-2xl)}.sce-multi-segment-bar-chart__fill{height:100%;transition:width .3s ease}.sce-multi-segment-bar-chart__row{display:flex;align-items:center;justify-content:space-between}:host-context([dir=rtl]) .sce-multi-segment-bar-chart__row{flex-direction:row-reverse}.sce-multi-segment-bar-chart__meta{display:flex;align-items:center;gap:var(--space-sm)}:host-context([dir=rtl]) .sce-multi-segment-bar-chart__meta{flex-direction:row-reverse}.sce-multi-segment-bar-chart__marker{inline-size:var(--space-xl);block-size:var(--space-xl);border-radius:var(--radius-md);flex-shrink:0}.sce-multi-segment-bar-chart__label{color:var(--color-text-secondary);font-size:var(--font-size-lg);font-weight:var(--font-weight-medium)}.sce-multi-segment-bar-chart__value{color:var(--color-text-primary);font-size:var(--font-size-2xl);font-weight:var(--font-weight-bold)}\n"] }]
7696
7807
  }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], barHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "barHeight", required: false }] }], segmentCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "segmentCount", required: false }] }], segmentGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "segmentGap", required: false }] }], rowGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowGap", required: false }] }], defaultColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }] } });
7697
7808
 
7809
+ /** Half-circle ECharts gauge whose arc is coloured by proportional segment stops, with an optional centred label and value. */
7698
7810
  class SceMultiSegmentGaugeComponent {
7699
7811
  /** Segments to display on the gauge arc */
7700
7812
  segments = input([], ...(ngDevMode ? [{ debugName: "segments" }] : /* istanbul ignore next */ []));
@@ -7760,6 +7872,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7760
7872
  args: [{ host: { class: 'sce-multi-segment-gauge' }, selector: 'sce-multi-segment-gauge', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"sce-multi-segment-gauge\">\n <div class=\"sce-multi-segment-gauge__canvas-wrap\" [style.height.px]=\"height()\">\n <div echarts [options]=\"chartOptions()\" class=\"sce-multi-segment-gauge__canvas\"></div>\n\n @if (centerValue() !== null) {\n <div class=\"sce-multi-segment-gauge__overlay\" aria-hidden=\"true\">\n @if (centerLabel()) {\n <span class=\"sce-multi-segment-gauge__center-label\">{{ centerLabel() }}</span>\n }\n <span class=\"sce-multi-segment-gauge__center-value\">{{ centerValue() }}</span>\n </div>\n }\n </div>\n\n @if (showLegend() && legendItems().length) {\n <div class=\"sce-multi-segment-gauge__legend\">\n @for (item of legendItems(); track item.name) {\n <div class=\"sce-multi-segment-gauge__legend-item\">\n <span class=\"sce-multi-segment-gauge__legend-label\">{{ item.name }}</span>\n <div class=\"sce-multi-segment-gauge__legend-dot\" [style.background-color]=\"item.color\"></div>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-multi-segment-gauge{display:flex;flex-direction:column;align-items:center;width:100%}.sce-multi-segment-gauge__canvas-wrap{position:relative;width:100%;flex-shrink:0}.sce-multi-segment-gauge__canvas{width:100%;height:100%}.sce-multi-segment-gauge__overlay{position:absolute;inset-inline:0;inset-block-end:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;padding-block-end:var(--space-sm);pointer-events:none;font-family:var(--font-family-primary)}.sce-multi-segment-gauge__center-label{font-size:var(--font-size-sm);color:var(--color-text-muted);line-height:var(--line-height-normal)}.sce-multi-segment-gauge__center-value{font-size:var(--font-size-4xl);font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:var(--line-height-normal)}.sce-multi-segment-gauge__legend{width:100%;display:flex;flex-direction:column;gap:var(--space-xs);padding-block-start:var(--space-sm);padding-inline-start:var(--space-xs)}.sce-multi-segment-gauge__legend-item{display:flex;align-items:center;gap:var(--space-sm)}.sce-multi-segment-gauge__legend-label{flex:1;font-size:var(--font-size-sm);color:var(--color-text-secondary);text-align:start}.sce-multi-segment-gauge__legend-dot{inline-size:var(--space-sm);block-size:var(--space-sm);border-radius:var(--radius-full);flex-shrink:0}\n"] }]
7761
7873
  }], propDecorators: { segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], centerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerLabel", required: false }] }], centerValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "centerValue", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }] } });
7762
7874
 
7875
+ /** Single stacked bar showing each item's share of the total plus a legend row per item, with an auto-generated aria summary and RTL auto-detection. */
7763
7876
  class SceStackedDistributionChartComponent {
7764
7877
  el = inject(ElementRef);
7765
7878
  /** Segments rendered in the distribution bar and legend rows */
@@ -7823,6 +7936,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7823
7936
  args: [{ host: { class: 'sce-stacked-distribution-chart' }, selector: 'sce-stacked-distribution-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-stacked-distribution-chart\">\n <div\n class=\"sce-stacked-distribution-chart__bar\"\n [style.height.px]=\"barHeight()\"\n [style.gap.px]=\"segmentGap()\"\n role=\"img\"\n [attr.aria-label]=\"ariaLabel()\"\n >\n @if (total() > 0 && computedItems().length) {\n @for (item of computedItems(); track item.label; let itemFirst = $first; let itemLast = $last) {\n <!-- track $index: fixed number of chart sub-segments within a single distribution item -->\n @for (val of item.subSegments; track $index; let subFirst = $first; let subLast = $last) {\n <div\n class=\"sce-stacked-distribution-chart__segment\"\n [class.sce-stacked-distribution-chart__segment--first]=\"itemFirst && subFirst\"\n [class.sce-stacked-distribution-chart__segment--last]=\"itemLast && subLast\"\n [class.sce-stacked-distribution-chart__segment--patterned]=\"item.patterned\"\n [style.flex-grow]=\"val\"\n [style.background-color]=\"item.color\"\n [attr.aria-hidden]=\"true\"\n ></div>\n }\n }\n } @else {\n <div\n class=\"sce-stacked-distribution-chart__segment sce-stacked-distribution-chart__segment--first sce-stacked-distribution-chart__segment--last\"\n [style.background-color]=\"emptyColor()\"\n [attr.aria-hidden]=\"true\"\n ></div>\n }\n </div>\n\n <div class=\"sce-stacked-distribution-chart__legend\" [style.row-gap.px]=\"rowGap()\" role=\"list\">\n @for (item of computedItems(); track item.label) {\n <div class=\"sce-stacked-distribution-chart__row\" role=\"listitem\">\n <div class=\"sce-stacked-distribution-chart__meta\">\n <span\n class=\"sce-stacked-distribution-chart__marker\"\n [style.background-color]=\"item.color\"\n [style.inline-size.px]=\"markerSize()\"\n [style.block-size.px]=\"markerSize()\"\n [attr.aria-hidden]=\"true\"\n ></span>\n <span class=\"sce-stacked-distribution-chart__label\">{{ item.label }}</span>\n </div>\n\n <span class=\"sce-stacked-distribution-chart__value\">{{ item.value }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.sce-stacked-distribution-chart{display:flex;flex-direction:column;gap:var(--space-20);width:100%}.sce-stacked-distribution-chart__bar{display:flex;width:100%}.sce-stacked-distribution-chart__segment{position:relative;flex-basis:0;min-inline-size:0;block-size:100%;overflow:hidden;transition:flex-grow .25s ease;border-radius:var(--radius-2xl)}.sce-stacked-distribution-chart__segment--patterned:after{content:\"\";position:absolute;inset:0;background-image:repeating-linear-gradient(90deg,rgba(255,255,255,.15) 0 1px,transparent 1px 100%);pointer-events:none}.sce-stacked-distribution-chart__legend{display:flex;flex-direction:column}:host-context([dir=ltr]) .sce-stacked-distribution-chart__legend .sce-stacked-distribution-chart__row{flex-direction:row-reverse}:host-context([dir=ltr]) .sce-stacked-distribution-chart__legend .sce-stacked-distribution-chart__meta{flex-direction:row-reverse}.sce-stacked-distribution-chart__row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-lg)}.sce-stacked-distribution-chart__meta{display:flex;align-items:center;gap:var(--space-md);min-inline-size:0}.sce-stacked-distribution-chart__marker{border-radius:var(--radius-md);flex-shrink:0}.sce-stacked-distribution-chart__label{color:var(--color-text-secondary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);text-align:start;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sce-stacked-distribution-chart__value{color:var(--color-text-display);font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);line-height:var(--line-height-normal);flex-shrink:0}\n"] }]
7824
7937
  }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], barHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "barHeight", required: false }] }], segmentGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "segmentGap", required: false }] }], rowGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowGap", required: false }] }], markerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "markerSize", required: false }] }], defaultColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultColor", required: false }] }], emptyColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyColor", required: false }] }], isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }] } });
7825
7938
 
7939
+ /** Half-circle gauge of `value` out of `total`, rendered with a subtitle and a list of colour-coded stat rows below it. */
7826
7940
  class SceStatGaugeComponent {
7827
7941
  /** Current (numerator) value, e.g. 120 */
7828
7942
  value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -7888,6 +8002,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7888
8002
  args: [{ host: { class: 'sce-stat-gauge' }, selector: 'sce-stat-gauge', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgxEchartsDirective], providers: [provideEchartsCore({ echarts })], template: "<div class=\"sce-stat-gauge\">\n <div class=\"sce-stat-gauge__canvas-wrap\" [style.height.px]=\"height()\">\n <div echarts [options]=\"chartOptions()\" class=\"sce-stat-gauge__canvas\"></div>\n\n <div class=\"sce-stat-gauge__overlay\" aria-hidden=\"true\">\n <span class=\"sce-stat-gauge__percentage\">{{ percentage() }}%</span>\n @if (subtitle()) {\n <span class=\"sce-stat-gauge__subtitle\">{{ subtitle() }}</span>\n }\n </div>\n </div>\n\n @if (stats().length) {\n <div class=\"sce-stat-gauge__stats\">\n @for (row of stats(); track row.label) {\n <div class=\"sce-stat-gauge__stat-row\">\n <div class=\"sce-stat-gauge__stat-row__meta\">\n <span\n class=\"sce-stat-gauge__marker\"\n [style.background-color]=\"row.color\"\n [style.inline-size.px]=\"markerSize()\"\n [style.block-size.px]=\"markerSize()\"\n [attr.aria-hidden]=\"true\"\n ></span>\n <span class=\"sce-stat-gauge__stat-label\">{{ row.label }}</span>\n </div>\n\n <span class=\"sce-stat-gauge__stat-value\">{{ row.value }}</span>\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.sce-stat-gauge{display:flex;flex-direction:column;align-items:center;width:100%}.sce-stat-gauge__canvas-wrap{position:relative;width:100%}.sce-stat-gauge__canvas{width:100%;height:100%}.sce-stat-gauge__overlay{position:absolute;inset-inline:0;inset-block-end:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;padding-block-end:var(--space-sm);pointer-events:none;font-family:var(--font-family-primary)}.sce-stat-gauge__percentage{font-size:var(--font-size-chart-value, var(--font-size-4xl));font-weight:var(--font-weight-bold);color:var(--color-chart-text, var(--color-text-primary));line-height:1}.sce-stat-gauge__subtitle{font-size:var(--font-size-chart-label, var(--font-size-sm));color:var(--color-chart-text-secondary, var(--color-text-muted));margin-block-start:var(--space-xs)}.sce-stat-gauge__marker{border-radius:var(--radius-md);flex-shrink:0}.sce-stat-gauge__stats{width:100%;display:flex;flex-direction:column;gap:var(--space-xs);padding-block-start:var(--space-sm)}.sce-stat-gauge__stat-row{display:flex;justify-content:space-between;align-items:center;padding-inline:var(--space-xs)}.sce-stat-gauge__stat-row__meta{display:flex;align-items:center;gap:var(--space-md);min-inline-size:0}.sce-stat-gauge__stat-label{font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-stat-gauge__stat-value{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}\n"] }]
7889
8003
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], stats: [{ type: i0.Input, args: [{ isSignal: true, alias: "stats", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], markerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "markerSize", required: false }] }] } });
7890
8004
 
8005
+ /** SVG progress ring (no ECharts) with a centred label and value, an optional gradient stroke and RTL auto-detection; `progress` may exceed 100. */
7891
8006
  class SceStatRingComponent {
7892
8007
  el = inject(ElementRef);
7893
8008
  /** Center label shown above the value */
@@ -7957,6 +8072,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7957
8072
  args: [{ host: { class: 'sce-stat-ring' }, selector: 'sce-stat-ring', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-stat-ring\" [style.width.px]=\"size()\" [style.height.px]=\"size()\">\n <svg\n class=\"sce-stat-ring__svg\"\n [attr.viewBox]=\"viewBox()\"\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n role=\"img\"\n [attr.aria-label]=\"label() + ' ' + value()\"\n >\n @if (useGradient()) {\n <defs>\n <linearGradient [id]=\"gradientId()\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" [attr.stop-color]=\"gradientStartColor()\" />\n <stop offset=\"100%\" [attr.stop-color]=\"gradientEndColor()\" />\n </linearGradient>\n </defs>\n }\n\n <circle\n class=\"sce-stat-ring__track\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"trackStrokeWidth()\"\n [attr.stroke]=\"trackColor()\"\n fill=\"none\"\n />\n <circle\n class=\"sce-stat-ring__fill\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"strokeWidth()\"\n [attr.stroke]=\"useGradient() ? 'url(#' + gradientId() + ')' : color()\"\n stroke-linecap=\"round\"\n [attr.stroke-dasharray]=\"circumference()\"\n [attr.stroke-dashoffset]=\"strokeDashOffset()\"\n [attr.transform]=\"'rotate(' + startAngle() + ' ' + center() + ' ' + center() + ')'\"\n fill=\"none\"\n />\n </svg>\n\n <div class=\"sce-stat-ring__content\" aria-hidden=\"true\">\n @if (label()) {\n <span class=\"sce-stat-ring__label\">{{ label() }}</span>\n }\n <span class=\"sce-stat-ring__value\">{{ value() }}</span>\n </div>\n</div>\n", styles: [":host{display:inline-flex}.sce-stat-ring{position:relative;display:inline-flex;align-items:center;justify-content:center}.sce-stat-ring__svg{display:block;overflow:visible}:host-context([dir=rtl]) .sce-stat-ring__svg{transform:scaleY(-1)}.sce-stat-ring__track,.sce-stat-ring__fill{stroke-linecap:round}.sce-stat-ring__fill{transition:stroke-dashoffset .3s ease}.sce-stat-ring__content{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2xs);pointer-events:none;text-align:center}.sce-stat-ring__label{color:var(--color-text-secondary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:1.2}.sce-stat-ring__value{color:var(--color-text-primary);font-size:var(--font-size-xl);font-weight:var(--font-weight-bold);line-height:1}\n"] }]
7958
8073
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], trackStrokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackStrokeWidth", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], gradientStartColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "gradientStartColor", required: false }] }], gradientEndColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "gradientEndColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], startAngle: [{ type: i0.Input, args: [{ isSignal: true, alias: "startAngle", required: false }] }], useGradient: [{ type: i0.Input, args: [{ isSignal: true, alias: "useGradient", required: false }] }], isRtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "isRtl", required: false }] }] } });
7959
8074
 
8075
+ /** Three-segment scale track showing either a single thumb or a highlighted range when both `start` and `end` are given; the segment labels default to hardcoded Arabic strings. */
7960
8076
  class SceScaleIndicatorComponent {
7961
8077
  /** Title displayed above the scale */
7962
8078
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
@@ -8025,6 +8141,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8025
8141
  args: [{ host: { class: 'sce-scale-indicator' }, selector: 'sce-scale-indicator', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-scale-indicator\">\n @if (title()) {\n <h4 class=\"sce-scale-indicator__title\">{{ title() }}</h4>\n }\n\n <div class=\"sce-scale-indicator__track\">\n <div class=\"sce-scale-indicator__segment\"></div>\n <div class=\"sce-scale-indicator__segment\"></div>\n <div class=\"sce-scale-indicator__segment\"></div>\n\n @if (isRangeMode()) {\n <div\n class=\"sce-scale-indicator__range\"\n [style.left.%]=\"rangeStartPercent()\"\n [style.width.%]=\"rangeWidthPercent()\"\n [style.background-color]=\"activeColor()\"\n ></div>\n } @else {\n <div\n class=\"sce-scale-indicator__thumb\"\n [style.height.px]=\"barHeight()\"\n [style.left.%]=\"thumbPercent()\"\n [style.background-color]=\"activeColor()\"\n ></div>\n }\n </div>\n\n <div class=\"sce-scale-indicator__labels\">\n <span class=\"sce-scale-indicator__label\">{{ labels().high }}</span>\n <span class=\"sce-scale-indicator__label\">{{ labels().mid }}</span>\n <span class=\"sce-scale-indicator__label\">{{ labels().low }}</span>\n </div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.sce-scale-indicator{width:100%;height:100%}.sce-scale-indicator__title{text-align:center;font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);color:var(--color-neutral-800);margin-block:0 var(--space-md);margin-inline:0}.sce-scale-indicator__track{position:relative;display:flex;gap:var(--space-xs);height:var(--size-8);margin-block-end:var(--space-sm)}.sce-scale-indicator__segment{flex:1;border-radius:var(--radius-xs);background-color:var(--color-neutral-200)}.sce-scale-indicator__thumb{position:absolute;top:50%;transform:translate(-50%,-50%);width:var(--size-32);height:var(--size-8);border-radius:var(--radius-sm);transition:left .3s ease}.sce-scale-indicator__range{position:absolute;top:50%;transform:translateY(-50%);height:var(--size-8);min-width:4%;border-radius:var(--radius-sm);transition:left .3s ease,width .3s ease}.sce-scale-indicator__labels{display:flex;justify-content:space-between}.sce-scale-indicator__label{flex:1;text-align:center;font-size:var(--font-size-xs);color:var(--color-neutral-400)}\n"] }]
8026
8142
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], start: [{ type: i0.Input, args: [{ isSignal: true, alias: "start", required: false }] }], end: [{ type: i0.Input, args: [{ isSignal: true, alias: "end", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], activeColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeColor", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], barHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "barHeight", required: false }] }] } });
8027
8143
 
8144
+ /** Dashboard overview tile showing a stat value, translated label, icon on a coloured background and an optional trend sparkline. */
8028
8145
  class SceOverviewStatCardComponent {
8029
8146
  value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
8030
8147
  labelKey = input.required(...(ngDevMode ? [{ debugName: "labelKey" }] : /* istanbul ignore next */ []));
@@ -8039,6 +8156,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8039
8156
  args: [{ host: { class: 'sce-overview-stat-card' }, selector: 'sce-overview-stat-card', standalone: true, imports: [TranslatePipe, SceOverviewStatSparklineComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"stat-card\">\n <!-- Top Row: Icon (start/right) and Trend (end/left) -->\n <div class=\"stat-header\">\n <div class=\"stat-icon-wrap\" [style.background]=\"iconBg()\">\n <img [src]=\"icon()\" width=\"22\" height=\"22\" alt=\"\" aria-hidden=\"true\" class=\"stat-icon\" />\n </div>\n @if (trend()) {\n <div class=\"stat-trend\">\n {{ trend() }}\n </div>\n }\n </div>\n\n <!-- Bottom Row: Text (start/right) and Sparkline (end/left) -->\n <div class=\"stat-body\">\n <div class=\"stat-text\">\n <p class=\"stat-value\">{{ value() }}</p>\n <p class=\"stat-label\">{{ labelKey() | translate }}</p>\n </div>\n <div class=\"sparkline-container\" aria-hidden=\"true\">\n <sce-overview-stat-sparkline [color]=\"iconBg()\" className=\"sparkline-img\" />\n </div>\n </div>\n</article>\n", styles: [":host{display:block;width:100%}.stat-card{background:var(--surface-primary);border:1px solid var(--color-border);box-shadow:0 1px 3px #1018280d,0 1px 2px #10182808;border-radius:var(--radius-brand-sm);padding:var(--space-20);display:flex;flex-direction:column;justify-content:space-between;min-height:var(--size-156);position:relative;z-index:0;overflow:hidden;box-sizing:border-box;transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1)}@media(prefers-reduced-motion:no-preference){.stat-card:hover{transform:translateY(-4px);box-shadow:0 12px 24px #10182814;border-color:#0000000d}}.stat-header{display:flex;justify-content:space-between;align-items:center;width:100%}.stat-icon-wrap{width:var(--space-44, var(--size-44));height:var(--space-44, var(--size-44));border-radius:var(--radius-xl);display:inline-flex;align-items:center;justify-content:center}.stat-icon{display:block;filter:brightness(0) invert(1)}.stat-trend{font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:600;color:var(--text-text-primary-900, var(--color-neutral-900));display:flex;align-items:center;gap:var(--space-4);direction:ltr}.stat-body{display:flex;justify-content:space-between;align-items:flex-end;width:100%;margin-block-start:auto}.stat-text{display:flex;flex-direction:column;gap:var(--space-4);align-items:flex-start;text-align:start}.stat-value{margin:.6rem 0 .2rem;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-2xl);font-weight:700;color:var(--text-text-primary-900, var(--color-neutral-900))}.stat-label{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600);line-height:1.4;white-space:nowrap}.sparkline-container{width:60%;max-width:var(--size-110);height:var(--space-32);display:block}.sparkline-container sce-overview-stat-sparkline{display:block;width:100%;height:100%}\n"] }]
8040
8157
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], labelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelKey", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], iconBg: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconBg", required: true }] }], trend: [{ type: i0.Input, args: [{ isSignal: true, alias: "trend", required: false }] }] } });
8041
8158
 
8159
+ /** Small dashboard card linking to a service, showing its icon and a count with a role-aware translated suffix. */
8042
8160
  class SceServiceMiniCardComponent {
8043
8161
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
8044
8162
  count = input.required(...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
@@ -8054,6 +8172,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8054
8172
  args: [{ host: { class: 'sce-service-mini-card' }, selector: 'sce-service-mini-card', standalone: true, imports: [RouterLink, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<a [routerLink]=\"link()\" class=\"service-card\">\n <!-- Right Column (Start side): Icon and Text -->\n <div class=\"service-info-group\">\n <div class=\"service-icon-wrap\">\n <img [src]=\"icon()\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" class=\"service-icon\" />\n </div>\n <div class=\"service-text\">\n <h3 class=\"service-title\">{{ title() }}</h3>\n <span class=\"service-count\"> {{ count() }} {{ countSuffix() | translate }} </span>\n </div>\n </div>\n\n <!-- Left Column (End side): Circular Arrow Button -->\n <div class=\"service-arrow-btn\" aria-hidden=\"true\">\n <span class=\"arrow-icon\"><img src=\"/assets/icons/arrow-left.svg\" height=\"12\" width=\"12\" alt=\"\" /></span>\n </div>\n</a>\n", styles: [":host{display:block;width:100%}.service-card{display:flex;justify-content:space-between;align-items:center;background:var(--surface-primary);border:1px solid var(--color-border);box-shadow:0 1px 3px #1018280d,0 1px 2px #10182808;border-radius:var(--radius-brand-sm);padding:var(--space-16) var(--space-20);text-decoration:none;color:inherit;box-sizing:border-box;width:100%;transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1)}@media(prefers-reduced-motion:no-preference){.service-card:hover{transform:translateY(-2px);box-shadow:0 8px 16px #1018280f;border-color:#0000000d}}.service-info-group{display:flex;align-items:center;gap:var(--space-16)}.service-icon-wrap{width:var(--space-56);height:var(--space-56);border-radius:var(--radius-2xl, var(--radius-2xl));background:var(--color-brand-primary-800);display:flex;align-items:center;justify-content:center;flex-shrink:0}.service-icon{display:block;filter:brightness(0) invert(1)}.service-text{display:flex;flex-direction:column;gap:var(--space-4);align-items:flex-start;text-align:start}.service-title{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-lg-18);font-weight:700;color:var(--text-text-primary-900, var(--color-neutral-900));line-height:1.2}.service-count{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600);line-height:1.4}.service-arrow-btn{width:var(--space-36);height:var(--space-36);border-radius:var(--radius-full);background:var(--background-bg-secondary);display:flex;align-items:center;justify-content:center;color:var(--text-text-primary-900, var(--color-neutral-900));transition:background .2s ease,transform .2s ease;flex-shrink:0}.arrow-icon{display:inline-block;font-size:var(--font-size-lg-18);line-height:1;font-weight:700;transition:transform .2s ease}.service-card:hover .service-arrow-btn{background:var(--color-neutral-200)}.service-card:hover .service-arrow-btn{transform:translate(calc(var(--dir) * 4px))}:host-context([dir=ltr]) .arrow-icon{transform:rotate(180deg)}\n"] }]
8055
8173
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], link: [{ type: i0.Input, args: [{ isSignal: true, alias: "link", required: true }] }], countSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "countSuffix", required: false }] }] } });
8056
8174
 
8175
+ /** Dashboard card for a featured engineering office showing rating, review count, country and service tabs; a zero review count renders the "no reviews yet" fallback. */
8057
8176
  class SceFeaturedOfficeCardComponent {
8058
8177
  office = input.required(...(ngDevMode ? [{ debugName: "office" }] : /* istanbul ignore next */ []));
8059
8178
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceFeaturedOfficeCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -8064,6 +8183,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8064
8183
  args: [{ host: { class: 'sce-featured-office-card' }, selector: 'sce-featured-office-card', standalone: true, imports: [RouterLink, TranslatePipe, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<article class=\"featured-office-card\">\n <!-- Right Side (Start side): Avatar + Meta Details -->\n <div class=\"office-lead-group\">\n <div class=\"office-avatar-wrap\">\n <img src=\"/assets/icons/avatar.svg\" width=\"64\" height=\"64\" alt=\"\" aria-hidden=\"true\" class=\"office-avatar\" />\n </div>\n\n <div class=\"office-meta-details\">\n <div class=\"office-title-row\">\n <h3 class=\"office-title\">{{ office().title }}</h3>\n <sce-icon name=\"checkmark-badge\" [size]=\"16\" class=\"office-checkmark\" aria-hidden=\"true\" />\n </div>\n\n <div class=\"office-stats-row\">\n <span class=\"office-rating-badge\">\n <img src=\"/assets/icons/star copy.svg\" width=\"12\" height=\"12\" alt=\"\" aria-hidden=\"true\" class=\"rating-star\" />\n <span class=\"office-rating-value\">{{ office().rating }}</span>\n </span>\n\n <span class=\"office-separator\" aria-hidden=\"true\">\u2022</span>\n\n <span class=\"office-review-count\">\n @if (office().reviewCount > 0) {\n {{ office().reviewCountLabel }} {{ 'dashboard.overview.reviewCountSuffix' | translate }}\n } @else {\n {{ 'dashboard.overview.noReviewsYet' | translate }}\n }\n </span>\n\n <span class=\"office-separator\" aria-hidden=\"true\">\u2022</span>\n\n <span class=\"office-location\">\n <img src=\"/assets/icons/location.svg\" width=\"14\" height=\"14\" alt=\"\" aria-hidden=\"true\" class=\"location-icon\" />\n {{ office().country }}\n </span>\n </div>\n </div>\n </div>\n\n <!-- Middle: Dynamic Capsule Tags -->\n @if (office().tabs.length) {\n <div class=\"office-tags-wrap\">\n @for (tab of office().tabs; track tab) {\n <span class=\"office-tag\">{{ tab }}</span>\n }\n </div>\n }\n\n <!-- Left Side (End side): Action Button \"\u0639\u0631\u0636 \u0627\u0644\u0645\u0644\u0641\" -->\n <a [routerLink]=\"office().href\" class=\"office-profile-btn\">\n <span class=\"btn-text\">{{ 'dashboard.overview.viewProfile' | translate }}</span>\n <span class=\"arrow-icon\" aria-hidden=\"true\">\n <img src=\"/assets/icons/arrow-left.svg\" width=\"12\" height=\"12\" alt=\"\" />\n </span>\n </a>\n</article>\n", styles: [":host{display:block;width:100%}.featured-office-card{position:relative;display:flex;align-items:center;justify-content:space-between;gap:var(--space-24);background:var(--surface-primary, var(--color-white));border:1px solid var(--color-border);border-radius:var(--radius-2xl);padding:var(--space-16) var(--space-24);width:100%;box-sizing:border-box;transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1);min-width:0}.featured-office-card:hover{transform:translateY(-2px);box-shadow:0 12px 24px #1018280f;border-color:var(--color-primary-200, var(--color-input-border))}.office-lead-group{display:flex;align-items:center;gap:var(--space-16);flex:1;min-width:0}.office-avatar-wrap{width:var(--space-64);height:var(--space-64);border-radius:var(--radius-xl);overflow:hidden;flex-shrink:0;background:var(--color-neutral-100, var(--color-neutral-100));display:flex;align-items:center;justify-content:center;border:1px solid var(--color-border)}.office-avatar-wrap .office-avatar{width:100%;height:100%;object-fit:cover}.office-meta-details{display:flex;flex-direction:column;gap:var(--space-6);min-width:0;text-align:start}.office-title-row{display:flex;align-items:center;gap:var(--space-6);min-width:0}.office-title{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-lg);font-weight:700;color:var(--text-text-primary-900, var(--text-primary-default));line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.office-checkmark{flex-shrink:0}.office-stats-row{display:flex;align-items:center;gap:var(--space-8);flex-wrap:wrap;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-sm);color:var(--text-text-secondary-600, var(--color-subtle));line-height:1.4}.office-rating-badge{display:inline-flex;direction:ltr;align-items:center;gap:var(--space-4);background:var(--color-warning-50, var(--color-warning-100));border-radius:var(--space-100);padding:var(--space-2) var(--space-8);flex-shrink:0}.office-rating-value{font-size:var(--font-size-xs);font-weight:700;color:var(--text-text-primary-900, var(--text-primary-default));line-height:1}.rating-star{flex-shrink:0}.office-separator{color:var(--color-black);font-weight:700;font-size:var(--font-size-lg);-webkit-user-select:none;user-select:none;margin-block-end:.4rem}.office-projects-count{font-weight:500}.office-location{display:inline-flex;align-items:center;gap:var(--space-4);font-weight:500}.location-icon{flex-shrink:0}.office-tags-wrap{display:flex;align-items:center;gap:var(--space-8);flex-wrap:wrap;justify-content:center}.office-tag{background:var(--background-bg-secondary, var(--app-canvas-bg));border:1px solid var(--color-border);color:var(--text-text-secondary-700);font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-xs);font-weight:500;padding:var(--space-6) var(--space-14);border-radius:var(--space-100);white-space:nowrap}.office-profile-btn{position:relative;z-index:2;display:inline-flex;align-items:center;gap:var(--space-8);background:var(--background-bg-secondary, var(--app-canvas-bg));color:var(--text-text-primary-900, var(--text-primary-default));font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:600;padding:var(--space-8) var(--space-20);border-radius:var(--space-100);text-decoration:none;transition:background-color .2s ease,transform .2s ease;flex-shrink:0}.office-profile-btn:hover{background:var(--color-border)}.arrow-icon{display:inline-flex;align-items:center;justify-content:center;transition:transform .2s ease}.featured-office-card:hover .office-profile-btn{background:var(--color-border)}.featured-office-card:hover .arrow-icon{transform:translate(-4px)}:host-context([dir=ltr]) .featured-office-card:hover .arrow-icon{transform:translate(4px)}:host-context([dir=ltr]) .arrow-icon{transform:rotate(180deg)}@media(max-width:992px){.featured-office-card{flex-direction:column;align-items:stretch;gap:var(--space-16);padding:var(--space-20)}.office-tags-wrap{justify-content:flex-start}.office-profile-btn{align-self:flex-start;width:100%;justify-content:center}}@media(max-width:480px){.office-avatar-wrap{width:var(--space-52, var(--size-52));height:var(--space-52, var(--size-52))}.office-title{font-size:var(--font-size-md-15)}.office-stats-row{font-size:var(--font-size-xs);gap:var(--space-6)}.office-profile-btn{padding:var(--space-10) var(--space-16)}}\n"] }]
8065
8184
  }], propDecorators: { office: [{ type: i0.Input, args: [{ isSignal: true, alias: "office", required: true }] }] } });
8066
8185
 
8186
+ /** Dashboard card summarising a contract request (office, location, deadline, budget) with tone-resolved tags, linking to its detail route. */
8067
8187
  class SceContractRequestCardComponent {
8068
8188
  request = input.required(...(ngDevMode ? [{ debugName: "request" }] : /* istanbul ignore next */ []));
8069
8189
  tagTones = computed(() => this.request().tags.map(tag => resolveBusinessStatusTone(tag)), ...(ngDevMode ? [{ debugName: "tagTones" }] : /* istanbul ignore next */ []));
@@ -8075,6 +8195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8075
8195
  args: [{ host: { class: 'sce-contract-request-card' }, selector: 'sce-contract-request-card', standalone: true, imports: [RouterLink, TranslatePipe, SceBusinessStatusTagComponent, SceBidiIsolate], changeDetection: ChangeDetectionStrategy.OnPush, template: "<a [routerLink]=\"'/dashboard/contracts-requests/' + request().id\" [queryParams]=\"{ source: 'contracts-requests' }\" class=\"request-card\">\n <!-- Tags Row (Start side) -->\n <div class=\"tags-row\">\n @for (tag of request().tags; track tag; let i = $index) {\n <sce-business-status-tag [label]=\"tag\" [tone]=\"tagTones()[i]\" size=\"sm\" />\n }\n </div>\n\n <!-- Title (Start side) -->\n <h3 class=\"card-title\">{{ request().title }}</h3>\n\n <!-- Meta Subtitle (Start side) -->\n <div class=\"card-meta\">\n <span class=\"meta-item\"\n ><sce-bidi-isolate>{{ request().requestNumber }}</sce-bidi-isolate></span\n >\n <span class=\"meta-divider\" aria-hidden=\"true\">&bull;</span>\n <span class=\"meta-item brand-name\">{{ request().officeName }}</span>\n </div>\n\n <!-- Divider -->\n <hr class=\"card-divider\" />\n\n <!-- Details List -->\n <div class=\"card-details\">\n <!-- Row 1: Location -->\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <img src=\"/assets/icons/location.svg\" width=\"17\" height=\"18\" alt=\"\" aria-hidden=\"true\" class=\"detail-icon\" />\n {{ 'dashboard.overview.locationLabel' | translate }}\n </span>\n <span class=\"detail-value\">{{ request().location }}</span>\n </div>\n\n <!-- Row 2: Deadline -->\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <img src=\"/assets/icons/calendar-04.svg\" width=\"17\" height=\"18\" alt=\"\" aria-hidden=\"true\" class=\"detail-icon\" />\n {{ 'dashboard.overview.deadlineLabel' | translate }}\n </span>\n <span class=\"detail-value\"\n ><sce-bidi-isolate>{{ request().deadline }}</sce-bidi-isolate></span\n >\n </div>\n\n <!-- Row 3: Offers -->\n @if (request().offersCount !== undefined) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">\n <img\n src=\"/assets/icons/nav-contracts-requests.svg\"\n width=\"17\"\n height=\"18\"\n alt=\"\"\n aria-hidden=\"true\"\n class=\"detail-icon\"\n style=\"filter: grayscale(1) opacity(0.7)\"\n />\n {{ 'dashboard.overview.offersLabel' | translate }}\n </span>\n <span class=\"detail-value\"> {{ request().offersCount }} {{ 'dashboard.overview.offersSuffix' | translate }} </span>\n </div>\n }\n </div>\n\n <!-- Budget Section (Bottom Row) -->\n <div class=\"budget-section\">\n <span class=\"budget-label\">{{ 'dashboard.overview.budgetLabel' | translate }}</span>\n <span class=\"budget-value\">\n @if (request().budget && request().budget !== '\u2014') {\n <!-- The Rial sign (U+FDFC) is a strong-RTL character \u2014 isolate it with the\n amount so it can't reorder the number in an LTR (English) layout. -->\n <sce-bidi-isolate>\n <span class=\"budget-amount\">{{ request().budget }}</span>\n <span class=\"currency-symbol\">&#xFDFC;</span>\n </sce-bidi-isolate>\n } @else {\n <span class=\"budget-amount-empty\">{{ 'common.notSpecified' | translate }}</span>\n }\n </span>\n </div>\n</a>\n", styles: [":host{display:block;width:100%}.request-card{display:flex;flex-direction:column;background:var(--surface-primary, var(--color-white));border:1px solid var(--color-border);box-shadow:0 1px 3px #1018280d,0 1px 2px #10182808;border-radius:var(--space-20);padding:var(--space-24);text-decoration:none;color:inherit;box-sizing:border-box;height:100%;transition:transform .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1),border-color .2s cubic-bezier(.4,0,.2,1)}@media(prefers-reduced-motion:no-preference){.request-card:hover{transform:translateY(-4px);box-shadow:0 12px 24px #10182814;border-color:#0000000d}}.tags-row{display:flex;flex-wrap:wrap;gap:var(--space-8);justify-content:flex-start}.card-title{margin:var(--space-16) 0 var(--space-8) 0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-xl);font-weight:700;color:var(--text-text-primary-900, var(--text-primary-default));text-align:start;line-height:1.3}.card-meta{display:flex;align-items:center;gap:var(--space-6);font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600, var(--color-subtle));text-align:start;margin-block-end:var(--space-16)}.brand-name{color:var(--text-text-brand-primary, var(--color-brand-primary-600))}.meta-divider{color:var(--color-input-border)}.card-divider{border:0;border-block-start:1px solid var(--color-neutral-100);margin:0 0 var(--space-16) 0;width:100%}.card-details{display:flex;flex-direction:column;gap:var(--space-12);margin-block-end:var(--space-16)}.detail-row{display:flex;justify-content:space-between;align-items:center;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500}.detail-label{display:inline-flex;align-items:center;gap:var(--space-8);color:var(--text-text-secondary-600, var(--color-subtle))}.detail-icon{display:block}.detail-value{color:var(--text-text-primary-900, var(--text-primary-default));font-weight:600}.budget-section{display:flex;justify-content:space-between;align-items:center;background:var(--background-bg-secondary, var(--color-surface-2));border-radius:var(--radius-xl);padding:var(--space-12) var(--space-16);width:100%;box-sizing:border-box;margin-block-start:auto}.budget-label{font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600, var(--color-muted-fg))}.budget-value{display:inline-flex;align-items:center;gap:var(--space-4);font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-lg-18);font-weight:700;color:var(--text-text-primary-900, var(--text-primary-default))}.currency-symbol{font-size:var(--font-size-lg);font-weight:600;color:var(--text-text-secondary-600, var(--color-muted-fg))}.budget-amount-empty{font-size:var(--font-size-md);font-weight:500;color:var(--text-text-secondary-600, var(--color-subtle))}\n"] }]
8076
8196
  }], propDecorators: { request: [{ type: i0.Input, args: [{ isSignal: true, alias: "request", required: true }] }] } });
8077
8197
 
8198
+ /** Dashboard table of the latest contracts with status tags, showing five skeleton rows while `loading`; the party column header label is caller-supplied. */
8078
8199
  class SceLatestContractsTableComponent {
8079
8200
  contracts = input.required(...(ngDevMode ? [{ debugName: "contracts" }] : /* istanbul ignore next */ []));
8080
8201
  partyColumnLabel = input.required(...(ngDevMode ? [{ debugName: "partyColumnLabel" }] : /* istanbul ignore next */ []));
@@ -8088,6 +8209,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8088
8209
  args: [{ host: { class: 'sce-latest-contracts-table' }, selector: 'sce-latest-contracts-table', standalone: true, imports: [RouterLink, TranslatePipe, SceBusinessStatusTagComponent, SceSkeleton, SceBidiIsolate], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"block\" data-tour=\"dashboard-contracts\">\n <div class=\"sectionHeader\">\n <h2 class=\"sectionTitle\">{{ 'dashboard.sections.latestContracts' | translate }}</h2>\n <a routerLink=\"/dashboard/contracts\" class=\"viewAllLink\">{{ 'dashboard.overview.viewAll' | translate }}</a>\n </div>\n\n <div class=\"contractTableWrap\">\n <table class=\"contractTable\">\n <thead>\n <tr>\n <th>{{ 'dashboard.overview.table.contractNumber' | translate }}</th>\n <th>{{ 'dashboard.overview.table.service' | translate }}</th>\n <th>{{ partyColumnLabel() }}</th>\n <th>{{ 'dashboard.overview.table.completionDate' | translate }}</th>\n <th>{{ 'dashboard.overview.table.projectStatus' | translate }}</th>\n </tr>\n </thead>\n <tbody>\n @if (loading()) {\n @for (row of skeletonRows(); track row) {\n <tr>\n <td><sce-skeleton variant=\"text\" animation=\"wave\" width=\"80px\" /></td>\n <td><sce-skeleton variant=\"text\" animation=\"wave\" /></td>\n <td><sce-skeleton variant=\"text\" animation=\"wave\" /></td>\n <td><sce-skeleton variant=\"text\" animation=\"wave\" width=\"90px\" /></td>\n <td><sce-skeleton variant=\"rounded\" animation=\"wave\" width=\"72px\" height=\"24px\" /></td>\n </tr>\n }\n } @else {\n @for (row of contracts(); track row.contractNumber) {\n <tr>\n <td>\n <span class=\"contract-number\">\n <sce-bidi-isolate [value]=\"row.contractNumber\" tabular />\n </span>\n </td>\n <td>{{ row.service }}</td>\n <td>{{ row.client }}</td>\n <td>{{ row.endDate }}</td>\n <td>\n <sce-business-status-tag [label]=\"row.status\" [tone]=\"row.statusVariant\" />\n </td>\n </tr>\n }\n @if (contracts().length === 0) {\n <tr>\n <td colspan=\"5\" class=\"table-empty-cell\">\n {{ 'dashboard.overview.tableEmpty' | translate }}\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n</section>\n", styles: [":host{display:block;width:100%}.block{background:var(--surface-primary);border:1px solid var(--color-primary-100);border-radius:var(--radius-2xl, var(--radius-2xl));padding:var(--space-24);display:grid;gap:var(--space-12);width:100%;box-sizing:border-box}.sectionHeader{display:flex;justify-content:space-between;align-items:center;gap:var(--space-12);width:100%}.sectionTitle{margin:0;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-xl, var(--font-size-xl));font-weight:700;color:var(--text-text-primary-900, var(--color-neutral-900))}.viewAllLink{text-decoration:none;border:1.5px solid var(--color-brand-primary-800);border-radius:var(--radius-xl);padding:var(--space-8) var(--space-16);display:inline-flex;align-items:center;justify-content:center;font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-md, var(--font-size-md));font-weight:500;color:var(--text-text-brand-primary, var(--color-brand-primary-800));transition:background-color .2s ease,color .2s ease}.viewAllLink:hover{background:var(--background-bg-secondary)}.contractTableWrap{border-radius:var(--radius-xl);overflow:hidden;border:1px solid var(--border-subtle)}.contractTable{width:100%;border-collapse:collapse}.contractTable thead th{text-align:start;padding:var(--space-12) var(--space-16);background:var(--details-row-bg, var(--color-surface-2));color:var(--form-field-text-placeholder, var(--color-neutral-400));font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-xs, var(--font-size-xs));font-weight:600}.contractTable tbody td{text-align:start;padding:var(--space-20) var(--space-16);border-block-start:1px solid var(--border-subtle);color:var(--color-text-heading-700, var(--color-neutral-700));font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-sm, var(--font-size-md));font-weight:500}.contract-number{font-weight:600;color:var(--text-text-primary-900, var(--color-neutral-900))}.table-empty-cell{padding:var(--space-32);text-align:center;color:var(--text-text-secondary-700, var(--text-text-secondary-600));font-family:var(--font-family-arabic-primary, sans-serif);font-size:var(--font-size-sm, var(--font-size-md))}@media(max-width:768px){.block{padding:var(--space-16)}.contractTableWrap{overflow-x:auto;-webkit-overflow-scrolling:touch}.contractTable{min-width:32rem}.contractTable thead th,.contractTable tbody td{padding-inline:var(--space-12);padding-block:var(--space-14);font-size:var(--font-size-xs, var(--font-size-xs))}}\n"] }]
8089
8210
  }], propDecorators: { contracts: [{ type: i0.Input, args: [{ isSignal: true, alias: "contracts", required: true }] }], partyColumnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "partyColumnLabel", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
8090
8211
 
8212
+ /** Login flow step presenting the selectable user-type cards and emitting the picked type plus a continue action. */
8091
8213
  class SceLoginUserTypeStepComponent {
8092
8214
  cards = input.required(...(ngDevMode ? [{ debugName: "cards" }] : /* istanbul ignore next */ []));
8093
8215
  selectedType = input(null, ...(ngDevMode ? [{ debugName: "selectedType" }] : /* istanbul ignore next */ []));
@@ -8105,6 +8227,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8105
8227
  args: [{ host: { class: 'sce-login-user-type-step' }, selector: 'sce-login-user-type-step', standalone: true, imports: [TranslatePipe, Button], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <h2 class=\"title\">{{ 'loginModal.chooseLoginTypeTitle' | translate }}</h2>\n <p class=\"subtitle\">{{ 'loginModal.chooseLoginTypeSubtitle' | translate }}</p>\n</div>\n\n<div class=\"userTypeList\">\n @for (card of cardViews(); track card.type) {\n <button\n type=\"button\"\n class=\"userTypeCard\"\n [class.userTypeCardSelected]=\"card.selected\"\n [attr.aria-pressed]=\"card.selected\"\n (click)=\"selectType.emit(card.type)\"\n >\n <span\n class=\"userTypeIcon\"\n [class.userTypeIconPrimary]=\"card.iconVariant === 'primary'\"\n [class.userTypeIconMuted]=\"card.iconVariant === 'muted'\"\n >\n <img [src]=\"card.icon\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" />\n </span>\n <div class=\"userTypeText\">\n <span class=\"userTypeTitle\">{{ card.titleKey | translate }}</span>\n <span class=\"userTypeDesc\">{{ card.descriptionKey | translate }}</span>\n </div>\n <span class=\"userTypeRadio\" [class.userTypeRadioSelected]=\"card.selected\" aria-hidden=\"true\"></span>\n </button>\n }\n</div>\n\n<p-button type=\"button\" [label]=\"'common.continue' | translate\" styleClass=\"submit w-full\" (onClick)=\"continue.emit()\" />\n" }]
8106
8228
  }], propDecorators: { cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: true }] }], selectedType: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedType", required: false }] }], selectType: [{ type: i0.Output, args: ["selectType"] }], continue: [{ type: i0.Output, args: ["continue"] }] } });
8107
8229
 
8230
+ /** Login flow step capturing national ID and birth date (Hijri/Gregorian), fully controlled — every field value and error is an input. */
8108
8231
  class SceLoginCredentialsStepComponent {
8109
8232
  titleKey = input.required(...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
8110
8233
  subtitleKey = input.required(...(ngDevMode ? [{ debugName: "subtitleKey" }] : /* istanbul ignore next */ []));
@@ -8161,6 +8284,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8161
8284
  }]
8162
8285
  }] });
8163
8286
 
8287
+ /** Login flow step with the OTP input, mask toggle and resend countdown; the timer label is supplied by the parent. */
8164
8288
  class SceLoginOtpStepComponent {
8165
8289
  otpValue = input.required(...(ngDevMode ? [{ debugName: "otpValue" }] : /* istanbul ignore next */ []));
8166
8290
  showOtpVisible = input(false, ...(ngDevMode ? [{ debugName: "showOtpVisible" }] : /* istanbul ignore next */ []));
@@ -8180,6 +8304,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8180
8304
  args: [{ host: { class: 'sce-login-otp-step' }, selector: 'sce-login-otp-step', standalone: true, imports: [TranslatePipe, FormsModule, Button, InputOtp, SceSkeleton, SceOtpAriaDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <h2 class=\"title\">{{ 'loginModal.otpTitle' | translate }}</h2>\n <p class=\"subtitle\">{{ 'loginModal.otpSubtitle' | translate }}</p>\n</div>\n\n<div class=\"form\">\n <div class=\"otpRow\">\n <div class=\"otpContainer\" [class.otpMasked]=\"!showOtpVisible()\" [class.otpInvalid]=\"otpError()\">\n <p-inputotp sceOtpAria [ngModel]=\"otpValue()\" (ngModelChange)=\"otpValueChange.emit($event)\" [length]=\"6\" [integerOnly]=\"true\" />\n </div>\n <button\n type=\"button\"\n class=\"otpToggleBtn\"\n (click)=\"showOtpToggle.emit()\"\n [attr.aria-pressed]=\"showOtpVisible()\"\n [attr.aria-label]=\"(showOtpVisible() ? 'loginModal.otpHide' : 'loginModal.otpShow') | translate\"\n >\n <i [class]=\"showOtpVisible() ? 'pi pi-eye-slash' : 'pi pi-eye'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n @if (otpError()) {\n <div class=\"otpError\" role=\"alert\">{{ otpError() }}</div>\n }\n\n <p class=\"resendRow\">\n <button type=\"button\" class=\"resendBtn\" [disabled]=\"resendSeconds() > 0 || submitting()\" (click)=\"resend.emit()\">\n {{ 'loginModal.resendOtp' | translate }}\n ({{ resendTimerLabel() }})\n </button>\n <span class=\"resendHint\">{{ 'loginModal.didNotReceiveCode' | translate }}</span>\n </p>\n\n <p-button\n type=\"button\"\n styleClass=\"submit w-full\"\n [ariaLabel]=\"'loginModal.otpSubmit' | translate\"\n [disabled]=\"submitting()\"\n (onClick)=\"submitted.emit()\"\n >\n @if (submitting()) {\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'loginModal.otpSubmit' | translate }}\n }\n </p-button>\n</div>\n" }]
8181
8305
  }], propDecorators: { otpValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "otpValue", required: true }] }], showOtpVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOtpVisible", required: false }] }], otpError: [{ type: i0.Input, args: [{ isSignal: true, alias: "otpError", required: false }] }], resendSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "resendSeconds", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], resendTimerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resendTimerLabel", required: true }] }], otpValueChange: [{ type: i0.Output, args: ["otpValueChange"] }], showOtpToggle: [{ type: i0.Output, args: ["showOtpToggle"] }], resend: [{ type: i0.Output, args: ["resend"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
8182
8306
 
8307
+ /** Login flow step that lists the accounts available to the authenticated user and emits the chosen account id. */
8183
8308
  class SceLoginAccountSelectStepComponent {
8184
8309
  accounts = input.required(...(ngDevMode ? [{ debugName: "accounts" }] : /* istanbul ignore next */ []));
8185
8310
  selectedAccountId = input(null, ...(ngDevMode ? [{ debugName: "selectedAccountId" }] : /* istanbul ignore next */ []));
@@ -8195,6 +8320,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8195
8320
  args: [{ host: { class: 'sce-login-account-select-step' }, selector: 'sce-login-account-select-step', standalone: true, imports: [TranslatePipe, Button, SceDashboardAccountRoleIconComponent, SceInlineApiErrorComponent, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"selectAccountLayout\">\n <div class=\"head\">\n <h2 class=\"title\">{{ 'loginModal.selectAccountTitle' | translate }}</h2>\n <p class=\"subtitle\">{{ 'loginModal.selectAccountSubtitle' | translate }}</p>\n </div>\n\n <div class=\"accountList\">\n @for (account of accounts(); track account.id) {\n <button\n type=\"button\"\n class=\"accountCard\"\n [class.accountCardSelected]=\"selectedAccountId() === account.id\"\n [attr.aria-pressed]=\"selectedAccountId() === account.id\"\n (click)=\"selectAccount.emit(account.id)\"\n >\n <div class=\"accountAvatar\">\n <sce-dashboard-account-role-icon\n [role]=\"$any(account.role)\"\n [accountKind]=\"account.kind\"\n [alt]=\"account.name\"\n [width]=\"56\"\n [height]=\"56\"\n [photoUrl]=\"account.avatarSrc ?? null\"\n />\n </div>\n <div class=\"accountInfo\">\n <span class=\"accountNameRow\">\n <span class=\"accountName\">{{ account.name }}</span>\n <span class=\"accountTag\">{{ account.tag }}</span>\n </span>\n <span class=\"accountDescription\">{{ account.description }}</span>\n </div>\n <span class=\"accountRadio\" [class.accountRadioSelected]=\"selectedAccountId() === account.id\" aria-hidden=\"true\"></span>\n </button>\n }\n </div>\n\n <div class=\"selectAccountFooter\">\n @if (apiError()) {\n <sce-inline-api-error [message]=\"apiError()!\" />\n }\n <p-button\n type=\"button\"\n styleClass=\"submit w-full\"\n [ariaLabel]=\"'loginModal.enterPlatform' | translate\"\n [disabled]=\"submitting()\"\n (onClick)=\"submitted.emit()\"\n >\n @if (submitting()) {\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'loginModal.enterPlatform' | translate }}\n }\n </p-button>\n </div>\n</div>\n" }]
8196
8321
  }], propDecorators: { accounts: [{ type: i0.Input, args: [{ isSignal: true, alias: "accounts", required: true }] }], selectedAccountId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedAccountId", required: false }] }], apiError: [{ type: i0.Input, args: [{ isSignal: true, alias: "apiError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], selectAccount: [{ type: i0.Output, args: ["selectAccount"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
8197
8322
 
8323
+ /** Login flow step collecting the missing mobile and email of a profile, emitting each change and the final submit. */
8198
8324
  class SceLoginCompleteDataStepComponent {
8199
8325
  mobile = input.required(...(ngDevMode ? [{ debugName: "mobile" }] : /* istanbul ignore next */ []));
8200
8326
  email = input.required(...(ngDevMode ? [{ debugName: "email" }] : /* istanbul ignore next */ []));
@@ -8212,6 +8338,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8212
8338
  args: [{ host: { class: 'sce-login-complete-data-step' }, selector: 'sce-login-complete-data-step', standalone: true, imports: [TranslatePipe, Button, SceTextFieldComponent, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"head\">\n <h2 class=\"title\">{{ 'loginModal.completeDataTitle' | translate }}</h2>\n <p class=\"subtitle\">{{ 'loginModal.completeDataSubtitle' | translate }}</p>\n</div>\n\n<div class=\"form\">\n <sce-text-field\n id=\"login-mobile\"\n [label]=\"'loginModal.mobileNumber' | translate\"\n [value]=\"mobile()\"\n [error]=\"mobileError()\"\n (valueChange)=\"mobileChange.emit($event)\"\n />\n <sce-text-field\n id=\"login-email\"\n [label]=\"'loginModal.email' | translate\"\n [value]=\"email()\"\n [error]=\"emailError()\"\n (valueChange)=\"emailChange.emit($event)\"\n />\n <p-button\n type=\"button\"\n styleClass=\"submit w-full\"\n [ariaLabel]=\"'loginModal.saveAndContinue' | translate\"\n [disabled]=\"submitting()\"\n (onClick)=\"submitted.emit()\"\n >\n @if (submitting()) {\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'loginModal.saveAndContinue' | translate }}\n }\n </p-button>\n</div>\n" }]
8213
8339
  }], propDecorators: { mobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobile", required: true }] }], email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: true }] }], mobileError: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileError", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], mobileChange: [{ type: i0.Output, args: ["mobileChange"] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
8214
8340
 
8341
+ /** Login flow step showing a failure message with a retry action. */
8215
8342
  class SceLoginErrorStepComponent {
8216
8343
  errorMessage = input(...(ngDevMode ? [undefined, { debugName: "errorMessage" }] : /* istanbul ignore next */ []));
8217
8344
  submitting = input(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
@@ -8224,6 +8351,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8224
8351
  args: [{ host: { class: 'sce-login-error-step' }, selector: 'sce-login-error-step', standalone: true, imports: [TranslatePipe, Button, SceIcon, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"errorStep\">\n <div class=\"errorIconWrap\">\n <sce-icon name=\"alert-01\" [size]=\"52\" aria-hidden=\"true\" />\n </div>\n <h2 class=\"errorTitle\" role=\"alert\">\n {{ errorMessage() || ('loginModal.verifyFailedTitle' | translate) }}\n </h2>\n @if (!errorMessage()) {\n <p class=\"errorSubtitle\">{{ 'loginModal.verifyFailedSubtitle' | translate }}</p>\n }\n <p-button\n type=\"button\"\n styleClass=\"submit w-full\"\n [ariaLabel]=\"'loginModal.tryAgain' | translate\"\n [disabled]=\"submitting()\"\n (onClick)=\"retry.emit()\"\n >\n @if (submitting()) {\n <sce-skeleton variant=\"text\" width=\"7rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'loginModal.tryAgain' | translate }}\n }\n </p-button>\n</div>\n", styles: [":host{display:block}.errorStep{display:flex;flex-direction:column;align-items:center;text-align:center;gap:var(--space-16);padding-block-start:var(--space-8)}.errorIconWrap{width:var(--space-80);height:var(--space-80);border-radius:var(--radius-2xl);display:flex;align-items:center;justify-content:center}.errorTitle{margin:0;font-weight:var(--font-weight-bold);font-size:var(--font-size-xl);line-height:var(--line-height-normal);color:var(--text-text-primary-900);white-space:pre-wrap}.errorSubtitle{font-weight:var(--font-weight-regular);font-size:var(--font-size-lg);color:var(--text-text-secondary-700)}\n"] }]
8225
8352
  }], propDecorators: { errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], retry: [{ type: i0.Output, args: ["retry"] }] } });
8226
8353
 
8354
+ /** Landing-page hero header with a title, breadcrumb trail and optional background image, rendered either as decorative left-aligned artwork or as a full-bleed cover photo. */
8227
8355
  class SceLandingHeroHeaderComponent {
8228
8356
  title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : /* istanbul ignore next */ []));
8229
8357
  breadcrumbs = input([], ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
@@ -8259,6 +8387,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8259
8387
  args: [{ host: { class: 'sce-dashboard-feature-coming-soon' }, selector: 'sce-dashboard-feature-coming-soon', standalone: true, imports: [SceEmptyStateComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"sce-dashboard-feature-coming-soon__panel\">\n <sce-empty-state [titleKey]=\"titleKey()\" [subtitleKey]=\"subtitleKey()\" [icon]=\"icon()\" [compact]=\"false\" tone=\"info\" />\n</section>\n", styles: [":host{display:block;width:100%}.sce-dashboard-feature-coming-soon__panel{display:flex;align-items:center;justify-content:center;min-block-size:var(--space-320, 20rem);padding:var(--space-8)}\n"] }]
8260
8388
  }], propDecorators: { titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: true }] }], subtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleKey", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }] } });
8261
8389
 
8390
+ /** Cell renderer selected for a `GridColumn` (text, status tag, progress bar, toggle, action button/menu, custom template…). */
8262
8391
  var ColumnsEnum;
8263
8392
  (function (ColumnsEnum) {
8264
8393
  ColumnsEnum["TOGGLE"] = "toggle";
@@ -8338,6 +8467,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8338
8467
  args: [{ name: 'statusConfig', standalone: true }]
8339
8468
  }] });
8340
8469
 
8470
+ /** Marks an `<ng-template sceCustomCol="columnDef">` inside `sce-grid-table` as the renderer for the column whose `columnDef` matches. */
8341
8471
  class SceCustomColsDirective {
8342
8472
  sceCustomCol = input.required(...(ngDevMode ? [{ debugName: "sceCustomCol" }] : /* istanbul ignore next */ []));
8343
8473
  templateRef = inject((TemplateRef));
@@ -8352,6 +8482,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8352
8482
  }]
8353
8483
  }], propDecorators: { sceCustomCol: [{ type: i0.Input, args: [{ isSignal: true, alias: "sceCustomCol", required: true }] }] } });
8354
8484
 
8485
+ /** Marks an `<ng-template sceGridExpansion>` as the expanded-row body of `sce-grid-table`; the row is passed as `$implicit`. */
8355
8486
  class SceGridExpansionDirective {
8356
8487
  templateRef = inject((TemplateRef));
8357
8488
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceGridExpansionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -8366,6 +8497,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8366
8497
  }] });
8367
8498
 
8368
8499
  const GRID_TABLE_LOADING_DELAY_MS = 300;
8500
+ /** PrimeNG-backed data table driven by a `columns` config: renders typed cells, row actions/menus, selection, expandable rows and skeletons, and switches between empty, filtered, searched and error result states; supports both client-side and `lazy` server-side paging/sorting, emitting `pageChange`/`sortChange` rather than fetching itself. */
8369
8501
  class SceGridTableComponent {
8370
8502
  showSelect = input(false, ...(ngDevMode ? [{ debugName: "showSelect" }] : /* istanbul ignore next */ []));
8371
8503
  btnLabel = input('table.addNewCard', ...(ngDevMode ? [{ debugName: "btnLabel" }] : /* istanbul ignore next */ []));
@@ -8689,6 +8821,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8689
8821
  }], ctorParameters: () => [], propDecorators: { showSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSelect", required: false }] }], btnLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "btnLabel", required: false }] }], selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: false }] }, { type: i0.Output, args: ["selectedItemsChange"] }], searchPipeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPipeKey", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], showAddButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAddButton", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingDelay", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], totalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalRecords", required: false }] }], totalPages: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalPages", required: false }] }], pageNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageNumber", required: false }] }], first: [{ type: i0.Input, args: [{ isSignal: true, alias: "first", required: false }] }], tableMinWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableMinWidth", required: false }] }], emptyStateIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateIcon", required: false }] }], emptyStateTitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateTitleKey", required: false }] }], emptyStateSubtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateSubtitleKey", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], errorTitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorTitleKey", required: false }] }], errorSubtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorSubtitleKey", required: false }] }], errorStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStatus", required: false }] }], filtered: [{ type: i0.Input, args: [{ isSignal: true, alias: "filtered", required: false }] }], searching: [{ type: i0.Input, args: [{ isSignal: true, alias: "searching", required: false }] }], sortField: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortField", required: false }] }], sortOrder: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortOrder", required: false }] }], rowRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowRoute", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], addActionEvent: [{ type: i0.Output, args: ["addActionEvent"] }], searchQuery: [{ type: i0.Output, args: ["searchQuery"] }], selectItems: [{ type: i0.Output, args: ["selectItems"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], errorRetry: [{ type: i0.Output, args: ["errorRetry"] }], clearFilters: [{ type: i0.Output, args: ["clearFilters"] }], clearSearch: [{ type: i0.Output, args: ["clearSearch"] }], rowNavigate: [{ type: i0.Output, args: ["rowNavigate"] }], customColumnTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SceCustomColsDirective), { isSignal: true }] }], expansionTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SceGridExpansionDirective), { isSignal: true }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }] } });
8690
8822
 
8691
8823
  const MULTI_TYPES = new Set(['checkbox', 'checkbox-search', 'multiselect', 'date-range']);
8824
+ /** Renders a filter bar from a declarative `config` (it is not a reactive form — values live in a plain `model` signal), emits `filterChange` debounced (default 300 ms), sanitises typed text against HTML/script injection, and can show a quick-filter chip bar with per-chip removal. */
8692
8825
  class SceFilterFormComponent {
8693
8826
  config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
8694
8827
  quickFilterTitle = input('', ...(ngDevMode ? [{ debugName: "quickFilterTitle" }] : /* istanbul ignore next */ []));
@@ -8879,6 +9012,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8879
9012
  args: [{ host: { class: 'sce-filter-form' }, selector: 'sce-filter-form', standalone: true, imports: [FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<form class=\"sce-filter-form\" (submit)=\"$event.preventDefault(); onSubmit()\">\n <div class=\"sce-filter-form__grid\" [style.grid-template-columns]=\"gridTemplateColumns()\">\n @for (field of config().fields; track field.key) {\n <div class=\"sce-filter-form__cell\" [style.grid-column]=\"config().columns != null ? 'span ' + (field.colspan ?? 1) : ''\">\n @if (field.type === 'divider') {\n <hr class=\"sce-filter-form__divider\" />\n } @else if (field.type === 'select') {\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <select\n class=\"sce-filter-form__select\"\n [id]=\"'filter-' + field.key\"\n [attr.aria-label]=\"field.label ? null : (field.placeholder ?? field.key | translate)\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (change)=\"onSelectChange(field.key, $event)\"\n >\n @if (field.placeholder) {\n <option value=\"\">{{ field.placeholder | translate }}</option>\n }\n @for (opt of field.options ?? []; track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label | translate }}</option>\n }\n </select>\n </div>\n } @else if (field.type === 'search') {\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <div class=\"sce-filter-form__input-wrapper\">\n @if (field.icon && field.iconPosition !== 'end') {\n <i class=\"pi\" [class]=\"field.icon\" aria-hidden=\"true\"></i>\n }\n <input\n type=\"text\"\n class=\"sce-filter-form__input\"\n [id]=\"'filter-' + field.key\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : ''\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (input)=\"onInputChange(field.key, $event)\"\n />\n @if (field.icon && field.iconPosition === 'end') {\n <i class=\"pi\" [class]=\"field.icon\" aria-hidden=\"true\"></i>\n }\n </div>\n </div>\n } @else if (field.type === 'date' || field.type === 'datetime') {\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <input\n [type]=\"field.type === 'datetime' ? 'datetime-local' : 'date'\"\n class=\"sce-filter-form__input\"\n [id]=\"'filter-' + field.key\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : ''\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (input)=\"onInputChange(field.key, $event)\"\n />\n </div>\n } @else if (field.type === 'number') {\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <input\n type=\"number\"\n class=\"sce-filter-form__input\"\n [id]=\"'filter-' + field.key\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : ''\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (input)=\"onInputChange(field.key, $event)\"\n />\n </div>\n } @else {\n <!-- Default: text input -->\n <div class=\"sce-filter-form__field\">\n @if (field.label) {\n <label class=\"sce-filter-form__label\" [for]=\"'filter-' + field.key\">{{ field.label | translate }}</label>\n }\n <input\n type=\"text\"\n class=\"sce-filter-form__input\"\n [id]=\"'filter-' + field.key\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : ''\"\n [disabled]=\"field.disabled ?? false\"\n [value]=\"fieldStringValues()[field.key]\"\n (input)=\"onInputChange(field.key, $event)\"\n />\n </div>\n }\n </div>\n }\n </div>\n\n @if (showSubmit() || showReset()) {\n <div class=\"sce-filter-form__actions\">\n @if (showSubmit()) {\n <button type=\"submit\" class=\"sce-filter-form__btn sce-filter-form__btn--primary\">\n {{ 'FILTER.APPLY' | translate }}\n </button>\n }\n @if (showReset()) {\n <button type=\"button\" class=\"sce-filter-form__btn sce-filter-form__btn--ghost\" [disabled]=\"!hasActiveFilters()\" (click)=\"onReset()\">\n {{ 'FILTER.RESET' | translate }}\n </button>\n }\n </div>\n }\n\n @if (showQuickFilterBar() && hasActiveFilters()) {\n <div class=\"sce-filter-form__quick-filters\" [style.justify-content]=\"quickFilterRowJustify()\">\n <div class=\"sce-filter-form__tags\" [style.gap]=\"quickFilterTagGap()\">\n @for (tag of activeFilterTags(); track tag.key) {\n <span class=\"sce-filter-form__tag\">\n <span class=\"sce-filter-form__tag-label\">{{ tag.label | translate }}:</span>\n <span class=\"sce-filter-form__tag-value\">{{ tag.value || (tag.values ?? []).join(', ') }}</span>\n @if (showRemoveOnTag()) {\n <button\n type=\"button\"\n class=\"sce-filter-form__tag-remove\"\n (click)=\"onFilterTagClick(tag)\"\n [attr.aria-label]=\"'aria.removeFilter' | translate\"\n >\n <i class=\"pi pi-times sce-filter-form__tag-remove-icon\"></i>\n </button>\n }\n </span>\n }\n </div>\n <div class=\"sce-filter-form__quick-actions\">\n @if (showClearAll()) {\n <button type=\"button\" class=\"sce-filter-form__link-btn\" (click)=\"onClearAll()\">\n {{ 'FILTER.CLEAR_ALL' | translate }}\n </button>\n }\n @if (showSaveFilter()) {\n <button type=\"button\" class=\"sce-filter-form__link-btn\" (click)=\"saveFilterClick.emit()\">\n {{ 'FILTER.SAVE_FILTER' | translate }}\n </button>\n }\n </div>\n </div>\n }\n</form>\n", styles: ["@charset \"UTF-8\";:host{display:block}.sce-filter-form{width:100%}.sce-filter-form__divider{border:none;border-block-start:1px solid var(--color-border);margin-block-start:var(--space-12)}.sce-filter-form__grid{display:grid;align-items:end;gap:var(--space-12)}.sce-filter-form__grid>*{min-width:0}.sce-filter-form__cell{min-width:0}.sce-filter-form__field{display:flex;flex-direction:column;gap:var(--space-4);width:100%}.sce-filter-form__label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-default)}.sce-filter-form__input-wrapper{display:flex;align-items:center;gap:var(--space-8);border:1px solid var(--border-neutral-primary);border-radius:var(--radius-md);padding-block:0;padding-inline:var(--space-12);background:var(--color-white, var(--background-bg-primary));transition:border-color .15s ease}.sce-filter-form__input-wrapper:focus-within{border-color:var(--color-primary);box-shadow:0 0 0 1px var(--color-primary)}.sce-filter-form__input-wrapper .pi{color:var(--color-icon-default);font-size:var(--font-size-sm)}.sce-filter-form__input-wrapper .sce-filter-form__input{border:none;padding-inline:0;box-shadow:none}.sce-filter-form__input-wrapper .sce-filter-form__input:focus{box-shadow:none}.sce-filter-form__input,.sce-filter-form__select{width:100%;height:var(--space-36);padding-block:0;padding-inline:var(--space-12);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-default);background:var(--color-white, var(--background-bg-primary));border:1px solid var(--border-neutral-primary);border-radius:var(--radius-md);transition:border-color .15s ease}.sce-filter-form__input::placeholder,.sce-filter-form__select::placeholder{color:var(--form-field-text-placeholder);font-weight:var(--font-weight-medium);font-size:var(--font-size-sm)}.sce-filter-form__input:focus,.sce-filter-form__select:focus{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 1px var(--color-primary)}.sce-filter-form__input:disabled,.sce-filter-form__select:disabled{opacity:.5;cursor:not-allowed}.sce-filter-form__select{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-inline-end:var(--space-40)}:host-context([dir=rtl]) .sce-filter-form__select{background-position:left .5rem center}.sce-filter-form__actions{display:flex;align-items:center;gap:var(--space-8);padding-block-start:var(--space-12)}.sce-filter-form__btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-24);height:var(--space-36);padding-block:0;padding-inline:var(--space-16);border-radius:var(--radius-md);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:background-color .15s ease,color .15s ease,border-color .15s ease;white-space:nowrap}.sce-filter-form__btn:disabled{opacity:.45;cursor:not-allowed}.sce-filter-form__btn--primary{background:var(--color-primary);color:var(--color-white, var(--background-bg-primary));border:1px solid var(--color-primary)}.sce-filter-form__btn--primary:not(:disabled):hover{background:var(--color-primary-dark, var(--color-primary-700));border-color:var(--color-primary-dark, var(--color-primary-700))}.sce-filter-form__btn--ghost{background:transparent;color:var(--color-text-secondary);border:1px solid var(--color-border)}.sce-filter-form__btn--ghost:not(:disabled):hover{background:var(--color-surface-subtle);color:var(--color-text-default)}.sce-filter-form__quick-filters{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-12);padding-block-start:var(--space-12)}.sce-filter-form__tags{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-8)}.sce-filter-form__tag{display:inline-flex;align-items:center;gap:var(--space-4);padding:var(--space-4) var(--space-8);background:var(--color-surface-subtle);border-radius:var(--radius-full);font-size:var(--font-size-xs);color:var(--color-text-default)}.sce-filter-form__tag-label{font-weight:var(--font-weight-medium)}.sce-filter-form__tag-value{color:var(--color-text-secondary)}.sce-filter-form__tag-remove{display:inline-flex;align-items:center;justify-content:center;width:var(--space-16);height:var(--space-16);border:none;background:transparent;cursor:pointer;color:var(--color-text-secondary);border-radius:var(--radius-full);transition:background .15s ease}.sce-filter-form__tag-remove:hover{background:var(--color-border);color:var(--color-text-default)}.sce-filter-form__tag-remove-icon{font-size:var(--font-size-xs)}.sce-filter-form__quick-actions{display:flex;align-items:center;gap:var(--space-12)}.sce-filter-form__link-btn{display:inline-flex;align-items:center;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-primary);background:transparent;border:none;cursor:pointer;padding:0;text-decoration:none}.sce-filter-form__link-btn:hover{text-decoration:underline}@media(max-width:1280px){.sce-filter-form__grid{display:flex;flex-wrap:wrap}.sce-filter-form__grid .sce-filter-form__cell{flex:1 1 180px;min-width:0}}@media(max-width:768px){.sce-filter-form__grid .sce-filter-form__cell{flex:1 1 140px}}@media(max-width:640px){.sce-filter-form__grid .sce-filter-form__cell{flex:1 1 100%}.sce-filter-form__actions{flex-direction:column}.sce-filter-form__actions .sce-filter-form__btn{width:100%}}\n"] }]
8880
9013
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], quickFilterTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterTitle", required: false }] }], quickFilterCounter: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterCounter", required: false }] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], filterSubmit: [{ type: i0.Output, args: ["filterSubmit"] }], filterReset: [{ type: i0.Output, args: ["filterReset"] }], saveFilterClick: [{ type: i0.Output, args: ["saveFilterClick"] }] } });
8881
9014
 
9015
+ /** All-in-one labelled field that switches its control on the `type` input (text, password, phone, number, select, multiselect, date/datetime, textarea, checkbox/radio); it is a self-registering `ControlValueAccessor` (`NgControl` is injected with `self`, so `formControlName` works) and maps validator errors to i18n keys, overridable per field via `errorMessages`. */
8882
9016
  class FormInput {
8883
9017
  static nextId = 0;
8884
9018
  phoneConfig = PHONE_CONFIG;
@@ -9144,6 +9278,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9144
9278
  args: [{ host: { class: 'sce-form-input' }, selector: 'sce-form-input', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (label() || subText()) {\n <label class=\"form-input__label\" [id]=\"fieldId + '-label'\" [attr.for]=\"isCheckboxRadio() ? null : fieldId\">\n @if (label()) {\n <span class=\"form-input__label-text\">{{ label() | translate }}</span>\n }\n @if (required()) {\n <span class=\"form-input__required\" aria-hidden=\"true\">*</span>\n }\n @if (subText()) {\n <span class=\"form-input__sub-text\">{{ subText() | translate }}</span>\n }\n </label>\n}\n\n<div\n class=\"form-input__wrapper\"\n [class.form-input__wrapper--focused]=\"focused()\"\n [class.form-input__wrapper--disabled]=\"disabled()\"\n [class.form-input__wrapper--error]=\"showError()\"\n [class.form-input__wrapper--has-toggle]=\"isPassword()\"\n [class.form-input__wrapper--textarea]=\"isTextarea()\"\n [class.is-ltr]=\"isPhone()\"\n [class.form-input__wrapper--small]=\"size() === 'small'\"\n [class.form-input__wrapper--medium]=\"size() === 'medium'\"\n [class.form-input__wrapper--large]=\"size() === 'large'\"\n [class.form-input__wrapper--date-picker]=\"isDatePicker()\"\n [class.form-input__wrapper--borderless]=\"isCheckboxRadio()\"\n [class.form-input__wrapper--with-inline-suffix]=\"!!inlineSuffix()\"\n>\n @if (isSelect()) {\n <select\n class=\"form-input__select\"\n [id]=\"fieldId\"\n [attr.aria-label]=\"label() ? null : (placeholder() | translate)\"\n [value]=\"value()\"\n [disabled]=\"disabled()\"\n (change)=\"onSelectChange($any($event).target.value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >\n @if (placeholder()) {\n <option value=\"\" disabled selected>{{ placeholder() | translate }}</option>\n }\n @for (opt of options(); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n } @else if (isMultiSelect()) {\n <select\n class=\"form-input__select\"\n multiple\n [id]=\"fieldId\"\n [attr.aria-label]=\"label() ? null : (placeholder() | translate)\"\n [disabled]=\"disabled()\"\n (change)=\"onMultiSelectChange($any($event))\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >\n @for (opt of options(); track opt.value) {\n <option [value]=\"opt.value\">{{ opt.label }}</option>\n }\n </select>\n } @else if (isTextarea()) {\n <textarea\n class=\"form-input__textarea\"\n [id]=\"fieldId\"\n [rows]=\"rows()\"\n [placeholder]=\"placeholder() | translate\"\n [disabled]=\"disabled()\"\n [value]=\"value()\"\n [attr.maxlength]=\"maxLength()\"\n (input)=\"onInput($any($event).target.value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n ></textarea>\n } @else if (isCheckboxRadio()) {\n <div class=\"form-input__checkbox-group\" [class.form-input__checkbox-group--horizontal]=\"layout() === 'horizontal'\">\n @for (opt of options(); track opt.value) {\n <label class=\"form-input__checkbox-label\">\n <input\n [type]=\"type() === 'radio' ? 'radio' : 'checkbox'\"\n [name]=\"radioName()\"\n [value]=\"opt.value\"\n [checked]=\"type() === 'radio' ? value() === opt.value : multiValue().includes(opt.value)\"\n [disabled]=\"disabled()\"\n (change)=\"type() === 'radio' ? onRadioChange(opt.value) : onCheckboxChange(\n $any($event).target.checked\n ? [...multiValue(), opt.value]\n : multiValue().filter(v => v !== opt.value)\n )\"\n />\n <span>{{ opt.label }}</span>\n </label>\n }\n </div>\n } @else {\n @if (isPhone()) {\n <div class=\"form-input__countrycode\" aria-hidden=\"true\">\n <span dir=\"ltr\">{{ phoneConfig.COUNTRY_CODE }}</span>\n </div>\n }\n\n <input\n class=\"form-input__field\"\n [id]=\"fieldId\"\n [type]=\"inputType()\"\n [value]=\"value()\"\n [placeholder]=\"placeholder() | translate\"\n [disabled]=\"disabled()\"\n [attr.maxlength]=\"maxLengthOverride() ?? maxLength()\"\n [attr.inputmode]=\"inputMode()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.dir]=\"isPhone() ? 'ltr' : null\"\n (input)=\"onInput($any($event).target.value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n />\n\n @if (inlineSuffix()) {\n <span class=\"form-input__inline-suffix\" aria-hidden=\"true\">{{ inlineSuffix() }}</span>\n }\n }\n\n @if (isPassword()) {\n <button\n type=\"button\"\n class=\"form-input__password-toggle\"\n (click)=\"togglePassword()\"\n [attr.aria-label]=\"showPassword() ? ('COMMON.HIDE_PASSWORD' | translate) : ('COMMON.SHOW_PASSWORD' | translate)\"\n >\n <i class=\"pi\" [class.pi-eye]=\"!showPassword()\" [class.pi-eye-slash]=\"showPassword()\"></i>\n </button>\n }\n</div>\n\n@if (showError()) {\n <p class=\"form-input__error\" role=\"alert\">{{ errorKey() | translate }}</p>\n}\n", styles: [":host.sce-form-input{display:block}.form-input__label{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-xs);margin-block-end:var(--space-xs)}.form-input__label-text{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--Form-field-text-label)}.form-input__required{color:var(--color-error);font-weight:var(--font-weight-semibold)}.form-input__sub-text{font-size:var(--font-size-xs);color:var(--color-text-muted)}.form-input__wrapper{position:relative;display:flex;align-items:center;background-color:var(--color-white);border:1px solid var(--border-neutral-primary);border-radius:var(--radius-md);transition:border-color var(--transition-base),box-shadow var(--transition-base)}@media(hover:hover)and (pointer:fine){.form-input__wrapper:hover:not(.form-input__wrapper--disabled):not(.form-input__wrapper--focused):not(.form-input__wrapper--error){border-color:var(--field-border-hovered)}}.form-input__wrapper:after{content:\"\";position:absolute;inset-block-end:0;inset-inline:50%;height:var(--border-width-1);background:var(--field-border-pressed);transition:inset-inline var(--transition-base);border-end-start-radius:var(--radius-md);border-end-end-radius:var(--radius-md)}.form-input__wrapper:active:not(.form-input__wrapper--disabled):not(.form-input__wrapper--error){background-color:var(--field-background-pressed)}.form-input__wrapper:active:not(.form-input__wrapper--disabled):not(.form-input__wrapper--error):after{inset-inline:0}.form-input__wrapper--focused:not(.form-input__wrapper--disabled):not(.form-input__wrapper--error){border-color:var(--color-border-focus)}.form-input__wrapper--focused:not(.form-input__wrapper--disabled):not(.form-input__wrapper--error):after{inset-inline:0}.form-input__wrapper--small .form-input__field,.form-input__wrapper--small .form-input__select,.form-input__wrapper--small .form-input__textarea{padding:var(--space-sm) var(--space-md)}.form-input__wrapper--large{min-inline-size:var(--size-360)}.form-input__wrapper--disabled{background-color:var(--color-disabled-bg);cursor:not-allowed}.form-input__wrapper--error{border-color:var(--color-error)}.form-input__wrapper--borderless{border:none;background:transparent}.form-input__wrapper--borderless:after{display:none}.form-input__wrapper--date-picker{cursor:pointer}.form-input__wrapper--textarea{align-items:flex-start;min-block-size:var(--space-80)}.form-input__wrapper--with-inline-suffix .form-input__field{flex:1;min-inline-size:0}.form-input__wrapper.is-ltr{direction:ltr;unicode-bidi:isolate}.form-input__wrapper.is-ltr .form-input__field{direction:ltr;text-align:start;flex:1;min-inline-size:0}.form-input__field{width:100%;padding:var(--space-md) var(--space-lg);font-size:var(--font-size-sm);font-family:inherit;color:var(--color-text);background:transparent;border:none;outline:none}.form-input__field::placeholder{color:var(--Form-field-text-placeholder, var(--color-neutral-500));font-size:var(--font-size-sm);font-weight:500}.form-input__field:disabled{cursor:not-allowed;opacity:.6}.form-input__select{width:100%;padding:var(--space-md) var(--space-lg);font-size:var(--font-size-sm);font-family:inherit;color:var(--color-text);background:transparent;border:none;outline:none;cursor:pointer;appearance:none}.form-input__select:disabled{cursor:not-allowed;opacity:.6}.form-input__inline-suffix{flex-shrink:0;padding-inline-end:var(--space-md);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-display);-webkit-user-select:none;user-select:none}.form-input__textarea{width:100%;padding:var(--space-md) var(--space-lg);font-size:var(--font-size-sm);font-family:inherit;color:var(--color-text);background:transparent;border:none;border-radius:var(--radius-md);outline:none;resize:block;overflow-y:auto;line-height:1.5}.form-input__textarea::placeholder{color:var(--Form-field-text-placeholder, var(--color-neutral-500));font-size:var(--font-size-sm);font-weight:500}.form-input__textarea:focus-visible{outline:none}.form-input__textarea:disabled{cursor:not-allowed;opacity:.6}.form-input__countrycode{display:flex;flex-shrink:0;align-items:center;align-self:stretch;padding:0 var(--space-md);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--text-secondary-700, var(--color-neutral-600));background:var(--app-surface-muted, var(--color-neutral-50));border-inline-end:1px solid var(--border-neutral-primary);-webkit-user-select:none;user-select:none;direction:ltr;unicode-bidi:isolate}.form-input__countrycode span{direction:ltr;unicode-bidi:isolate;white-space:nowrap}.form-input__password-toggle{position:absolute;inset-inline-end:var(--space-md);display:flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;color:var(--color-icon-default);padding:var(--space-xs)}.form-input__password-toggle:hover{color:var(--color-primary)}.form-input__password-toggle:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px;border-radius:var(--radius-md)}.form-input__checkbox-group{display:flex;flex-direction:column;gap:var(--space-sm);padding:var(--space-sm)}.form-input__checkbox-group--horizontal{flex-direction:row;flex-wrap:wrap}.form-input__checkbox-label{display:flex;align-items:center;gap:var(--space-xs);font-size:var(--font-size-sm);color:var(--color-text);cursor:pointer}.form-input__checkbox-label input{accent-color:var(--color-primary)}.form-input__error{margin-block-start:var(--space-xs);font-size:var(--font-size-sm);color:var(--color-error)}\n"] }]
9145
9279
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], subText: [{ type: i0.Input, args: [{ isSignal: true, alias: "subText", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], dateAppendToBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateAppendToBody", required: false }] }], dateSelectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateSelectionMode", required: false }] }], dateShowDropdownIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateShowDropdownIcon", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], valueDateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueDateFormat", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], radioName: [{ type: i0.Input, args: [{ isSignal: true, alias: "radioName", required: false }] }], selectShowFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectShowFilter", required: false }] }], selectAppendToBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAppendToBody", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], restrictInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "restrictInput", required: false }] }], filterOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterOverride", required: false }] }], maxLengthOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLengthOverride", required: false }] }], inlineSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineSuffix", required: false }] }], errorMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessages", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], multiValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiValue", required: false }] }, { type: i0.Output, args: ["multiValueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }] } });
9146
9280
 
9281
+ /** Row of `length` single-digit OTP boxes (default `VALIDATION_LENGTHS.OTP`) with auto-advance, backspace-back and paste-to-fill; a self-registering `ControlValueAccessor` whose value is the joined digit string. */
9147
9282
  class OtpInput {
9148
9283
  length = input(VALIDATION_LENGTHS.OTP, ...(ngDevMode ? [{ debugName: "length" }] : /* istanbul ignore next */ []));
9149
9284
  submitted = input(false, ...(ngDevMode ? [{ debugName: "submitted" }] : /* istanbul ignore next */ []));
@@ -9625,6 +9760,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9625
9760
  ], host: { class: 'sce-dynamic-form' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<form class=\"sce-dynamic-form__form\" [formGroup]=\"form()\" (ngSubmit)=\"onSubmit()\">\n @for (section of renderSections(); track section.fields[0].key) {\n <section class=\"sce-dynamic-form__section\">\n @if (section.title) {\n <h3 class=\"sce-dynamic-form__section-title\">{{ section.title | translate }}</h3>\n }\n @if (section.description) {\n <p class=\"sce-dynamic-form__section-desc\">{{ section.description | translate }}</p>\n }\n <div class=\"sce-dynamic-form__grid\" [style.grid-template-columns]=\"section.gridTemplateColumns\" [style.gap]=\"gap()\">\n @for (field of section.fields; track field.key) {\n <div class=\"sce-dynamic-form__field\" [style.grid-column]=\"field.gridColumn\">\n @if (field.isMulti) {\n <sce-form-input\n [type]=\"$any(field.type)\"\n [label]=\"field.label ?? ''\"\n [subText]=\"field.subText ?? ''\"\n [placeholder]=\"field.placeholder ?? ''\"\n [options]=\"field.options ?? []\"\n [layout]=\"field.layout ?? 'vertical'\"\n [required]=\"!!field.validators?.required\"\n [submitted]=\"effectiveSubmitted()\"\n [errorMessages]=\"field.errorMessages ?? {}\"\n [disabled]=\"!!field.disabled\"\n [multiValue]=\"multiValues()[field.key]\"\n (multiValueChange)=\"onMultiChange(field.key, $event)\"\n />\n } @else if (field.type === 'currency') {\n <sce-currency-input\n [id]=\"field.key\"\n [label]=\"field.label ?? '' | translate\"\n [placeholder]=\"field.placeholder ? (field.placeholder | translate) : '0.00'\"\n [value]=\"$any(liveValues()[field.key])\"\n [required]=\"!!field.validators?.required\"\n [disabled]=\"!!field.disabled\"\n [error]=\"fieldErrors()[field.key]\"\n [invalid]=\"!!fieldErrors()[field.key]\"\n (valueChange)=\"setControlValue(field.key, $event)\"\n />\n } @else if (field.type === 'unit') {\n <sce-unit-input-field\n [id]=\"field.key\"\n [label]=\"field.label ?? '' | translate\"\n [unitInput]=\"field.unit ?? '' | translate\"\n [placeholder]=\"field.placeholder ?? ''\"\n [value]=\"$any(liveValues()[field.key])\"\n [required]=\"!!field.validators?.required\"\n [allowDecimal]=\"field.allowDecimal ?? true\"\n [error]=\"fieldErrors()[field.key]\"\n (valueChange)=\"setControlValue(field.key, $event)\"\n />\n } @else if (field.type === 'switch') {\n <sce-field\n [id]=\"field.key\"\n [label]=\"field.label ?? '' | translate\"\n [required]=\"!!field.validators?.required\"\n [error]=\"fieldErrors()[field.key]\"\n >\n <sce-switch\n [checked]=\"$any(liveValues()[field.key])\"\n [disabled]=\"!!field.disabled\"\n [showLabel]=\"!!(field.activeLabel || field.inactiveLabel)\"\n [activeLabel]=\"field.activeLabel ?? '' | translate\"\n [inactiveLabel]=\"field.inactiveLabel ?? '' | translate\"\n (checkedChange)=\"setControlValue(field.key, $event)\"\n />\n </sce-field>\n } @else if (field.type === 'rating') {\n <sce-field [id]=\"field.key\" [label]=\"field.label ?? '' | translate\" [required]=\"!!field.validators?.required\">\n <sce-star-rating-input\n [value]=\"$any(liveValues()[field.key])\"\n [disabled]=\"!!field.disabled\"\n [ariaLabel]=\"field.ariaLabel ?? field.label ?? '' | translate\"\n [error]=\"fieldErrors()[field.key]\"\n (valueChange)=\"setControlValue(field.key, $event)\"\n />\n </sce-field>\n } @else if (field.type === 'otp') {\n <sce-field [id]=\"field.key\" [label]=\"field.label ?? '' | translate\" [required]=\"!!field.validators?.required\">\n <sce-otp-input [length]=\"field.length ?? 4\" [submitted]=\"effectiveSubmitted()\" [formControlName]=\"field.key\" />\n </sce-field>\n } @else {\n <sce-form-input\n [type]=\"$any(field.type)\"\n [label]=\"field.label ?? ''\"\n [subText]=\"field.subText ?? ''\"\n [placeholder]=\"field.placeholder ?? ''\"\n [options]=\"field.options ?? []\"\n [rows]=\"field.rows ?? 4\"\n [icon]=\"field.icon ?? ''\"\n [size]=\"field.size ?? 'medium'\"\n [inlineSuffix]=\"field.inlineSuffix ?? ''\"\n [layout]=\"field.layout ?? 'vertical'\"\n [minDate]=\"field.minDate ?? null\"\n [maxDate]=\"field.maxDate ?? null\"\n [restrictInput]=\"field.restrictInput ?? null\"\n [required]=\"!!field.validators?.required\"\n [submitted]=\"effectiveSubmitted()\"\n [errorMessages]=\"field.errorMessages ?? {}\"\n [formControlName]=\"field.key\"\n />\n }\n </div>\n }\n </div>\n </section>\n }\n\n @if (showSubmit()) {\n <div class=\"sce-dynamic-form__actions\">\n <button type=\"submit\" class=\"sce-dynamic-form__submit\">\n {{ submitLabel() | translate }}\n </button>\n </div>\n }\n</form>\n", styles: [":host{display:block}.sce-dynamic-form__form{display:flex;flex-direction:column;gap:var(--space-24)}.sce-dynamic-form__section{display:flex;flex-direction:column;gap:var(--space-3)}.sce-dynamic-form__section-title{margin:0;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.sce-dynamic-form__section-desc{margin:0;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-dynamic-form__grid{display:grid;align-items:start}.sce-dynamic-form__field{min-width:0}.sce-dynamic-form__actions{grid-column:1/-1;display:flex;justify-content:flex-end;margin-block-start:var(--space-2)}.sce-dynamic-form__submit{display:inline-flex;align-items:center;justify-content:center;padding-block:var(--space-3);padding-inline:var(--space-24);border:none;border-radius:var(--radius-lg);background-color:var(--color-primary);color:var(--color-on-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);cursor:pointer;transition:background-color var(--transition-fast)}.sce-dynamic-form__submit:hover{background-color:var(--color-primary-hover)}.sce-dynamic-form__submit:disabled{opacity:.6;cursor:not-allowed}\n"] }]
9626
9761
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], initialValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialValue", required: false }] }], submitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitted", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }], formInvalid: [{ type: i0.Output, args: ["formInvalid"] }] } });
9627
9762
 
9763
+ /** Modal shell over PrimeNG `p-dialog` (portaled to `body`) with projected header/body/footer slots; `size` maps to a max-width and `dismissed` fires exactly once whether closed by button, backdrop or ESC — note it uses `ViewEncapsulation.None`, so its styles are global. */
9628
9764
  class Popup {
9629
9765
  open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
9630
9766
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
@@ -9691,6 +9827,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9691
9827
  args: [{ selector: 'sce-popup', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [Dialog, TranslatePipe], host: { class: 'sce-popup' }, template: "<p-dialog\n [visible]=\"open()\"\n (onHide)=\"onHide()\"\n [modal]=\"true\"\n [dismissableMask]=\"closeOnBackdropClick()\"\n [closeOnEscape]=\"closeOnBackdropClick()\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [closable]=\"false\"\n [showHeader]=\"false\"\n [blockScroll]=\"true\"\n [style]=\"dialogStyle()\"\n [styleClass]=\"dialogStyleClass()\"\n [appendTo]=\"dialogAppendTo\"\n>\n @if (showHeader()) {\n <div class=\"popup__header\" [class.popup__header--large]=\"largeHeader()\">\n <div class=\"popup__header-main\">\n @if (showBackButton()) {\n <button type=\"button\" class=\"popup__header-button back\" (click)=\"back()\" [attr.aria-label]=\"'COMMON.BACK' | translate\">\n <i class=\"pi pi-chevron-left\" style=\"font-size: 1.25rem\"></i>\n </button>\n }\n @if (title()) {\n <div class=\"popup-title__area\">\n <h2 [id]=\"titleId\" class=\"popup__title\">{{ title() }}</h2>\n <ng-content select=\"[subTitle]\"></ng-content>\n </div>\n }\n </div>\n @if (showCloseButton()) {\n <button type=\"button\" class=\"popup__header-button\" (click)=\"close()\" [attr.aria-label]=\"'COMMON.CLOSE' | translate\">\n <i class=\"pi pi-times\" style=\"font-size: 1.25rem\"></i>\n </button>\n }\n </div>\n }\n\n <div class=\"popup__body\" [attr.aria-labelledby]=\"showHeader() && title() ? titleId : null\">\n <ng-content></ng-content>\n </div>\n\n <div [class.popup__footer]=\"footerStyle()\" [class.popup__footer--border]=\"footerBorder()\">\n <ng-content select=\"[popupFooter]\"></ng-content>\n </div>\n</p-dialog>\n", styles: ["@charset \"UTF-8\";.sce-popup-dialog.p-dialog{border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);max-height:calc(100vb - var(--space-xl) * 2);display:flex;flex-direction:column}.sce-popup-dialog.p-dialog .p-dialog-content{padding:0;border-radius:var(--radius-lg);display:flex;flex-direction:column;overflow:hidden;flex:1}.sce-popup-dialog--overflow-visible.p-dialog .p-dialog-content,.sce-popup-dialog--overflow-visible .popup__body{overflow:visible}.popup__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-lg);padding:var(--space-xl) var(--space-xl) 0;flex-shrink:0}.popup__header--large .popup__header-button{width:var(--size-54, 3.375rem);height:var(--size-54, 3.375rem)}.popup__header-main{display:flex;gap:var(--space-md)}.popup__title{margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--color-text-display)}.popup__header-button{display:flex;align-items:center;justify-content:center;width:var(--size-32);height:var(--size-32);padding:var(--space-xs);color:var(--color-icon-default);background:var(--landing-modal-close-bg, var(--color-neutral-100));border:none;border-radius:var(--radius-lg);cursor:pointer;transition:color var(--transition-fast),background-color var(--transition-fast)}.popup__header-button:hover{background:var(--color-neutral-50)}.popup__header-button:focus-visible{outline:var(--space-2) solid var(--color-primary);outline-offset:var(--space-2)}[dir=rtl] .popup__header-button.back{transform:rotate(180deg)}.popup__body{flex:1;overflow-y:auto;padding:var(--space-20) var(--space-xl)}.popup__footer{display:flex;gap:var(--space-lg);justify-content:flex-end;padding:var(--space-lg) var(--space-xl);flex-shrink:0}.popup__footer--border{border-block-start:1px solid var(--color-border)}.popup__footer:empty{display:none}\n"] }]
9692
9828
  }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], footerBorder: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerBorder", required: false }] }], footerStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerStyle", required: false }] }], showCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseButton", required: false }] }], showBackButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBackButton", required: false }] }], largeHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "largeHeader", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], bodyScrollable: [{ type: i0.Input, args: [{ isSignal: true, alias: "bodyScrollable", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], backClicked: [{ type: i0.Output, args: ["backClicked"] }] } });
9693
9829
 
9830
+ /** Abstract base for modal components: holds `isOpen`/`modalData` signals, exposes `openModal(data)`/`closeModal()`, and requires the subclass template to contain a `Popup` whose dismissal closes the modal and re-emits `dismissed`. */
9694
9831
  class PopupModalBase {
9695
9832
  destroyRef = inject(DestroyRef);
9696
9833
  modalData = signal(null, ...(ngDevMode ? [{ debugName: "modalData" }] : /* istanbul ignore next */ []));
@@ -9846,6 +9983,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9846
9983
  }]
9847
9984
  }] });
9848
9985
 
9986
+ /** Tab bar over PrimeNG `p-tabs` that renders `items` and emits `tabChange`, projecting the panel content itself; `activeId` seeds a `linkedSignal` (so the tab strip is uncontrolled after the first click) and a host directive fixes inkbar placement in RTL. */
9849
9987
  class Tabs {
9850
9988
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
9851
9989
  activeId = input('', ...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
@@ -9881,6 +10019,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9881
10019
  args: [{ host: { class: 'sce-tabs' }, selector: 'sce-tabs', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslatePipe, Tabs$1, TabList, Tab], hostDirectives: [TabsInkbarRtlDirective], template: "<div\n class=\"tabs\"\n [class.tabs--default]=\"variant() === 'default'\"\n [class.tabs--pills]=\"variant() === 'pills'\"\n [class.tabs--underline]=\"variant() === 'underline'\"\n [class.tabs--small]=\"size() === 'small'\"\n [class.tabs--medium]=\"size() === 'medium'\"\n [class.tabs--large]=\"size() === 'large'\"\n [class.tabs--justify-start]=\"justify() === 'start'\"\n [class.tabs--justify-center]=\"justify() === 'center'\"\n [class.tabs--justify-end]=\"justify() === 'end'\"\n [class.tabs--justify-between]=\"justify() === 'between'\"\n [class.tabs--underline-text]=\"underlineStyle() === 'text'\"\n>\n <p-tabs [(value)]=\"activeValue\" (valueChange)=\"onValueChange($event)\">\n <p-tablist>\n @for (tab of items(); track tab.id) {\n <p-tab [value]=\"tab.id\" [disabled]=\"tab.disabled ?? false\">\n @if (tab.icon) {\n <span class=\"tabs__tab-icon\">{{ tab.icon }}</span>\n }\n <span class=\"tabs__tab-label\">{{ tab.label | translate }}</span>\n @if (tab.badge) {\n <span class=\"tabs__tab-badge\">{{ tab.badge }}</span>\n }\n </p-tab>\n }\n </p-tablist>\n </p-tabs>\n\n <div class=\"tabs__content\" role=\"tabpanel\" [attr.id]=\"contentPanelId()\" [attr.aria-labelledby]=\"activeTabId()\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block;width:100%}.tabs{width:100%;position:relative;direction:inherit}.tabs :host ::ng-deep .p-tabs,.tabs ::ng-deep .p-tabs{width:100%}.tabs :host ::ng-deep .p-tablist,.tabs ::ng-deep .p-tablist{background:var(--color-background);border-block-end:none;position:relative}.tabs :host ::ng-deep .p-tablist:after,.tabs ::ng-deep .p-tablist:after{content:\"\";position:absolute;inset-block-end:0;inset-inline-start:0;inline-size:100%;block-size:var(--size-3);background:var(--color-neutral-50);border-radius:var(--radius-10);z-index:9}.tabs :host ::ng-deep .p-tablist-tab-list,.tabs ::ng-deep .p-tablist-tab-list{background:transparent;border:none;position:relative;height:100%;display:flex;align-items:center}.tabs :host ::ng-deep .p-tablist-active-bar,.tabs ::ng-deep .p-tablist-active-bar{position:absolute;inset-block-end:0;background:var(--color-primary);block-size:var(--size-3);border-radius:var(--radius-10);z-index:10}[dir=rtl] .tabs :host ::ng-deep .p-tablist-active-bar,[dir=rtl] .tabs ::ng-deep .p-tablist-active-bar{inset-inline-start:unset;inset-inline-end:unset}.tabs :host ::ng-deep .p-tab,.tabs ::ng-deep .p-tab{position:relative;background:none;border:none;padding-block:var(--space-md);padding-inline:var(--space-lg);cursor:pointer;color:var(--color-text-display);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);font-family:inherit;transition:all var(--transition-base);display:flex;align-items:center;white-space:nowrap;border-radius:0}.tabs :host ::ng-deep .p-tab:hover:not(.p-disabled),.tabs ::ng-deep .p-tab:hover:not(.p-disabled){color:var(--color-primary);background:var(--color-background-hover)}.tabs :host ::ng-deep .p-tab.p-tab-active,.tabs ::ng-deep .p-tab.p-tab-active{font-weight:var(--font-weight-bold);color:var(--Text-text-default, var(--color-neutral-900));background:var(--color-background)}.tabs :host ::ng-deep .p-tab.p-disabled,.tabs ::ng-deep .p-tab.p-disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tabs--underline-text ::ng-deep .p-tablist-active-bar{display:none}.tabs--underline-text ::ng-deep .p-tablist:after{display:none}.tabs--underline-text .tabs__tab-label{position:relative}.tabs--underline-text .tabs__tab-label:after{content:\"\";position:absolute;inset-block-end:calc((var(--space-md) + var(--size-3)) * -1);inset-inline-start:0;inline-size:0;block-size:var(--size-3);background:var(--color-primary);border-radius:0;z-index:10;transition:inline-size var(--transition-base, .2s ease)}.tabs--underline-text ::ng-deep .p-tab-active .tabs__tab-label:after{inline-size:100%}.tabs--underline-text.tabs --small .tabs__tab-label:after{inset-block-end:calc((var(--space-sm) + var(--size-3)) * -1)}.tabs--underline-text.tabs --large .tabs__tab-label:after{inset-block-end:calc((var(--space-lg) + var(--size-3)) * -1)}.tabs--justify-start ::ng-deep .p-tablist-tab-list{justify-content:flex-start}.tabs--justify-center ::ng-deep .p-tablist-tab-list{justify-content:center}.tabs--justify-end ::ng-deep .p-tablist-tab-list{justify-content:flex-end}.tabs--justify-between ::ng-deep .p-tablist-tab-list{justify-content:space-between}.tabs--small ::ng-deep .p-tab{padding-block:var(--space-sm);padding-inline:var(--space-md);font-size:var(--font-size-sm)}.tabs--large ::ng-deep .p-tab{padding-block:var(--space-lg);padding-inline:var(--space-xl);font-size:var(--font-size-lg)}.tabs--pills ::ng-deep .p-tablist-tab-list{border:none}.tabs--pills ::ng-deep .p-tab{flex:1;justify-content:flex-start}.tabs--pills ::ng-deep .p-tab.p-tab-active{color:var(--color-primary)}.tabs--underline ::ng-deep .p-tablist{border:none}.tabs--underline ::ng-deep .p-tablist:after{display:none}.tabs--underline ::ng-deep .p-tab.p-tab-active{border-block-end-color:var(--color-primary)}.tabs__tab-icon{font-size:var(--font-size-lg)}.tabs__tab-label{flex:1}.tabs__tab-badge{background:var(--color-primary);color:var(--color-primary-contrast);border-radius:var(--radius-full);padding-block:var(--space-xs);padding-inline:var(--space-sm);font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);min-width:var(--size-20);text-align:center}.tabs__content{margin-block:var(--space-lg);margin-inline:0}\n"] }]
9882
10020
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], activeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeId", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], justify: [{ type: i0.Input, args: [{ isSignal: true, alias: "justify", required: false }] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }], underlineStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "underlineStyle", required: false }] }], primeTabs: [{ type: i0.ViewChild, args: [i0.forwardRef(() => Tabs$1), { isSignal: true }] }] } });
9883
10021
 
10022
+ /** Wraps PrimeNG `p-breadcrumb` over `items`, prepending a home entry unless `showHomeIcon` is false; re-translates labels on language change and sets its own `dir` from the `rtl` input (default: current lang is Arabic). */
9884
10023
  class Breadcrumb {
9885
10024
  destroyRef = inject(DestroyRef);
9886
10025
  translateService = inject(TranslateService);
@@ -9976,6 +10115,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9976
10115
  }, template: "<p-breadcrumb [model]=\"menuItems()\" [home]=\"homeMenuItem()\" styleClass=\"breadcrumb\" (onItemClick)=\"onBreadcrumbItemClick($event)\">\n @if (separatorItem()) {\n <ng-template #separator>\n <span class=\"breadcrumb-separator\">{{ separatorItem() }}</span>\n </ng-template>\n }\n</p-breadcrumb>\n", styles: [":host{display:block}.breadcrumb{background:transparent;border:none;padding:0}::ng-deep .breadcrumb .p-breadcrumb-list{align-items:center;gap:var(--space-xs)}::ng-deep .breadcrumb .p-breadcrumb-item-label{color:var(--color-breadcrumb)}::ng-deep .breadcrumb .p-breadcrumb-item-link{font-weight:var(--font-weight-regular);font-size:var(--font-size-xs)}::ng-deep .breadcrumb .p-breadcrumb-item:hover .p-breadcrumb-link{color:var(--primary-color)}::ng-deep .breadcrumb .p-breadcrumb-item.p-disabled{opacity:.6;pointer-events:none}::ng-deep .breadcrumb .p-breadcrumb-item:last-child .p-breadcrumb-link{font-weight:var(--font-weight-semibold);color:var(--text-color);cursor:default}::ng-deep .breadcrumb .p-breadcrumb-item:last-child .p-breadcrumb-link:hover{color:var(--text-color)}::ng-deep .breadcrumb .p-breadcrumb-link{color:var(--color-breadcrumb);text-decoration:none;transition:color .2s ease;display:flex;align-items:center;cursor:pointer;border-radius:var(--radius-md)}::ng-deep .breadcrumb .p-breadcrumb-link:focus-visible{outline:2px solid var(--color-brand-primary-600, var(--color-brand-primary-600));outline-offset:2px}::ng-deep .breadcrumb .p-breadcrumb-link .p-breadcrumb-icon{font-size:var(--font-size-md)}::ng-deep .breadcrumb .p-breadcrumb-separator{margin:var(--space-1);color:var(--color-breadcrumb-separator)}::ng-deep .breadcrumb .breadcrumb-separator{margin:var(--space-1);color:var(--color-breadcrumb-separator);font-size:var(--font-size-2xs)}[dir=rtl] .p-breadcrumb-separator{transform:scaleX(-1)}[dir=rtl] .p-breadcrumb-list{direction:rtl}:host ::ng-deep .p-breadcrumb.p-breadcrumb{background-color:transparent;background:transparent;padding:var(--space-0);gap:var(--space-0);display:inline-flex}:host ::ng-deep .p-breadcrumb .p-breadcrumb-item-link{gap:var(--space-0)}:host ::ng-deep .p-breadcrumb-list .p-breadcrumb-item-link.p-breadcrumb-item-link{cursor:pointer}:host ::ng-deep .p-breadcrumb-list .p-breadcrumb-item-link.p-breadcrumb-item-link .p-menuitem-text{font-weight:700;color:var(--color-neutral-900)}\n"] }]
9977
10116
  }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], home: [{ type: i0.Input, args: [{ isSignal: true, alias: "home", required: false }] }], showHomeIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHomeIcon", required: false }] }], rtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "rtl", required: false }] }], separatorItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorItem", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
9978
10117
 
10118
+ /** Input-free card shell: projects its content into a styled `.card` container (host class `sce-card`). */
9979
10119
  class Card {
9980
10120
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: Card, deps: [], target: i0.ɵɵFactoryTarget.Component });
9981
10121
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.17", type: Card, isStandalone: true, selector: "sce-card", host: { classAttribute: "sce-card" }, ngImport: i0, template: "<div class=\"card\">\n <ng-content />\n</div>\n", styles: [":host{display:block}.card{padding:var(--space-lg);background:var(--color-white);border-radius:var(--radius-lg)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -9985,6 +10125,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9985
10125
  args: [{ host: { class: 'sce-card' }, selector: 'sce-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"card\">\n <ng-content />\n</div>\n", styles: [":host{display:block}.card{padding:var(--space-lg);background:var(--color-white);border-radius:var(--radius-lg)}\n"] }]
9986
10126
  }] });
9987
10127
 
10128
+ /** Renders `steps` as a horizontal/vertical step indicator in a `steps`, `progress` or `pills` `variant`; every step click emits `stepChange`, so `linear` currently gates nothing and the host must decide whether to honour it. */
9988
10129
  class Stepper {
9989
10130
  steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
9990
10131
  variant = input('steps', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -10026,6 +10167,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10026
10167
  }, template: "@if (variant() === 'pills') {\n <div\n class=\"stepper-pills\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"progressPercentage()\"\n [attr.aria-label]=\"progressPercentage() + '%'\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n @for (step of steps(); track step.id) {\n <div\n class=\"stepper-pills__segment\"\n [style.width.px]=\"width()\"\n [class.stepper-pills__segment--active]=\"step.state === 'active'\"\n [class.stepper-pills__segment--completed]=\"step.state === 'completed'\"\n [class.stepper-pills__segment--upcoming]=\"step.state === 'upcoming'\"\n ></div>\n }\n </div>\n} @else if (variant() === 'progress') {\n <div\n class=\"stepper-progress\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"progressPercentage()\"\n [attr.aria-label]=\"progressPercentage() + '%'\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <div class=\"stepper-progress__fill\" [style.width.%]=\"progressPercentage()\"></div>\n </div>\n} @else {\n <nav\n class=\"stepper\"\n [class.stepper--vertical]=\"orientation() === 'vertical'\"\n role=\"navigation\"\n [attr.aria-label]=\"'ARIA.PROGRESS' | translate\"\n >\n <ol class=\"stepper__list\">\n @for (step of steps(); track step.id; let idx = $index; let last = $last) {\n <li\n class=\"stepper__item\"\n [class.stepper__item--completed]=\"step.state === 'completed'\"\n [class.stepper__item--active]=\"step.state === 'active'\"\n [class.stepper__item--upcoming]=\"step.state === 'upcoming'\"\n [class.stepper__item--disabled]=\"step.state === 'disabled'\"\n >\n <button\n class=\"stepper__circle\"\n type=\"button\"\n [disabled]=\"step.state === 'disabled' || step.state === 'active' || (linear() && step.state === 'upcoming')\"\n [attr.aria-current]=\"step.state === 'active' ? 'step' : null\"\n [attr.aria-label]=\"step.label ? (step.label | translate) : idx + 1\"\n (click)=\"onStepClick(step)\"\n >\n @if (step.state === 'completed') {\n <i class=\"stepper__check pi pi-check\"></i>\n } @else {\n <span class=\"stepper__number\">{{ idx + 1 }}</span>\n }\n </button>\n\n @if (step.label) {\n <div class=\"stepper__container\">\n <span class=\"stepper__label\">{{ step.label | translate }}</span>\n @if (step.subLabel) {\n <span class=\"stepper__sub-label\">{{ step.subLabel | translate }}</span>\n }\n </div>\n }\n\n @if (!last) {\n <div class=\"stepper__connector\" [class.stepper__connector--completed]=\"step.state === 'completed'\"></div>\n }\n </li>\n }\n </ol>\n </nav>\n}\n", styles: [":host{display:block;width:100%}.stepper-pills{display:flex;gap:var(--space-xs);width:100%}.stepper-pills__segment{flex-shrink:0;height:var(--size-8);border-radius:var(--rail-radius);background:var(--Background-background-neutral-200, var(--color-neutral-200));transition:background var(--transition-medium)}.stepper-pills__segment--active,.stepper-pills__segment--completed{background:var(--color-primary)}.stepper-pills__segment--upcoming{background:var(--Background-background-neutral-200, var(--color-neutral-200))}.stepper-progress{width:var(--space-100, var(--size-100));height:var(--size-8);background:var(--color-progress-bar-bg);border-radius:var(--rail-radius);overflow:hidden}.stepper-progress__fill{height:100%;border-radius:var(--rail-radius);background:var(--color-primary);transition:width var(--transition-medium)}.stepper__list{display:flex;align-items:center;list-style:none;padding:0;margin:0}.stepper__item{display:flex;align-items:center;flex:1;position:relative}.stepper__item:last-child{flex:0 0 auto}.stepper__item--completed .stepper__circle{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-white);cursor:pointer}.stepper__item--active .stepper__circle{border-color:var(--color-primary);color:var(--color-primary);background:var(--Background-background-primary-25);cursor:default}.stepper__item--upcoming .stepper__circle{border-color:var(--border-neutral-primary);color:var(--color-text-muted);background:var(--color-white)}.stepper__item--disabled .stepper__circle{opacity:.4;cursor:not-allowed}.stepper__item--completed .stepper__label{color:var(--color-primary)}.stepper__item--active .stepper__label{color:var(--Form-field-text-label);font-weight:var(--font-weight-semibold)}.stepper__item--upcoming .stepper__label,.stepper__item--disabled .stepper__label{color:var(--color-text-muted)}.stepper__circle{width:var(--size-32);height:var(--size-32);border-radius:var(--radius-full);border:2px solid;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:var(--font-size-sm, var(--font-size-md));font-weight:var(--font-weight-semibold);transition:all var(--transition-base, .2s ease);background:none;padding:0}.stepper__circle:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.stepper__circle:disabled{pointer-events:none}.stepper__check{font-size:var(--font-size-lg)}.stepper__container{display:contents}.stepper__label{display:block;font-size:var(--font-size-xs);white-space:nowrap;position:absolute;top:100%;margin-block-start:var(--space-xs);inset-inline-start:0;width:var(--size-32);text-align:center}.stepper__sub-label{display:none}.stepper__connector{flex:1;height:var(--space-2);background:var(--border-neutral-primary);margin-inline-start:var(--space-sm);margin-inline-end:var(--space-sm);transition:background var(--transition-base)}.stepper__connector--completed{background:var(--color-primary)}.stepper--vertical .stepper__list{flex-direction:column;align-items:stretch}.stepper--vertical .stepper__item{display:grid;grid-template-columns:var(--size-32) 1fr;grid-template-rows:auto 1fr;column-gap:var(--space-md);flex:unset}.stepper--vertical .stepper__item:last-child{grid-template-rows:auto}.stepper--vertical .stepper__circle{grid-column:1;grid-row:1}.stepper--vertical .stepper__container{display:flex;flex-direction:column;justify-content:center;gap:var(--space-2xs);grid-column:2;grid-row:1;align-self:center}.stepper--vertical .stepper__label{position:static;top:auto;inset-inline-start:auto;width:auto;text-align:start;white-space:normal;font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--Form-field-text-label);margin-block-start:0}.stepper--vertical .stepper__sub-label{display:block;font-size:var(--font-size-xs);color:var(--color-text-muted)}.stepper--vertical .stepper__connector{grid-column:1;grid-row:2;width:var(--space-2);height:auto;min-height:var(--sce-stepper-step-gap, var(--space-96));flex:unset;margin-inline-start:auto;margin-inline-end:auto;margin-block:var(--space-xs)}.stepper--vertical .stepper__item--completed .stepper__label{color:var(--color-primary)}.stepper--vertical .stepper__item--active .stepper__label{color:var(--Form-field-text-label)}.stepper--vertical .stepper__item--upcoming .stepper__label,.stepper--vertical .stepper__item--disabled .stepper__label{color:var(--color-text-muted)}\n"] }]
10027
10168
  }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], linear: [{ type: i0.Input, args: [{ isSignal: true, alias: "linear", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], stepGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "stepGap", required: false }] }], stepChange: [{ type: i0.Output, args: ["stepChange"] }] } });
10028
10169
 
10170
+ /** Page title with an optional breadcrumb trail (`breadcrumbItems`, on by default); `breadcrumbFirst` moves the trail above the title and `actionLayout` switches to a split layout with a projected actions slot. */
10029
10171
  class ScePageHeaderComponent {
10030
10172
  titleKey = input('', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
10031
10173
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
@@ -10089,6 +10231,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10089
10231
  args: [{ host: { class: 'sce-page-error' }, selector: 'sce-page-error', standalone: true, imports: [TranslatePipe, SceEmptyStateComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sce-page-error\">\n <sce-empty-state [titleKey]=\"titleKey()\" [subtitleKey]=\"subtitleKey()\" [icon]=\"icon()\" tone=\"error\">\n <button type=\"button\" class=\"sce-page-error__retry-btn\" (click)=\"retry.emit()\">\n {{ retryLabelKey() | translate }}\n </button>\n </sce-empty-state>\n</div>\n", styles: [":host{display:block}.sce-page-error{margin-block-start:var(--space-24);padding:var(--space-12);background:var(--color-white);border:1px solid var(--color-neutral);border-radius:var(--radius-lg)}.sce-page-error__retry-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-2) var(--space-24);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-primary);background:transparent;border:1px solid var(--color-primary);border-radius:var(--radius-lg);cursor:pointer;transition:background-color .15s ease,color .15s ease;white-space:nowrap}.sce-page-error__retry-btn:hover{background:var(--color-primary);color:var(--color-white)}.sce-page-error__retry-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}\n"] }]
10090
10232
  }], propDecorators: { titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: true }] }], subtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleKey", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], retryLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "retryLabelKey", required: false }] }], retry: [{ type: i0.Output, args: ["retry"] }] } });
10091
10233
 
10234
+ /** Page layout for authentication screens: a logo, title and subtitle header (each settable as literal text or a translation key) above the projected form, with an optional decorative side panel and footer. */
10092
10235
  class SceAuthLayoutComponent {
10093
10236
  /** Logo image URL for the auth header */
10094
10237
  logoSrc = input('', ...(ngDevMode ? [{ debugName: "logoSrc" }] : /* istanbul ignore next */ []));
@@ -10163,6 +10306,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10163
10306
  args: [{ host: { class: 'sce-status-page' }, selector: 'sce-status-page', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"sce-status-page-layout\">\n <header class=\"sce-status-page-layout__header\">\n <a class=\"sce-status-page-layout__brand\" href=\"/\" [attr.aria-label]=\"'ARIA.HOME' | translate\">\n <!-- `logo.png` is white ink (for dark surfaces); `logo_dark.png` is dark ink (for light ones). -->\n <img class=\"sce-status-page-layout__logo sce-status-page-layout__logo--on-light\" src=\"/logo_dark.png\" alt=\"\" />\n <img class=\"sce-status-page-layout__logo sce-status-page-layout__logo--on-dark\" src=\"/logo.png\" alt=\"\" />\n </a>\n </header>\n\n <main class=\"sce-status-page-layout__main\">\n <div class=\"sce-status-page-layout__card\">\n <section class=\"sce-status-page\" [class]=\"variantClass()\" [attr.aria-labelledby]=\"titleId\">\n <span class=\"sce-status-page__accent\" aria-hidden=\"true\"></span>\n\n @if (code()) {\n <span class=\"sce-status-page__code-badge sce-status-page__stagger-1\">{{ code() }}</span>\n }\n\n @if (imageSrc()) {\n <div class=\"sce-status-page__illustration sce-status-page__stagger-2\">\n <img\n class=\"sce-status-page__image\"\n [src]=\"imageSrc()\"\n [alt]=\"imageAlt()\"\n [attr.aria-hidden]=\"imageDecorative() ? 'true' : null\"\n />\n </div>\n } @else {\n <div class=\"sce-status-page__icon-wrapper sce-status-page__stagger-2\" [class]=\"'sce-status-page__icon-wrapper--' + iconVariant()\">\n <span class=\"sce-status-page__icon-ring\" aria-hidden=\"true\"></span>\n <svg\n class=\"sce-status-page__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n @switch (iconVariant()) {\n @case ('error') {\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 7.5v5\" />\n <path d=\"M12 16.25h.01\" />\n }\n @case ('warning') {\n <path d=\"M10.3 3.9 2.6 17a2 2 0 0 0 1.7 3h15.4a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z\" />\n <path d=\"M12 9v4\" />\n <path d=\"M12 17h.01\" />\n }\n @case ('info') {\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M12 16v-4.5\" />\n <path d=\"M12 8h.01\" />\n }\n @case ('success') {\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"m8.5 12.2 2.4 2.4 4.6-5\" />\n }\n @default {\n <path d=\"M3.5 7.5 12 3l8.5 4.5v9L12 21l-8.5-4.5Z\" />\n <path d=\"M3.5 7.5 12 12l8.5-4.5\" />\n <path d=\"M12 12v9\" />\n }\n }\n </svg>\n </div>\n }\n\n <div class=\"sce-status-page__copy sce-status-page__stagger-3\">\n <h1 [id]=\"titleId\" class=\"sce-status-page__title\">\n {{ titleKey() | translate }}\n </h1>\n\n @if (subtitleKey()) {\n <p class=\"sce-status-page__subtitle\">\n {{ subtitleKey() | translate }}\n </p>\n }\n </div>\n\n <span class=\"sce-status-page__divider sce-status-page__stagger-4\" aria-hidden=\"true\"></span>\n\n <div class=\"sce-status-page__actions sce-status-page__stagger-5\">\n <ng-content />\n </div>\n </section>\n </div>\n </main>\n\n <footer class=\"sce-status-page-layout__footer\">\n <img src=\"/logo_dark.png\" alt=\"\" class=\"sce-status-page-layout__footer-logo sce-status-page-layout__logo--on-light\" />\n <img src=\"/logo.png\" alt=\"\" class=\"sce-status-page-layout__footer-logo sce-status-page-layout__logo--on-dark\" />\n </footer>\n</div>\n", styles: ["sce-status-page{display:block;min-height:var(--sce-status-page-min-block-size, 100dvb)}.sce-status-page-layout{--sce-status-card-max-width: 34rem;--sce-status-icon-size: var(--space-96);--sce-status-icon-glyph-size: var(--space-40);--sce-status-glow-size: var(--space-160);--sce-status-decor-size: clamp(18rem, 40vi, 36rem);width:100%;position:relative;display:flex;flex-direction:column;align-items:center;min-height:var(--sce-status-page-min-block-size, 100dvb);overflow:hidden;background:radial-gradient(ellipse at 30% 20%,rgba(39,177,167,.06) 0%,transparent 60%),radial-gradient(ellipse at 70% 80%,rgba(0,52,73,.05) 0%,transparent 60%),var(--surface-section-soft)}.sce-status-page-layout:before,.sce-status-page-layout:after{content:\"\";position:absolute;inset:0;z-index:0;background-image:url(/images/h1_shape%201.png);background-repeat:no-repeat;background-size:var(--sce-status-decor-size);opacity:.07}.sce-status-page-layout:before{background-position:right bottom}.sce-status-page-layout:after{background-position:left bottom;transform:scaleX(-1)}.sce-status-page-layout__header{position:absolute;top:0;inset-inline-start:0;inset-inline-end:0;display:flex;justify-content:flex-start;padding:var(--space-32);z-index:3}.sce-status-page-layout__brand{display:inline-flex;border-radius:var(--radius-md)}.sce-status-page-layout__brand:focus-visible{outline:var(--border-width-2) solid var(--color-brand-secondary-500);outline-offset:var(--space-4)}.sce-status-page-layout__logo{height:var(--space-36);width:auto;object-fit:contain;transition:opacity var(--transition-base)}.sce-status-page-layout__brand:hover .sce-status-page-layout__logo{opacity:.75}.sce-status-page-layout__logo--on-dark{display:none}.sce-status-page-layout__main{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;width:100%;padding:var(--space-100) var(--space-24) var(--space-40)}.sce-status-page-layout__card{width:100%;max-width:var(--sce-status-card-max-width);animation:sce-status-card-enter var(--motion-duration-slow) var(--motion-ease-emphasized) forwards}.sce-status-page-layout__footer{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;padding:var(--space-16) var(--space-24);opacity:.35;transition:opacity var(--transition-base)}.sce-status-page-layout__footer:hover{opacity:.55}.sce-status-page-layout__footer-logo{height:var(--space-20);width:auto;object-fit:contain}.sce-status-page{position:relative;display:flex;flex-direction:column;align-items:center;gap:0;text-align:center;padding:0 clamp(var(--space-24),4vi,var(--space-40)) clamp(2rem,5vi,var(--space-40));background:var(--surface-glass-light);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:var(--border-width-1) solid var(--border-chip-light);border-radius:var(--radius-brand-lg);box-shadow:var(--shadow-card-lg);overflow:hidden}.sce-status-page__accent{display:block;width:100%;height:var(--space-4);margin-block-end:clamp(var(--space-24),4vi,2rem);background:linear-gradient(90deg,var(--color-brand-primary-800) 0%,var(--color-brand-secondary-500) 100%);flex-shrink:0;position:relative;overflow:hidden}.sce-status-page__accent:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.4) 50%,transparent 100%);transform:translate(-100%);animation:sce-accent-shimmer 3s ease-in-out 1s infinite}.sce-status-page__code-badge{display:inline-flex;align-items:center;justify-content:center;min-width:var(--space-64);padding:var(--space-8) var(--space-20);background:var(--color-brand-primary-800);border-radius:var(--radius-full);font-family:ui-monospace,SF Mono,monospace;font-size:var(--font-size-sm);font-weight:var(--font-weight-bold);font-variant-numeric:tabular-nums;color:var(--color-white);letter-spacing:.12em;flex-shrink:0;margin-block-end:var(--space-16);box-shadow:var(--shadow-sm)}.sce-status-page__illustration{position:relative;display:flex;align-items:center;justify-content:center;margin-block-end:var(--space-24)}.sce-status-page__illustration:before{content:\"\";position:absolute;width:var(--sce-status-glow-size);height:var(--sce-status-glow-size);border-radius:var(--radius-full);background:radial-gradient(circle,var(--color-brand-secondary-100) 0%,transparent 70%);pointer-events:none}.sce-status-page__image{position:relative;width:auto;height:auto;max-width:min(var(--size-200),60%);max-height:var(--size-180);object-fit:contain;flex-shrink:0;animation:sce-illustration-float 4s ease-in-out .75s infinite}.sce-status-page__icon-wrapper{position:relative;display:flex;align-items:center;justify-content:center;width:var(--sce-status-icon-size);height:var(--sce-status-icon-size);border-radius:var(--radius-full);flex-shrink:0;margin-block-end:var(--space-24)}.sce-status-page__icon-wrapper--error{background:var(--color-red-100);color:var(--color-red-500)}.sce-status-page__icon-wrapper--warning{background:var(--color-yellow-100);color:var(--color-yellow-600)}.sce-status-page__icon-wrapper--info{background:var(--color-blue-100);color:var(--color-blue-500)}.sce-status-page__icon-wrapper--success{background:var(--color-brand-secondary-100);color:var(--color-brand-secondary-600)}.sce-status-page__icon-wrapper--neutral{background:var(--color-neutral-100);color:var(--color-text-muted)}.sce-status-page__icon-ring{position:absolute;inset:0;border-radius:var(--radius-full);border:var(--border-width-1) solid currentColor;opacity:0;animation:sce-icon-ring-pulse 2.8s var(--motion-ease-out) infinite;pointer-events:none}.sce-status-page__icon{position:relative;width:var(--sce-status-icon-glyph-size);height:var(--sce-status-icon-glyph-size);animation:sce-illustration-float 4s ease-in-out .75s infinite}.sce-status-page__copy{display:flex;flex-direction:column;align-items:center;gap:var(--space-8);margin-block-end:var(--space-24)}.sce-status-page__title{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:clamp(var(--space-20),3vi,1.625rem);font-weight:var(--font-weight-bold);color:var(--text-text-primary-900);margin:0;line-height:1.4;text-wrap:balance;overflow-wrap:break-word}.sce-status-page__subtitle{font-family:var(--font-family-arabic-primary),var(--font-geist-sans),Arial,sans-serif;font-size:var(--font-size-base);font-weight:var(--font-weight-regular);color:var(--text-text-secondary-700);margin:0;line-height:1.75;text-wrap:pretty;overflow-wrap:break-word;max-width:42ch}.sce-status-page__divider{display:block;width:100%;height:var(--space-1);background:linear-gradient(to right,transparent 0%,var(--border-subtle) 20%,var(--border-subtle) 80%,transparent 100%);margin-block-end:var(--space-24);flex-shrink:0}.sce-status-page__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--space-12);width:100%}.sce-status-page__stagger-1,.sce-status-page__stagger-2,.sce-status-page__stagger-3,.sce-status-page__stagger-4,.sce-status-page__stagger-5{opacity:0;animation:sce-stagger-in var(--motion-duration-slow) var(--motion-ease-emphasized) forwards}.sce-status-page__stagger-1{animation-delay:.15s}.sce-status-page__stagger-2{animation-delay:.25s}.sce-status-page__stagger-3{animation-delay:.4s}.sce-status-page__stagger-4{animation-delay:.55s}.sce-status-page__stagger-5{animation-delay:.65s}.sce-status-page--error .sce-status-page__illustration:before{background:radial-gradient(circle,var(--color-red-100) 0%,transparent 70%)}.sce-status-page--warning .sce-status-page__illustration:before{background:radial-gradient(circle,var(--color-yellow-100) 0%,transparent 70%)}.sce-status-page--info .sce-status-page__illustration:before{background:radial-gradient(circle,var(--color-blue-100) 0%,transparent 70%)}.sce-status-page--success .sce-status-page__illustration:before{background:radial-gradient(circle,var(--color-brand-secondary-100) 0%,transparent 70%)}.sce-status-page--error .sce-status-page__accent{background:linear-gradient(90deg,var(--color-red-500) 0%,var(--color-red-300) 100%)}.sce-status-page--error .sce-status-page__code-badge{background:var(--color-red-500)}.sce-status-page--warning .sce-status-page__accent{background:linear-gradient(90deg,var(--color-yellow-500) 0%,var(--color-yellow-300) 100%)}.sce-status-page--warning .sce-status-page__code-badge{background:var(--color-yellow-600)}.sce-status-page--info .sce-status-page__accent{background:linear-gradient(90deg,var(--color-blue-500) 0%,var(--color-blue-300) 100%)}.sce-status-page--info .sce-status-page__code-badge{background:var(--color-blue-500)}.sce-status-page--success .sce-status-page__accent{background:linear-gradient(90deg,var(--color-brand-secondary-600) 0%,var(--color-brand-secondary-300) 100%)}.sce-status-page--success .sce-status-page__code-badge{background:var(--color-brand-secondary-600)}.sce-status-page--neutral .sce-status-page__accent{background:linear-gradient(90deg,var(--color-brand-primary-800) 0%,var(--color-brand-secondary-500) 100%)}@keyframes sce-status-card-enter{0%{opacity:0;transform:translateY(var(--motion-distance-lg)) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes sce-stagger-in{0%{opacity:0;transform:translateY(var(--motion-distance-sm))}to{opacity:1;transform:translateY(0)}}@keyframes sce-illustration-float{0%,to{transform:translateY(0)}50%{transform:translateY(-6px)}}@keyframes sce-icon-ring-pulse{0%{transform:scale(1);opacity:.5}70%,to{transform:scale(1.35);opacity:0}}@keyframes sce-accent-shimmer{0%{transform:translate(-100%)}to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.sce-status-page-layout__card,.sce-status-page__stagger-1,.sce-status-page__stagger-2,.sce-status-page__stagger-3,.sce-status-page__stagger-4,.sce-status-page__stagger-5{animation:none;opacity:1}.sce-status-page__image,.sce-status-page__icon,.sce-status-page__icon-ring,.sce-status-page__accent:after{animation:none}}html[data-theme=dark] .sce-status-page-layout{background:radial-gradient(ellipse at 30% 20%,rgba(39,177,167,.08) 0%,transparent 60%),radial-gradient(ellipse at 70% 80%,rgba(0,52,73,.1) 0%,transparent 60%),var(--color-bg)}html[data-theme=dark] .sce-status-page-layout:before,html[data-theme=dark] .sce-status-page-layout:after{opacity:.04}html[data-theme=dark] .sce-status-page-layout__logo{opacity:.9}.sce-status-page-layout__brand:hover html[data-theme=dark] .sce-status-page-layout__logo{opacity:.7}html[data-theme=dark] .sce-status-page-layout__logo--on-light{display:none}html[data-theme=dark] .sce-status-page-layout__logo--on-dark{display:block}html[data-theme=dark] .sce-status-page{background:var(--surface-card-frosted);border-color:var(--border-on-brand-faint);box-shadow:var(--shadow-panel-md)}html[data-theme=dark] .sce-status-page__title{color:var(--text-text-primary-900)}html[data-theme=dark] .sce-status-page__subtitle{color:var(--text-text-secondary-700)}html[data-theme=dark] .sce-status-page__divider{background:linear-gradient(to right,transparent 0%,var(--border-on-brand-faint) 20%,var(--border-on-brand-faint) 80%,transparent 100%)}html[data-theme=dark] .sce-status-page__icon-wrapper--error{background:#ef444426}html[data-theme=dark] .sce-status-page__icon-wrapper--warning{background:#f59e0b26}html[data-theme=dark] .sce-status-page__icon-wrapper--info{background:#3b82f626}html[data-theme=dark] .sce-status-page__icon-wrapper--success{background:#27b1a726}html[data-theme=dark] .sce-status-page__icon-wrapper--neutral{background:var(--surface-on-brand-subtle)}@media(max-width:640px){.sce-status-page-layout{--sce-status-icon-size: var(--space-72);--sce-status-icon-glyph-size: var(--space-32);--sce-status-glow-size: var(--space-96);--sce-status-decor-size: 14rem}.sce-status-page-layout__header{padding:var(--space-16)}.sce-status-page-layout__logo{height:var(--space-28)}.sce-status-page-layout__main{padding:var(--space-80) var(--space-16) var(--space-24)}.sce-status-page-layout__footer-logo{height:var(--space-16)}.sce-status-page-layout:before,.sce-status-page-layout:after{opacity:.04}.sce-status-page{padding:0 var(--space-20) var(--space-24);border-radius:var(--radius-brand-sm)}.sce-status-page__accent{margin-block-end:var(--space-20)}.sce-status-page__image{max-width:var(--size-140);max-height:var(--size-140)}.sce-status-page__title{font-size:var(--font-size-xl)}.sce-status-page__subtitle{font-size:var(--font-size-md)}}@media print{.sce-status-page-layout{background:var(--color-base-white);min-height:auto}.sce-status-page-layout:before,.sce-status-page-layout:after{display:none}.sce-status-page-layout__header{position:static;padding:var(--space-16)}.sce-status-page-layout__footer{display:none}.sce-status-page{background:var(--color-base-white);-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none;border:var(--border-width-1) solid var(--border-neutral-primary)}.sce-status-page__accent:after,.sce-status-page__image,.sce-status-page__icon,.sce-status-page__icon-ring{animation:none}.sce-status-page__stagger-1,.sce-status-page__stagger-2,.sce-status-page__stagger-3,.sce-status-page__stagger-4,.sce-status-page__stagger-5,.sce-status-page-layout__card{animation:none;opacity:1}}\n"] }]
10164
10307
  }], propDecorators: { iconVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconVariant", required: false }] }], imageSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageSrc", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }], code: [{ type: i0.Input, args: [{ isSignal: true, alias: "code", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: true }] }], subtitleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleKey", required: false }] }] } });
10165
10308
 
10309
+ /** Searchable single- or multi-select list (`multiSelect` defaults to true) that filters `items` in-place and emits the full `selectedValues` array; rows can be overridden with a projected `ng-template`, and `loading` swaps in skeletons. */
10166
10310
  class SceSelectableListWithSearchComponent {
10167
10311
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
10168
10312
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
@@ -10228,6 +10372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10228
10372
  }, template: "<div\n [class.sce-selectable-list--primary]=\"variant() === 'primary'\"\n [class.sce-selectable-list--black]=\"variant() === 'black'\"\n class=\"sce-selectable-list\"\n>\n @if (title()) {\n <h3 class=\"sce-selectable-list__title\">{{ title() }}</h3>\n }\n\n <div class=\"sce-selectable-list__search\">\n <span class=\"sce-selectable-list__search-icon\" aria-hidden=\"true\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\"></circle>\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"></line>\n </svg>\n </span>\n <input\n type=\"text\"\n class=\"sce-selectable-list__search-input\"\n [placeholder]=\"searchPlaceholder() || ('COMMON.SEARCH' | translate)\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n />\n </div>\n\n @if (loading()) {\n <ul class=\"sce-selectable-list__items\" role=\"list\" aria-busy=\"true\">\n @for (i of [1, 2, 3, 4, 5]; track i) {\n <li class=\"sce-selectable-list__item\">\n <sce-skeleton variant=\"rectangular\" height=\"64px\" borderRadius=\"12px\" />\n </li>\n }\n </ul>\n } @else {\n <ul class=\"sce-selectable-list__items\" role=\"list\">\n @for (view of itemViews(); track view.item.value; let i = $index) {\n <li class=\"sce-selectable-list__item\">\n <button\n type=\"button\"\n class=\"sce-selectable-list__item-btn\"\n [class.sce-selectable-list__item-btn--selected]=\"view.selected\"\n [class.sce-selectable-list__item-btn--disabled]=\"view.item.disabled\"\n [disabled]=\"view.item.disabled\"\n (click)=\"toggleItem(view.item)\"\n >\n @if (!rtl()) {\n <span class=\"sce-selectable-list__checkbox\" [class.sce-selectable-list__checkbox--checked]=\"view.selected\">\n @if (view.selected) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </span>\n }\n <span class=\"sce-selectable-list__item-content\">\n @if (!itemTemplate()) {\n <span class=\"sce-selectable-list__item-label\">{{ view.item.label }}</span>\n @if (view.item.subLabel) {\n <span class=\"sce-selectable-list__item-sublabel\">{{ view.item.subLabel }}</span>\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"itemTemplate()!\" [ngTemplateOutletContext]=\"{ $implicit: view.item, index: i }\" />\n }\n </span>\n @if (rtl()) {\n <span class=\"sce-selectable-list__checkbox\" [class.sce-selectable-list__checkbox--checked]=\"view.selected\">\n @if (view.selected) {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </span>\n }\n </button>\n </li>\n } @empty {\n <li class=\"sce-selectable-list__empty\">{{ 'COMMON.NO_RESULTS' | translate }}</li>\n }\n </ul>\n }\n</div>\n", styles: [":host{display:block}.sce-selectable-list{display:flex;flex-direction:column;gap:var(--space-lg);min-width:var(--size-280)}.sce-selectable-list--primary{--selection-color: var(--color-primary);--selection-background-color: var(--color-accent-success-overlay-20)}.sce-selectable-list--black{--selection-color: var(--background-neutral-950);--selection-background-color: var(--color-neutral-50)}.sce-selectable-list__title{margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--color-text-display)}.sce-selectable-list__search{position:relative;display:flex;align-items:center}.sce-selectable-list__search-icon{position:absolute;inset-inline-start:var(--space-md);display:flex;align-items:center;justify-content:center;color:var(--color-text-muted-gray);pointer-events:none}.sce-selectable-list__search-input{width:100%;height:var(--size-44);padding-inline-start:calc(var(--space-md) + var(--space-18) + var(--space-xs));padding-inline-end:var(--space-md);font-size:var(--font-size-md);color:var(--color-text-display);background:var(--color-neutral-50);border:1px solid var(--color-border-light);border-radius:var(--radius-lg);font-family:inherit;transition:border-color .15s,box-shadow .15s}.sce-selectable-list__search-input::placeholder{color:var(--Form-field-text-placeholder, var(--color-neutral-500));font-weight:500}.sce-selectable-list__search-input:focus{outline:none;border-color:var(--selection-color);box-shadow:0 0 0 2px var(--selection-background-color)}.sce-selectable-list__items{display:flex;flex-direction:column;gap:var(--space-sm);margin:0;padding:0;list-style:none;overflow-y:auto}.sce-selectable-list__item{margin:0;padding:0;list-style:none}.sce-selectable-list__item-btn{display:flex;align-items:center;gap:var(--space-md);width:100%;padding:var(--space-md) var(--space-lg);text-align:start;background:var(--color-neutral-50);border:1px solid transparent;border-radius:var(--radius-lg);height:var(--space-64);cursor:pointer;font-family:inherit;transition:background-color .15s,border-color .15s}.sce-selectable-list__item-btn:hover:not(:disabled){background:var(--color-neutral-100);border-color:var(--color-border-light)}.sce-selectable-list__item-btn--disabled{opacity:.5;cursor:not-allowed}.sce-selectable-list__item-btn:focus-visible{outline:2px solid var(--selection-color);outline-offset:2px}.sce-selectable-list__checkbox{flex-shrink:0;width:var(--size-20);height:var(--size-20);display:flex;align-items:center;justify-content:center;background:var(--color-white);border:2px solid var(--color-border-light);border-radius:var(--radius-md);color:var(--color-white);transition:all .15s}.sce-selectable-list__checkbox--checked{background:var(--selection-color);border-color:var(--selection-color)}.sce-selectable-list__item-content{display:flex;flex-direction:column;gap:var(--space-2);flex:1;min-width:0}.sce-selectable-list__item-label{font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--color-text-display)}.sce-selectable-list__item-sublabel{font-size:var(--font-size-sm);color:var(--color-text-muted-gray)}.sce-selectable-list__empty{padding:var(--space-xl);text-align:center;font-size:var(--font-size-sm);color:var(--color-text-muted-gray)}\n"] }]
10229
10373
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }], selectedValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValues", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], multiSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSelect", required: false }] }], rtl: [{ type: i0.Input, args: [{ isSignal: true, alias: "rtl", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }] } });
10230
10374
 
10375
+ /** Bar of currently-applied filter tags (`activeFilters`) with an optional counter, "save filter" and "clear all" actions; it only emits clicks and never mutates the tag list itself. */
10231
10376
  class SceQuickFilterBarComponent {
10232
10377
  activeFilters = input([], ...(ngDevMode ? [{ debugName: "activeFilters" }] : /* istanbul ignore next */ []));
10233
10378
  showSaveFilter = input(true, ...(ngDevMode ? [{ debugName: "showSaveFilter" }] : /* istanbul ignore next */ []));
@@ -10250,6 +10395,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10250
10395
  }, template: "<div class=\"sce-quick-filter-bar\">\n @if (title()) {\n <div class=\"sce-quick-filter-bar__title\">{{ title() }}</div>\n }\n\n <div class=\"sce-quick-filter-bar__row\" [style.justify-content]=\"rowJustify()\">\n <div class=\"sce-quick-filter-bar__tags\" [style.gap]=\"tagGap() || null\">\n @for (tag of activeFilters(); track tag.key ?? $index) {\n @if (tag.values && tag.values.length > 0) {\n <div class=\"sce-quick-filter-bar__tag-group sce-quick-filter-bar__tag\">\n {{ tag.label | translate }} ({{ tag.count }}):\n @for (val of tag.values; track val) {\n <!-- When the inner remove button renders, the wrapper must NOT be interactive itself\n (axe: nested-interactive) \u2014 the button already emits the same event. -->\n <div\n [attr.role]=\"showRemoveButton() ? null : 'button'\"\n [attr.tabindex]=\"showRemoveButton() ? null : 0\"\n (click)=\"filterTagClick.emit({ key: tag.key, label: tag.label, count: 1, value: val ?? '' })\"\n (keydown.enter)=\"filterTagClick.emit({ key: tag.key, label: tag.label, count: 1, value: val ?? '' })\"\n (keydown.space)=\"\n $event.preventDefault(); filterTagClick.emit({ key: tag.key, label: tag.label, count: 1, value: val ?? '' })\n \"\n [attr.aria-label]=\"showRemoveButton() ? null : tag.label + ': ' + (val ?? '')\"\n >\n <span>\n {{ val ?? '' | translate }}\n @if (showRemoveButton()) {\n <button\n type=\"button\"\n class=\"sce-quick-filter-bar__tag-remove\"\n (click)=\"\n $event.stopPropagation(); filterTagClick.emit({ key: tag.key, label: tag.label, count: 1, value: val ?? '' })\n \"\n [attr.aria-label]=\"'COMMON.REMOVE' | translate\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n }\n </span>\n </div>\n }\n </div>\n } @else {\n <!-- Same nested-interactive guard as the grouped variant above. -->\n <div\n [attr.role]=\"showRemoveButton() ? null : 'button'\"\n [attr.tabindex]=\"showRemoveButton() ? null : 0\"\n class=\"sce-quick-filter-bar__tag\"\n (click)=\"filterTagClick.emit(tag)\"\n (keydown.enter)=\"filterTagClick.emit(tag)\"\n (keydown.space)=\"$event.preventDefault(); filterTagClick.emit(tag)\"\n [attr.aria-label]=\"showRemoveButton() ? null : tag.label + ': ' + tag.value\"\n >\n {{ tag.label | translate }} ({{ tag.count }}):\n <span>\n {{ tag.value | translate }}\n @if (showRemoveButton()) {\n <button\n type=\"button\"\n class=\"sce-quick-filter-bar__tag-remove\"\n (click)=\"$event.stopPropagation(); filterTagClick.emit(tag)\"\n [attr.aria-label]=\"'COMMON.REMOVE' | translate\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n }\n </span>\n </div>\n }\n } @empty {\n <div class=\"sce-quick-filter-bar__empty\">\n {{ 'COMMON.NO_ACTIVE_FILTERS' | translate }}\n </div>\n }\n </div>\n\n <div class=\"sce-quick-filter-bar__actions\">\n @if (showSaveFilter()) {\n <p-button\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n icon=\"pi pi-bookmark\"\n [label]=\"'COMMON.SAVE_FILTER' | translate\"\n (onClick)=\"saveFilterClick.emit()\"\n />\n }\n @if (showClearAll() && activeFilters().length > 0) {\n <p-button\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n icon=\"pi pi-trash\"\n [label]=\"'COMMON.CLEAR_ALL' | translate\"\n (onClick)=\"clearAllClick.emit()\"\n />\n }\n </div>\n </div>\n</div>\n", styles: [":host{display:block}.sce-quick-filter-bar{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap;gap:var(--space-md);margin-block-start:var(--space-lg);margin-block-end:var(--space-lg)}.sce-quick-filter-bar__title{flex-shrink:0;white-space:nowrap;margin:0;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);color:var(--color-text-display);width:100%}.sce-quick-filter-bar__row{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-md);width:100%}.sce-quick-filter-bar__tags{display:flex;flex-wrap:wrap;gap:var(--space-md)}.sce-quick-filter-bar__empty{font-size:var(--font-size-sm);color:var(--color-text-muted-gray)}.sce-quick-filter-bar__tag{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--space-sm) var(--space-md);background:var(--tag-background-neutral-light, var(--color-neutral-100));border-radius:var(--radius-lg);color:var(--color-text-display);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .15s}.sce-quick-filter-bar__tag:hover{background:var(--background-neutral-pressed, var(--color-neutral-200))}.sce-quick-filter-bar__tag:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.sce-quick-filter-bar__tag span{padding:var(--space-4, var(--space-4)) var(--space-8, var(--space-8));color:var(--color-text-display);border-radius:var(--radius-full, var(--radius-full));background:var(--border-neutral-secondary, var(--color-neutral-200));font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);display:flex;justify-content:center;align-items:center;gap:var(--space-xs)}.sce-quick-filter-bar__tag-remove{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:0;font-size:var(--font-size-xs);line-height:1;color:var(--color-text-muted-gray);flex-shrink:0}.sce-quick-filter-bar__tag-remove:hover{color:var(--color-text-display)}.sce-quick-filter-bar__tag-group{display:inline-flex;align-items:center;flex-wrap:wrap;gap:var(--space-xs)}.sce-quick-filter-bar__actions{display:flex;align-items:center;gap:var(--space-md);flex-wrap:wrap;flex-shrink:0}\n"] }]
10251
10396
  }], propDecorators: { activeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeFilters", required: false }] }], showSaveFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSaveFilter", required: false }] }], showClearAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearAll", required: false }] }], quickFilterCounter: [{ type: i0.Input, args: [{ isSignal: true, alias: "quickFilterCounter", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], tagGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "tagGap", required: false }] }], showRemoveButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRemoveButton", required: false }] }], rowJustify: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowJustify", required: false }] }], saveFilterClick: [{ type: i0.Output, args: ["saveFilterClick"] }], clearAllClick: [{ type: i0.Output, args: ["clearAllClick"] }], filterTagClick: [{ type: i0.Output, args: ["filterTagClick"] }] } });
10252
10397
 
10398
+ /** Two-step user-verification panel that first collects a national ID and birth date, then the verified user's roles, contact details and active flag, emitting `verify` and `confirm` payloads. */
10253
10399
  class SceUserVerifySectionPanelComponent {
10254
10400
  // ── Inputs ──
10255
10401
  step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
@@ -10363,6 +10509,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10363
10509
  args: [{ selector: 'sce-user-verify-section-panel', standalone: true, imports: [FormsModule, TranslatePipe, MultiSelect, SceSwitchComponent, SceSkeleton], encapsulation: ViewEncapsulation.None, host: { class: 'sce-user-verify-panel' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Step 1: Enter national ID + birth date -->\n@if (step() === 1) {\n <div class=\"sce-user-verify-panel__step\">\n <div class=\"sce-user-verify-panel__fields-grid\">\n <div class=\"sce-user-verify-panel__field\">\n <label class=\"sce-user-verify-panel__field-label\" for=\"uvp-national-id\">\n {{ 'dashboard.accountUsers.dialog.nationalId' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"uvp-national-id\"\n class=\"sce-user-verify-panel__input\"\n [class.sce-user-verify-panel__input--error]=\"nationalIdError()\"\n [placeholder]=\"'dashboard.accountUsers.dialog.nationalIdPlaceholder' | translate\"\n inputmode=\"numeric\"\n maxlength=\"10\"\n [ngModel]=\"nationalId()\"\n (ngModelChange)=\"onNationalIdChange($event)\"\n [attr.aria-describedby]=\"nationalIdError() ? 'uvp-national-id-error' : null\"\n />\n @if (nationalIdError()) {\n <span id=\"uvp-national-id-error\" class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ nationalIdError() | translate }}\n </span>\n }\n </div>\n\n <div class=\"sce-user-verify-panel__field\">\n <label class=\"sce-user-verify-panel__field-label\" for=\"uvp-birth-date\">\n {{ 'dashboard.accountUsers.dialog.birthDate' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"uvp-birth-date\"\n class=\"sce-user-verify-panel__input\"\n [class.sce-user-verify-panel__input--error]=\"birthDateError()\"\n placeholder=\"YYYY-MM-DD\"\n inputmode=\"numeric\"\n maxlength=\"10\"\n [ngModel]=\"birthDate()\"\n (ngModelChange)=\"onBirthDateChange($event)\"\n [attr.aria-describedby]=\"birthDateError() ? 'uvp-birth-date-error' : null\"\n />\n @if (birthDateError()) {\n <span id=\"uvp-birth-date-error\" class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ birthDateError() | translate }}\n </span>\n }\n </div>\n </div>\n\n @if (error()) {\n <p class=\"sce-user-verify-panel__error-msg\" role=\"alert\">{{ error() }}</p>\n }\n\n @if (loading()) {\n <div class=\"sce-user-verify-panel__loading-bar\" aria-hidden=\"true\">\n <sce-skeleton variant=\"rectangular\" animation=\"wave\" height=\"var(--space-1)\" />\n </div>\n }\n\n <div class=\"sce-user-verify-panel__actions\">\n <button class=\"sce-user-verify-panel__btn sce-user-verify-panel__btn--secondary\" type=\"button\" (click)=\"onCancel()\">\n {{ 'dashboard.accountUsers.dialog.cancel' | translate }}\n </button>\n <button\n class=\"sce-user-verify-panel__btn sce-user-verify-panel__btn--primary\"\n type=\"button\"\n [disabled]=\"loading()\"\n (click)=\"onVerify()\"\n >\n {{ 'dashboard.accountUsers.dialog.verify' | translate }}\n </button>\n </div>\n </div>\n}\n\n<!-- Step 2: Show verified data, select roles, confirm -->\n@if (step() === 2) {\n <div class=\"sce-user-verify-panel__step\">\n @if (verifiedData(); as data) {\n <div class=\"sce-user-verify-panel__readonly-grid\">\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.nationalId' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.nationalId || '\u2014' }}</p>\n </div>\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.birthDate' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.birthDate || '\u2014' }}</p>\n </div>\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.fullName' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.name || '\u2014' }}</p>\n </div>\n\n @if (requireEmail()) {\n <div class=\"sce-user-verify-panel__field\">\n <label class=\"sce-user-verify-panel__field-label\" for=\"uvp-email\">\n {{ 'dashboard.accountUsers.dialog.email' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"uvp-email\"\n class=\"sce-user-verify-panel__input\"\n [class.sce-user-verify-panel__input--error]=\"emailError()\"\n [ngModel]=\"email()\"\n (ngModelChange)=\"onEmailChange($event)\"\n inputmode=\"email\"\n [attr.aria-describedby]=\"emailError() ? 'uvp-email-error' : null\"\n />\n @if (emailError()) {\n <span id=\"uvp-email-error\" class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ emailError() | translate }}\n </span>\n }\n </div>\n } @else {\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.email' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.email || '\u2014' }}</p>\n </div>\n }\n\n @if (requireMobile()) {\n <div class=\"sce-user-verify-panel__field\">\n <label class=\"sce-user-verify-panel__field-label\" for=\"uvp-mobile\">\n {{ 'dashboard.accountUsers.dialog.mobile' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"uvp-mobile\"\n class=\"sce-user-verify-panel__input\"\n [class.sce-user-verify-panel__input--error]=\"mobileError()\"\n [ngModel]=\"mobile()\"\n (ngModelChange)=\"onMobileChange($event)\"\n inputmode=\"numeric\"\n maxlength=\"15\"\n [attr.aria-describedby]=\"mobileError() ? 'uvp-mobile-error' : null\"\n />\n @if (mobileError()) {\n <span id=\"uvp-mobile-error\" class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ mobileError() | translate }}\n </span>\n }\n </div>\n } @else {\n <div class=\"sce-user-verify-panel__readonly-field\">\n <p class=\"sce-user-verify-panel__field-label\">\n {{ 'dashboard.accountUsers.dialog.mobile' | translate }}\n </p>\n <p class=\"sce-user-verify-panel__readonly-value\">{{ data.mobile || '\u2014' }}</p>\n </div>\n }\n </div>\n }\n\n <div class=\"sce-user-verify-panel__group\">\n <h4 class=\"sce-user-verify-panel__group-title\">\n {{ 'dashboard.accountUsers.dialog.permissions' | translate }}\n </h4>\n <div class=\"sce-user-verify-panel__multi-select\">\n @if (rolesLoading()) {\n <sce-skeleton variant=\"input\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n <p-multiSelect\n [options]=\"roleOptions()\"\n [ngModel]=\"roleIds()\"\n (ngModelChange)=\"onRoleIdsChange($event)\"\n [ariaLabel]=\"'dashboard.accountUsers.dialog.permissions' | translate\"\n display=\"chip\"\n [selectedItemsLabel]=\"'dashboard.accountUsers.dialog.selectedItems' | translate\"\n [placeholder]=\"'dashboard.accountUsers.dialog.selectPermissions' | translate\"\n optionLabel=\"label\"\n optionValue=\"value\"\n appendTo=\"body\"\n />\n }\n </div>\n @if (rolesError()) {\n <span class=\"sce-user-verify-panel__field-error\" role=\"alert\">\n {{ rolesError() | translate }}\n </span>\n }\n\n <div class=\"sce-user-verify-panel__status-row\">\n <h4 class=\"sce-user-verify-panel__group-title\">\n {{ 'dashboard.accountUsers.dialog.userStatus' | translate }}\n </h4>\n <sce-switch\n [checked]=\"isActive()\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.accountUsers.dialog.active' | translate\"\n [inactiveLabel]=\"'dashboard.accountUsers.dialog.inactive' | translate\"\n (checkedChange)=\"onIsActiveChange($event)\"\n />\n </div>\n </div>\n\n @if (error()) {\n <p class=\"sce-user-verify-panel__error-msg\" role=\"alert\">{{ error() }}</p>\n }\n\n @if (loading()) {\n <div class=\"sce-user-verify-panel__loading-bar\" aria-hidden=\"true\">\n <sce-skeleton variant=\"rectangular\" animation=\"wave\" height=\"var(--space-1)\" />\n </div>\n }\n\n <div class=\"sce-user-verify-panel__actions\">\n <button class=\"sce-user-verify-panel__btn sce-user-verify-panel__btn--secondary\" type=\"button\" (click)=\"onCancel()\">\n {{ 'dashboard.accountUsers.dialog.cancel' | translate }}\n </button>\n <button\n class=\"sce-user-verify-panel__btn sce-user-verify-panel__btn--primary\"\n type=\"button\"\n [disabled]=\"loading()\"\n (click)=\"onConfirm()\"\n >\n @if (submitLabel()) {\n {{ submitLabel() }}\n } @else {\n {{ 'dashboard.accountUsers.dialog.addUser' | translate }}\n }\n </button>\n </div>\n </div>\n}\n", styles: ["sce-user-verify-section-panel{display:block;width:100%;max-width:100%;box-sizing:border-box;border:1px solid var(--color-primary-100);border-radius:var(--radius-2xl, var(--radius-2xl));padding:var(--space-24);background:var(--color-surface);margin-block-end:var(--space-20)}.sce-user-verify-panel__step{display:flex;flex-direction:column;gap:var(--space-16)}.sce-user-verify-panel__fields-grid{display:grid;grid-template-columns:1fr;gap:var(--space-16);align-items:start;width:100%}.sce-user-verify-panel__fields-grid>*{min-width:0;width:100%}@media(min-width:768px){.sce-user-verify-panel__fields-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}.sce-user-verify-panel__field{display:flex;flex-direction:column;gap:var(--space-24)}.sce-user-verify-panel__field-label{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);font-weight:500;color:var(--text-text-primary-900);margin:0}.sce-user-verify-panel__input{width:100%;box-sizing:border-box;height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding-block:var(--space-12);padding-inline:var(--space-16);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);font-weight:var(--font-weight-normal);color:var(--color-neutral-500);outline:none;transition:border-color .15s ease}.sce-user-verify-panel__input::placeholder{color:var(--color-neutral-500)}.sce-user-verify-panel__input:focus{border-color:var(--button-background-primary-bg-primary)}.sce-user-verify-panel__input:disabled{background:var(--app-surface-hover);color:var(--details-value-color);cursor:not-allowed}.sce-user-verify-panel__input--error{border:1.5px solid var(--text-text-error-primary)}.sce-user-verify-panel__input--error:focus{border-color:var(--text-text-error-primary)}.sce-user-verify-panel__field-error{font-size:var(--font-size-xs);color:var(--text-text-error-primary);margin:0}.sce-user-verify-panel__readonly-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}.sce-user-verify-panel__readonly-field{background:var(--app-surface-hover);border-radius:var(--radius-xl);padding:var(--space-16);display:grid;align-content:center;gap:var(--space-8)}.sce-user-verify-panel__readonly-value{color:var(--details-value-color);font-size:var(--details-value-size);font-weight:var(--details-value-weight);margin:0}.sce-user-verify-panel__group{display:flex;flex-direction:column;gap:var(--space-12);padding-block-start:var(--space-16);border-block-start:1px solid var(--color-primary-100)}.sce-user-verify-panel__group-title{margin:0;font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);font-weight:600;color:var(--text-text-primary-900)}.sce-user-verify-panel__multi-select{width:100%}.sce-user-verify-panel__status-row{display:flex;align-items:center;gap:var(--space-12);flex-wrap:wrap}.sce-user-verify-panel__actions{display:grid;grid-template-columns:1fr;gap:var(--space-12);width:100%;padding-block-start:var(--space-16);border-block-start:1px solid var(--color-primary-100)}@media(min-width:480px){.sce-user-verify-panel__actions{grid-template-columns:repeat(2,minmax(0,1fr))}}.sce-user-verify-panel__loading-bar{border-radius:var(--radius-full);overflow:hidden}.sce-user-verify-panel__error-msg{font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);color:var(--text-text-error-primary);margin:0}.sce-user-verify-panel__btn{display:inline-flex;align-items:center;justify-content:center;width:100%;min-height:var(--space-48);padding-block:var(--space-14);padding-inline:var(--space-24);border-radius:var(--radius-xl);font-family:var(--font-family-arabic-primary);font-weight:600;font-size:var(--font-size-lg);cursor:pointer;transition:opacity .15s ease,background .15s ease,box-shadow .15s ease,transform .1s ease}.sce-user-verify-panel__btn:disabled{opacity:.5;cursor:not-allowed}.sce-user-verify-panel__btn--primary{border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand);box-shadow:var(--shadow-brand-button)}.sce-user-verify-panel__btn--primary:hover:not(:disabled){background:var(--color-primary-700);box-shadow:var(--shadow-brand-button-hover)}.sce-user-verify-panel__btn--primary:active:not(:disabled){transform:translateY(1px)}.sce-user-verify-panel__btn--primary:disabled{box-shadow:none}.sce-user-verify-panel__btn--secondary{border:1px solid var(--button-background-primary-bg-disabled);background:var(--color-surface);color:var(--text-text-primary-900)}.sce-user-verify-panel__btn--secondary:hover:not(:disabled){background:var(--app-surface-hover)}\n"] }]
10364
10510
  }], ctorParameters: () => [], propDecorators: { step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], verifiedData: [{ type: i0.Input, args: [{ isSignal: true, alias: "verifiedData", required: false }] }], roleOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleOptions", required: false }] }], rolesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesLoading", required: false }] }], requireEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireEmail", required: false }] }], requireMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireMobile", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: false }] }], verify: [{ type: i0.Output, args: ["verify"] }], confirm: [{ type: i0.Output, args: ["confirm"] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
10365
10511
 
10512
+ /** Renderer the file viewer picks for a file; `Unsupported` shows a download-only fallback. */
10366
10513
  var FileType;
10367
10514
  (function (FileType) {
10368
10515
  FileType["Image"] = "image";
@@ -10703,6 +10850,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10703
10850
  args: [{ selector: 'sce-timeline', standalone: true, imports: [DatePipe, TooltipModule, SceEmptyStateComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-timeline' }, template: "@if (items().length) {\n <ol class=\"sce-timeline__list\">\n @for (item of items(); track item.label) {\n <li class=\"sce-timeline__item\" [class.sce-timeline__item--active]=\"item.active\">\n <button type=\"button\" class=\"sce-timeline__row\" (click)=\"itemClick.emit(item)\">\n <span class=\"sce-timeline__marker\" aria-hidden=\"true\">\n @if (item.icon) {\n <i [class]=\"item.icon\"></i>\n }\n </span>\n <span class=\"sce-timeline__content\">\n <span class=\"sce-timeline__label\">{{ item.label }}</span>\n @if (item.dateDisplay || item.date) {\n <span class=\"sce-timeline__date\">{{ item.dateDisplay || (item.date | date: 'mediumDate') }}</span>\n }\n @if (item.segments?.length) {\n <span class=\"sce-timeline__segments\">\n @for (segment of item.segments; track segment.text) {\n <span class=\"sce-timeline__segment\" [pTooltip]=\"segment.tooltip || ''\">{{ segment.text }}</span>\n }\n </span>\n }\n </span>\n </button>\n </li>\n }\n </ol>\n} @else {\n <sce-empty-state [title]=\"emptyText()\" [compact]=\"true\" imageSrc=\"\" icon=\"clock\" />\n}\n", styles: [":host{display:block}.sce-timeline__list{margin:0;padding:0;list-style:none}.sce-timeline__item{position:relative;padding-inline-start:var(--space-8)}.sce-timeline__item:before{content:\"\";position:absolute;inset-block-start:var(--space-6);inset-inline-start:var(--space-8);inline-size:1px;block-size:calc(100% - var(--space-4));background:var(--color-border-light)}.sce-timeline__item:last-child:before{display:none}.sce-timeline__row{display:flex;align-items:flex-start;gap:var(--space-3);inline-size:100%;padding-block:var(--space-3);padding-inline:0;border:0;background:transparent;text-align:start;cursor:pointer}.sce-timeline__marker{position:absolute;inset-inline-start:0;display:flex;align-items:center;justify-content:center;inline-size:var(--space-16);block-size:var(--space-16);border:2px solid var(--color-border-light);border-radius:var(--radius-full);background:var(--color-surface);font-size:var(--font-size-sm);color:var(--color-text-muted)}.sce-timeline__item--active .sce-timeline__marker{border-color:var(--color-brand-secondary-600);background:var(--color-brand-secondary-600);color:var(--color-base-white, var(--background-bg-primary))}.sce-timeline__content{display:flex;flex-direction:column;gap:var(--space-2);padding-inline-start:var(--space-16)}.sce-timeline__label{font-size:var(--font-size-base);font-weight:600;color:var(--color-text-display)}.sce-timeline__date{font-size:var(--font-size-sm);color:var(--color-text-muted)}.sce-timeline__segments{display:flex;flex-wrap:wrap;gap:var(--space-2)}.sce-timeline__segment{padding-block:var(--space-2);padding-inline:var(--space-3);border-radius:var(--radius-sm);background:var(--color-background);font-size:var(--font-size-sm);color:var(--color-text-secondary)}\n"] }]
10704
10851
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
10705
10852
 
10853
+ /** User list with a client-side name search box; filtering happens internally and only `deleteUser` is emitted to the host. */
10706
10854
  class SceSearchableUsersListComponent {
10707
10855
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
10708
10856
  users = input([], ...(ngDevMode ? [{ debugName: "users" }] : /* istanbul ignore next */ []));
@@ -10731,6 +10879,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10731
10879
  args: [{ selector: 'sce-searchable-users-list', standalone: true, imports: [SceIcon, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-searchable-users-list' }, template: "@if (title()) {\n <h3 class=\"sce-searchable-users-list__title\">{{ title() }}</h3>\n}\n\n<input type=\"search\" class=\"sce-searchable-users-list__search\" [placeholder]=\"searchPlaceholder()\" (input)=\"onSearchInput($event)\" />\n\n<ul class=\"sce-searchable-users-list__items\">\n @for (user of filteredUsers(); track user.id) {\n <li class=\"sce-searchable-users-list__item\">\n <div class=\"sce-searchable-users-list__meta\">\n <span class=\"sce-searchable-users-list__name\">{{ user.name }}</span>\n @if (user.subtitle) {\n <span class=\"sce-searchable-users-list__subtitle\">{{ user.subtitle }}</span>\n }\n </div>\n <button\n type=\"button\"\n class=\"sce-searchable-users-list__delete\"\n [attr.aria-label]=\"'COMMON.DELETE' | translate\"\n (click)=\"onDeleteClick(user)\"\n >\n <sce-icon name=\"trash-icon\" [size]=\"16\" />\n </button>\n </li>\n }\n</ul>\n", styles: [":host.sce-searchable-users-list{display:block}.sce-searchable-users-list{display:flex;flex-direction:column;gap:var(--space-3)}.sce-searchable-users-list__items{display:flex;flex-direction:column;gap:var(--space-2);margin:0;padding:0;list-style:none}.sce-searchable-users-list__item{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3)}\n"] }]
10732
10880
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], users: [{ type: i0.Input, args: [{ isSignal: true, alias: "users", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], deleteUser: [{ type: i0.Output, args: ["deleteUser"] }] } });
10733
10881
 
10882
+ /** Page header for detail screens with a title, breadcrumb trail and a row of action buttons that emit `actionClick` carrying the action's key. */
10734
10883
  class SceDetailHeaderComponent {
10735
10884
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
10736
10885
  breadcrumbs = input([], ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
@@ -10791,6 +10940,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10791
10940
  args: [{ selector: 'sce-copy-button', standalone: true, imports: [TranslatePipe, SceBidiIsolate], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-copy-button' }, template: "<button\n type=\"button\"\n class=\"sce-copy-button__btn\"\n [class.sce-copy-button__btn--copied]=\"copied()\"\n [attr.aria-label]=\"(copied() ? 'COPY_BUTTON.COPIED' : 'COPY_BUTTON.COPY') | translate\"\n (click)=\"copy()\"\n>\n @if (showValue()) {\n <span class=\"sce-copy-button__value\">\n <!-- A value worth a copy button is almost always an identifier \u2014 isolate it. -->\n <sce-bidi-isolate [value]=\"value()\" />\n </span>\n } @else if (label()) {\n <span class=\"sce-copy-button__label\">{{ label() }}</span>\n }\n <i class=\"sce-copy-button__icon\" [class.pi]=\"true\" [class.pi-copy]=\"!copied()\" [class.pi-check]=\"copied()\" aria-hidden=\"true\"></i>\n</button>\n", styles: [":host{display:block;display:inline-flex}.sce-copy-button__btn{display:inline-flex;align-items:center;gap:var(--space-2);padding-block:var(--space-2);padding-inline:var(--space-3);border:1px solid var(--color-border-light);border-radius:var(--radius-md);background:var(--color-surface);font-size:var(--font-size-sm);color:var(--color-text-secondary);cursor:pointer}.sce-copy-button__btn--copied{border-color:var(--color-brand-secondary-600);color:var(--color-brand-secondary-600)}.sce-copy-button__value{font-variant-numeric:tabular-nums;letter-spacing:.02em}.sce-copy-button__icon{font-size:var(--font-size-sm)}\n"] }]
10792
10941
  }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }] } });
10793
10942
 
10943
+ /** Header for a request page: `title`, a copyable `requestId`, a coloured `status` tag, and a row of `metaItems` (date items are run through `LocalizedDatePipe`). */
10794
10944
  class SceRequestHeaderComponent {
10795
10945
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
10796
10946
  requestId = input.required(...(ngDevMode ? [{ debugName: "requestId" }] : /* istanbul ignore next */ []));
@@ -10806,6 +10956,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10806
10956
  args: [{ selector: 'sce-request-header', standalone: true, imports: [TranslatePipe, LocalizedDatePipe, SceCopyButtonComponent, SceIcon, SceBidiIsolate], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-request-header' }, template: "<div class=\"sce-request-header__main\">\n <div class=\"sce-request-header__title-row\">\n <h3 class=\"sce-request-header__title\">{{ title() | translate }}</h3>\n <span class=\"sce-request-header__status sce-request-header__status--{{ status().color }}\">\n {{ status().label | translate }}\n </span>\n </div>\n\n @if (data()) {\n <div class=\"sce-request-header__date\">\n <span class=\"sce-request-header__date-label\">{{ dateLabelKey() | translate }}</span>\n <span class=\"sce-request-header__date-value\">{{ data() }}</span>\n </div>\n }\n\n <div class=\"sce-request-header__id\">\n <span\n ><sce-bidi-isolate>#{{ requestId() }}</sce-bidi-isolate></span\n >\n <sce-copy-button [value]=\"requestId()\" />\n </div>\n</div>\n\n@if (metaItems().length) {\n <div class=\"sce-request-header__meta\">\n @for (item of metaItems(); track item.label) {\n <div class=\"sce-request-header__meta-item\">\n <div class=\"sce-request-header__meta-label\">\n <sce-icon [name]=\"item.icon\" [size]=\"18\" />\n <span>{{ item.label | translate }}</span>\n </div>\n <span class=\"sce-request-header__meta-value\">\n @if (item.isDate) {\n {{ item.value | localizedDate }}\n } @else {\n {{ item.value }}\n }\n </span>\n </div>\n }\n </div>\n}\n", styles: [":host{display:block}.sce-request-header__main{display:flex;flex-direction:column;gap:var(--space-3)}.sce-request-header__title-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3)}.sce-request-header__title{margin:0;font-size:var(--font-size-lg);font-weight:600}.sce-request-header__status{padding:var(--space-1) var(--space-3);border-radius:var(--radius-full);font-size:var(--font-size-xs);font-weight:500}.sce-request-header__status--warning{background:var(--color-status-warning-bg);color:var(--color-status-warning-text)}.sce-request-header__status--success{background:var(--color-status-success-bg);color:var(--color-status-success-text)}.sce-request-header__status--danger{background:var(--color-status-danger-bg);color:var(--color-status-danger-text)}.sce-request-header__status--neutral{background:var(--color-surface-secondary);color:var(--color-text-secondary)}.sce-request-header__id{display:inline-flex;align-items:center;gap:var(--space-2);font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-request-header__meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:var(--space-4);margin-block-start:var(--space-4);padding-block-start:var(--space-4);border-block-start:1px solid var(--color-border-subtle)}.sce-request-header__meta-label{display:flex;align-items:center;gap:var(--space-2);font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-request-header__meta-value{display:block;margin-block-start:var(--space-1);font-size:var(--font-size-md);color:var(--color-text-primary)}\n"] }]
10807
10957
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], requestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestId", required: true }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: true }] }], metaItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "metaItems", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], dateLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateLabelKey", required: false }] }] } });
10808
10958
 
10959
+ /** Card wrapper around `sce-request-header` that adds a body slot for request details; takes the same `title`, `requestId`, `status`, and `metaItems` inputs. */
10809
10960
  class SceRequestDetailsCardComponent {
10810
10961
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
10811
10962
  requestId = input.required(...(ngDevMode ? [{ debugName: "requestId" }] : /* istanbul ignore next */ []));
@@ -10828,6 +10979,7 @@ function resolveAttachmentType(attachment) {
10828
10979
  const ext = attachment.name.split('.').pop()?.toLowerCase() ?? '';
10829
10980
  return ext === 'pdf' || ext === 'doc' || ext === 'docx' ? 'pdf' : 'image';
10830
10981
  }
10982
+ /** List of file attachments with a per-row pdf/image icon inferred from the file extension and an empty state; in `download` mode it emits `downloadFile`, in `show` mode it opens the file in a new tab itself. */
10831
10983
  class SceAttachmentsListComponent {
10832
10984
  attachments = input([], ...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
10833
10985
  titleKey = input('common.attachments', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
@@ -10855,6 +11007,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10855
11007
  args: [{ selector: 'sce-attachments-list', standalone: true, imports: [TranslatePipe, SceIcon, SceEmptyStateComponent, ImgFallbackDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-attachments-list' }, template: "@if (showSectionTitle()) {\n <h3 class=\"sce-attachments-list__title\">{{ titleKey() | translate }}</h3>\n}\n\n@if (attachments().length > 0) {\n <ul class=\"sce-attachments-list__grid\" role=\"list\">\n @for (row of attachmentRows(); track row.file.id) {\n <li class=\"sce-attachments-list__item\">\n @if (row.type === 'image') {\n <img class=\"sce-attachments-list__preview\" [src]=\"row.file.url\" [alt]=\"row.file.name\" sceImgFallback />\n } @else {\n <span class=\"sce-attachments-list__pdf-icon\" aria-hidden=\"true\">\n <sce-icon name=\"stack\" [size]=\"28\" />\n </span>\n }\n <span class=\"sce-attachments-list__name\">{{ row.file.name }}</span>\n @if (row.file.sizeLabel) {\n <span class=\"sce-attachments-list__size\">{{ row.file.sizeLabel }}</span>\n }\n <div class=\"sce-attachments-list__actions\">\n <button\n type=\"button\"\n class=\"sce-attachments-list__action\"\n [attr.aria-label]=\"(mode() === 'show' ? 'COMMON.VIEW' : 'COMMON.DOWNLOAD') | translate\"\n (click)=\"onAction(row.file)\"\n >\n <sce-icon [name]=\"mode() === 'show' ? 'eye' : 'download2'\" [size]=\"18\" />\n </button>\n @if (row.file.deletable) {\n <button\n type=\"button\"\n class=\"sce-attachments-list__action sce-attachments-list__action--delete\"\n (click)=\"deleteFile.emit(row.file.id)\"\n [attr.aria-label]=\"'common.delete' | translate\"\n >\n <sce-icon name=\"trash\" [size]=\"18\" />\n </button>\n }\n </div>\n </li>\n }\n </ul>\n} @else {\n <sce-empty-state titleKey=\"common.noAttachments\" icon=\"file-o\" [compact]=\"true\" />\n}\n", styles: [":host{display:block}.sce-attachments-list__title{margin:0 0 var(--space-4);font-size:var(--font-size-md);font-weight:600}.sce-attachments-list__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--space-3);margin:0;padding:0;list-style:none}.sce-attachments-list__item{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg)}.sce-attachments-list__preview{inline-size:100%;block-size:var(--space-20);object-fit:cover;border-radius:var(--radius-md)}.sce-attachments-list__pdf-icon{display:flex;align-items:center;justify-content:center;block-size:var(--space-20);background:var(--color-surface-secondary);border-radius:var(--radius-md)}.sce-attachments-list__name{font-size:var(--font-size-sm);overflow-wrap:anywhere}.sce-attachments-list__size{font-size:var(--font-size-xs);color:var(--color-text-secondary)}.sce-attachments-list__actions{display:flex;gap:var(--space-2)}.sce-attachments-list__action{align-self:flex-end;border:0;background:transparent;cursor:pointer;color:var(--color-brand-primary)}.sce-attachments-list__action--delete{color:var(--color-status-danger-text, var(--color-danger-default))}\n"] }]
10856
11008
  }], propDecorators: { attachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachments", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], showSectionTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSectionTitle", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], downloadFile: [{ type: i0.Output, args: ["downloadFile"] }], deleteFile: [{ type: i0.Output, args: ["deleteFile"] }] } });
10857
11009
 
11010
+ /** Profile banner showing an avatar (`avatarUrl`, falling back to a person icon), `name`, and `role`. */
10858
11011
  class SceProfileHeroComponent {
10859
11012
  name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
10860
11013
  role = input('', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
@@ -10867,6 +11020,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10867
11020
  args: [{ selector: 'sce-profile-hero', standalone: true, imports: [SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-profile-hero' }, template: "<div class=\"sce-profile-hero__center\">\n <div class=\"sce-profile-hero__avatar-ring\">\n <div class=\"sce-profile-hero__avatar\" [style.background-image]=\"avatarUrl() ? 'url(' + avatarUrl() + ')' : null\">\n @if (!avatarUrl()) {\n <sce-icon name=\"user\" [size]=\"40\" />\n }\n </div>\n </div>\n @if (name()) {\n <span class=\"sce-profile-hero__name\">{{ name() }}</span>\n }\n @if (role()) {\n <span class=\"sce-profile-hero__role\">{{ role() }}</span>\n }\n</div>\n", styles: [":host{display:block}.sce-profile-hero__center{display:flex;flex-direction:column;align-items:center;gap:var(--space-3);text-align:center}.sce-profile-hero__avatar-ring{padding:var(--space-1);border-radius:var(--radius-full);background:var(--color-border-subtle)}.sce-profile-hero__avatar{display:flex;align-items:center;justify-content:center;inline-size:var(--space-20);block-size:var(--space-20);border-radius:var(--radius-full);background-color:var(--color-surface-secondary);background-size:cover;background-position:center;overflow:hidden}.sce-profile-hero__name{font-size:var(--font-size-lg);font-weight:600;color:var(--color-text-primary)}.sce-profile-hero__role{font-size:var(--font-size-sm);color:var(--color-text-secondary)}\n"] }]
10868
11021
  }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], avatarUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarUrl", required: false }] }] } });
10869
11022
 
11023
+ /** Titled list of downloadable/linked resources from `items`; `titleKey` defaults to the knowledge-centre resources heading. */
10870
11024
  class SceResourcesListComponent {
10871
11025
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
10872
11026
  titleKey = input('knowledgeCenter.resources', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
@@ -10878,6 +11032,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10878
11032
  args: [{ selector: 'sce-resources-list', standalone: true, imports: [TranslatePipe, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-resources-list' }, template: "<h4 class=\"sce-resources-list__title\">{{ titleKey() | translate }}</h4>\n<ul class=\"sce-resources-list__list\">\n @for (item of items(); track item.url) {\n <li>\n <a [href]=\"item.url\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"sce-resources-list__link\">\n <sce-icon [name]=\"item.icon || 'pdf'\" [size]=\"20\" />\n <span class=\"sce-resources-list__label\">\n {{ item.labelKey ? (item.labelKey | translate) : (item.label ?? '') }}\n </span>\n <sce-icon name=\"download-small\" [size]=\"20\" />\n </a>\n </li>\n }\n</ul>\n", styles: [":host{display:block}.sce-resources-list__title{margin:0 0 var(--space-4);font-size:var(--font-size-md);font-weight:600}.sce-resources-list__list{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:var(--space-2)}.sce-resources-list__link{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg);color:var(--color-text-primary);text-decoration:none}.sce-resources-list__label{flex:1;min-width:0}\n"] }]
10879
11033
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
10880
11034
 
11035
+ /** "Was this helpful?" yes/no prompt (all labels are overridable i18n keys) that emits `feedback` once and then locks itself into a thank-you state. */
10881
11036
  class SceFeedbackSectionComponent {
10882
11037
  questionKey = input('knowledge.helpful', ...(ngDevMode ? [{ debugName: "questionKey" }] : /* istanbul ignore next */ []));
10883
11038
  yesKey = input('common.YES', ...(ngDevMode ? [{ debugName: "yesKey" }] : /* istanbul ignore next */ []));
@@ -10909,6 +11064,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10909
11064
  args: [{ selector: 'sce-feedback-section', standalone: true, imports: [TranslatePipe, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-feedback-section' }, template: "<div class=\"sce-feedback-section__panel\" role=\"group\" [attr.aria-label]=\"questionKey() | translate\">\n @if (!isComplete()) {\n <p class=\"sce-feedback-section__question\" id=\"sce-feedback-question\">{{ questionKey() | translate }}</p>\n <div class=\"sce-feedback-section__actions\" role=\"group\" aria-labelledby=\"sce-feedback-question\">\n <button type=\"button\" class=\"sce-feedback-section__btn sce-feedback-section__btn--yes\" [disabled]=\"isComplete()\" (click)=\"onYes()\">\n <sce-icon name=\"checkmark-badge\" [size]=\"16\" />\n {{ yesKey() | translate }}\n </button>\n <button type=\"button\" class=\"sce-feedback-section__btn sce-feedback-section__btn--no\" [disabled]=\"isComplete()\" (click)=\"onNo()\">\n <sce-icon name=\"x-badge\" [size]=\"16\" />\n {{ noKey() | translate }}\n </button>\n </div>\n } @else {\n <div class=\"sce-feedback-section__thanks-wrap\" role=\"status\" aria-live=\"polite\">\n <sce-icon class=\"sce-feedback-section__thanks-icon\" name=\"success-icon\" [size]=\"20\" />\n <p class=\"sce-feedback-section__thanks\">{{ thanksKey() | translate }}</p>\n </div>\n }\n</div>\n", styles: [":host{display:block}.sce-feedback-section__panel{padding:var(--space-24);border:1px solid var(--color-border-subtle);border-radius:var(--radius-xl);background:linear-gradient(180deg,var(--color-surface-primary) 0%,var(--color-surface-secondary) 100%);box-shadow:var(--shadow-sm, 0 1px 2px rgba(2, 6, 23, .06))}.sce-feedback-section__question{margin:0 0 var(--space-5);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-lg);font-weight:600;letter-spacing:-.01em;color:var(--color-text-primary)}.sce-feedback-section__actions{display:flex;flex-wrap:wrap;gap:var(--space-3)}.sce-feedback-section__btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);min-inline-size:6.5rem;padding:var(--space-3) var(--space-5);border:1px solid var(--color-border-default);border-radius:var(--radius-lg);background:var(--color-surface-primary);color:var(--color-text-primary);font:inherit;font-size:var(--font-size-sm);font-weight:600;cursor:pointer;transition:background-color .15s ease,border-color .15s ease,color .15s ease,transform .15s ease,box-shadow .15s ease}.sce-feedback-section__btn:hover:not(:disabled){transform:translateY(calc(var(--space-1) * -.25));box-shadow:var(--shadow-sm, 0 2px 8px rgba(2, 6, 23, .08))}.sce-feedback-section__btn:focus-visible{outline:2px solid var(--color-brand-primary);outline-offset:2px}.sce-feedback-section__btn--yes:hover:not(:disabled){border-color:var(--color-status-success-text, var(--color-brand-primary));background:var(--color-status-success-bg, var(--app-surface-hover));color:var(--color-status-success-text, var(--color-text-primary))}.sce-feedback-section__btn--no:hover:not(:disabled){border-color:var(--color-status-danger-text, var(--color-border-default));background:var(--color-status-danger-bg, var(--app-surface-hover));color:var(--color-status-danger-text, var(--color-text-primary))}.sce-feedback-section__btn:disabled{opacity:.55;cursor:not-allowed;transform:none}.sce-feedback-section__thanks-wrap{display:flex;align-items:center;gap:var(--space-3)}.sce-feedback-section__thanks-icon{flex-shrink:0;color:var(--color-status-success-text, var(--color-brand-primary))}.sce-feedback-section__thanks{margin:0;font-size:var(--font-size-md);font-weight:600;color:var(--color-status-success-text, var(--color-brand-primary))}@media(prefers-reduced-motion:reduce){.sce-feedback-section__btn:hover:not(:disabled){transform:none}}\n"] }]
10910
11065
  }], propDecorators: { questionKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "questionKey", required: false }] }], yesKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "yesKey", required: false }] }], noKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "noKey", required: false }] }], thanksKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "thanksKey", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], feedback: [{ type: i0.Output, args: ["feedback"] }] } });
10911
11066
 
11067
+ /** Renders a titled grid of related-content cards from `items`, each optionally linking to its own `route`. */
10912
11068
  class SceRelatedCardsListComponent {
10913
11069
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
10914
11070
  titleKey = input('', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
@@ -10928,6 +11084,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10928
11084
  args: [{ selector: 'sce-related-cards-list', standalone: true, imports: [TranslatePipe, RouterLink], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-related-cards-list' }, template: "@if (titleKey()) {\n <h3 class=\"sce-related-cards-list__title\">{{ titleKey() | translate }}</h3>\n}\n\n<div class=\"sce-related-cards-list__grid\">\n <!-- track $index: SceRelatedCardItem has no required field; list is a static per-page config -->\n @for (item of itemViews(); track $index) {\n @if (item.resolvedRoute; as route) {\n <a class=\"sce-related-cards-list__card\" [routerLink]=\"route\">\n @if (item.thumbnailSrc) {\n <img class=\"sce-related-cards-list__thumb\" [src]=\"item.thumbnailSrc\" alt=\"\" loading=\"lazy\" />\n }\n <h4 class=\"sce-related-cards-list__card-title\">\n {{ item.titleKey ? (item.titleKey | translate) : (item.title ?? '') }}\n </h4>\n @if (item.descriptionKey || item.description) {\n <p class=\"sce-related-cards-list__card-desc\">\n {{ item.descriptionKey ? (item.descriptionKey | translate) : (item.description ?? '') }}\n </p>\n }\n </a>\n } @else {\n <article class=\"sce-related-cards-list__card sce-related-cards-list__card--static\">\n @if (item.thumbnailSrc) {\n <img class=\"sce-related-cards-list__thumb\" [src]=\"item.thumbnailSrc\" alt=\"\" loading=\"lazy\" />\n }\n <h4 class=\"sce-related-cards-list__card-title\">\n {{ item.titleKey ? (item.titleKey | translate) : (item.title ?? '') }}\n </h4>\n @if (item.descriptionKey || item.description) {\n <p class=\"sce-related-cards-list__card-desc\">\n {{ item.descriptionKey ? (item.descriptionKey | translate) : (item.description ?? '') }}\n </p>\n }\n </article>\n }\n }\n</div>\n", styles: [":host{display:block}.sce-related-cards-list__title{margin:0 0 var(--space-4);font-size:var(--font-size-md);font-weight:600}.sce-related-cards-list__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--space-4)}.sce-related-cards-list__card{display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-4);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg);background:var(--color-surface-primary);color:inherit;text-decoration:none}.sce-related-cards-list__thumb{inline-size:100%;block-size:var(--space-20);object-fit:cover;border-radius:var(--radius-lg)}.sce-related-cards-list__card-title{margin:0;font-size:var(--font-size-sm);font-weight:600}.sce-related-cards-list__card-desc{margin:0;font-size:var(--font-size-xs);color:var(--color-text-secondary)}\n"] }]
10929
11085
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }] } });
10930
11086
 
11087
+ /** Loading placeholder for the office-detail page, rendering the hero header plus a skeleton body matching the currently active tab. */
10931
11088
  class SceOfficeDetailLoadingStateComponent {
10932
11089
  activeTab = input('overview', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
10933
11090
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SceOfficeDetailLoadingStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -10938,6 +11095,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10938
11095
  args: [{ selector: 'sce-office-detail-loading-state', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceLandingHeroHeaderComponent], host: { class: 'sce-office-detail-loading-state' }, template: "<sce-landing-hero-header [breadcrumbs]=\"[]\" title=\"\" aria-busy=\"true\">\n <div class=\"heroBody\">\n <div class=\"heroTopRow\">\n <div class=\"officeInfoColumn\">\n <div class=\"titleBlock\">\n <div class=\"shimmerBlock heroTitleSkeleton\"></div>\n <div class=\"shimmerBlock heroLocationSkeleton\"></div>\n </div>\n <div class=\"ratingRow\">\n <div class=\"reviewerSkeletonGroup\">\n @for (i of [0, 1, 2]; track i) {\n <span class=\"shimmerBlock reviewerSkeleton\"></span>\n }\n </div>\n <div class=\"ratingSkeletonGroup\">\n <div class=\"shimmerBlock starsSkeleton\"></div>\n <div class=\"shimmerBlock ratingLineSkeleton\"></div>\n </div>\n </div>\n </div>\n <div class=\"actionsRow\">\n <div class=\"shimmerBlock primaryActionSkeleton\"></div>\n <div class=\"shimmerBlock iconActionSkeleton\"></div>\n <div class=\"shimmerBlock iconActionSkeleton\"></div>\n </div>\n </div>\n </div>\n</sce-landing-hero-header>\n\n<main aria-busy=\"true\">\n <div class=\"tabsSurface\">\n <div class=\"tabsViewport\">\n <div class=\"relative w-[64px] sm:w-[130px]\">\n <div class=\"logoBadge logoBadgeSkeletonWrap\">\n <div class=\"shimmerBlock logoBadgeSkeleton\"></div>\n </div>\n </div>\n <div class=\"tabsRow\">\n <span class=\"shimmerBlock tabSkeleton\"></span>\n <span class=\"shimmerBlock tabSkeleton\"></span>\n <span class=\"shimmerBlock tabSkeleton\"></span>\n </div>\n </div>\n </div>\n\n <section class=\"contentSection\">\n @switch (activeTab()) {\n @case ('overview') {\n <div class=\"contentSkeletonLayout\">\n <div class=\"contentSkeletonColumn\">\n <div class=\"panelSkeleton shimmerPanel\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n </div>\n <div class=\"panelSkeleton shimmerPanel\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"metricSkeletonRow\">\n <div class=\"shimmerBlock metricSkeleton\"></div>\n <div class=\"shimmerBlock metricSkeleton\"></div>\n </div>\n </div>\n </div>\n <div class=\"panelSkeleton shimmerPanel mapPanelSkeleton\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock mapSkeleton\"></div>\n </div>\n </div>\n }\n @case ('projects') {\n <div class=\"contentSkeletonLayout projectsSkeletonStack\">\n @for (item of [1, 2]; track item) {\n <div class=\"panelSkeleton shimmerPanel projectPanelSkeleton\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock projectHeroSkeleton\"></div>\n <div class=\"projectThumbsSkeletonRow\">\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n <div class=\"shimmerBlock projectThumbSkeleton\"></div>\n </div>\n </div>\n }\n </div>\n }\n @case ('reviews') {\n <div class=\"contentSkeletonLayout\">\n <div class=\"contentSkeletonColumn\">\n <div class=\"panelSkeleton shimmerPanel\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n </div>\n <div class=\"panelSkeleton shimmerPanel\">\n <div class=\"shimmerBlock panelTitleSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n <div class=\"shimmerBlock panelLineSkeleton\"></div>\n </div>\n </div>\n </div>\n }\n }\n </section>\n</main>\n", styles: ["@charset \"UTF-8\";sce-office-detail-loading-state{display:block}.heroTitleSkeleton{width:min(28rem,72vi);height:var(--space-44);border-radius:var(--space-12)}.heroLocationSkeleton{width:10rem;height:var(--space-20)}.reviewerSkeletonGroup{display:flex;gap:.35rem}.reviewerSkeleton{width:var(--space-32);height:var(--space-32);border-radius:var(--radius-full)}.ratingSkeletonGroup{display:grid;gap:var(--space-8)}.starsSkeleton{width:6.5rem;height:var(--space-16)}.ratingLineSkeleton{width:9rem;height:.9rem}.primaryActionSkeleton{width:8.5rem;height:3.125rem;border-radius:var(--radius-md)}.iconActionSkeleton{width:var(--space-44);height:var(--space-44);border-radius:var(--radius-md)}.logoBadgeSkeletonWrap{display:flex;align-items:center;justify-content:center;overflow:hidden}.logoBadgeSkeleton{width:72%;height:72%;border-radius:var(--radius-full)}.tabSkeleton{width:var(--space-88, var(--size-88));height:var(--space-20);border-radius:.4rem}\n", "@charset \"UTF-8\";.shimmerBlock,.shimmerPanel{position:relative;overflow:hidden;background:#ffffff2e;border-radius:var(--space-8)}.shimmerPanel{background:var(--public-surface, var(--background-bg-primary));border-radius:var(--space-16);padding:var(--space-16) var(--space-20)}.shimmerBlock:after,.shimmerPanel:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.42) 45%,transparent 100%);animation:office-detail-shimmer 1.35s ease-in-out infinite}.shimmerPanel:after{background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.65) 45%,transparent 100%)}@keyframes office-detail-shimmer{to{transform:translate(100%)}}.contentSkeletonLayout{display:flex;width:100%;max-width:var(--size-1220);flex-direction:column;gap:var(--space-24);padding-inline:var(--space-16)}.contentSkeletonColumn{display:flex;flex:1;flex-direction:column;gap:var(--space-24)}.panelSkeleton{display:grid;gap:var(--space-12)}.panelTitleSkeleton{width:8rem;height:1.35rem}.panelLineSkeleton{width:100%;height:var(--space-16)}.panelLineSkeleton:last-child{width:82%}.metricSkeletonRow{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-16);margin-block-start:var(--space-8)}.metricSkeleton{height:var(--space-88, var(--size-88));border-radius:var(--space-16)}.mapPanelSkeleton{min-height:var(--size-280)}.mapSkeleton{width:100%;height:var(--size-220);border-radius:var(--space-16);margin-block-start:var(--space-8)}.projectsSkeletonStack{flex-direction:column;gap:var(--space-24)}.projectPanelSkeleton{width:100%}.projectHeroSkeleton{width:100%;height:var(--size-220);border-radius:var(--space-16);margin-block-start:var(--space-8)}.projectThumbsSkeletonRow{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-16);margin-block-start:var(--space-16)}.projectThumbSkeleton{width:100%;aspect-ratio:379/213;border-radius:var(--space-16)}@media(min-width:1024px){.contentSkeletonLayout{flex-direction:row;align-items:flex-start;padding-inline:0}.mapPanelSkeleton{width:min(596.5px,42%);flex-shrink:0}}\n"] }]
10939
11096
  }], propDecorators: { activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }] } });
10940
11097
 
11098
+ /** Not-found state for the office-detail page, rendering the hero header above a result state whose preset back action is suppressed in favour of the page's own links. */
10941
11099
  class SceOfficeDetailNotFoundComponent {
10942
11100
  breadcrumbs = input([], ...(ngDevMode ? [{ debugName: "breadcrumbs" }] : /* istanbul ignore next */ []));
10943
11101
  /** The page owns its own navigation links, so the preset's `back` button is suppressed. */
@@ -10950,6 +11108,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10950
11108
  args: [{ selector: 'sce-office-detail-not-found', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceLandingHeroHeaderComponent, SceResultStateComponent, RouterLink, TranslatePipe], host: { class: 'sce-office-detail-not-found' }, template: "<sce-landing-hero-header [breadcrumbs]=\"breadcrumbs()\" [title]=\"'offices.notFound' | translate\" />\n<main class=\"sce-office-detail-not-found__main\">\n <sce-result-state status=\"not-found\" titleKey=\"offices.notFound\" subtitleKey=\"engineeringOffices.empty.subtitle\" [actions]=\"noActions\">\n <div class=\"sce-office-detail-not-found__actions\">\n <a class=\"sce-office-detail-not-found__action sce-office-detail-not-found__action--primary\" routerLink=\"/engineering-offices\">\n {{ 'offices.browseOffices' | translate }}\n </a>\n <a class=\"sce-office-detail-not-found__action sce-office-detail-not-found__action--secondary\" routerLink=\"/\">\n {{ 'STATUS_PAGES.BACK_HOME' | translate }}\n </a>\n </div>\n </sce-result-state>\n</main>\n", styles: ["@charset \"UTF-8\";:host.sce-office-detail-not-found{display:block}.sce-office-detail-not-found__main{display:flex;flex-direction:column;align-items:center;justify-content:center;padding-block:var(--space-32);padding-inline:var(--space-24);text-align:center}.sce-office-detail-not-found__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--space-12)}.sce-office-detail-not-found__action{display:inline-flex;align-items:center;justify-content:center;min-height:var(--space-40);padding-inline:var(--space-16);border:var(--border-width-hairline) solid transparent;border-radius:var(--radius-brand-sm);font-weight:var(--font-weight-semibold);text-decoration:none;transition:background-color var(--transition-base),box-shadow var(--transition-base)}.sce-office-detail-not-found__action--primary{background-color:var(--color-brand-primary-800);color:var(--color-white);box-shadow:var(--shadow-brand-button)}.sce-office-detail-not-found__action--primary:hover{background-color:var(--color-brand-primary-700);box-shadow:var(--shadow-brand-button-hover)}.sce-office-detail-not-found__action--secondary{border-color:var(--color-brand-primary-200);color:var(--color-brand-primary-800)}.sce-office-detail-not-found__action--secondary:hover{border-color:var(--color-brand-primary-800);background-color:var(--color-neutral-100)}@media(prefers-reduced-motion:reduce){.sce-office-detail-not-found__action{transition:none}}\n"] }]
10951
11109
  }], propDecorators: { breadcrumbs: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumbs", required: false }] }] } });
10952
11110
 
11111
+ /** Hero content of the public office-detail page: office name with verification badge, location, star-rating summary, reviewer avatars and an optional request-contract button. */
10953
11112
  class SceOfficeDetailHeroBodyComponent {
10954
11113
  officeName = input.required(...(ngDevMode ? [{ debugName: "officeName" }] : /* istanbul ignore next */ []));
10955
11114
  verificationStatus = input(null, ...(ngDevMode ? [{ debugName: "verificationStatus" }] : /* istanbul ignore next */ []));
@@ -10968,6 +11127,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10968
11127
  args: [{ selector: 'sce-office-detail-hero-body', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceEngineeringOfficeVerificationBadgeComponent, TranslatePipe], host: { class: 'sce-office-detail-hero-body' }, template: "<div class=\"heroBody\">\n <div class=\"heroTopRow\">\n <div class=\"officeInfoColumn\">\n <div class=\"titleBlock\">\n <div class=\"titleRow\">\n <h1 class=\"officeTitle\">{{ officeName() }}</h1>\n <sce-engineering-office-verification-badge [status]=\"verificationStatus()\" [size]=\"24\" />\n </div>\n <div class=\"locationRow\">\n <img src=\"/assets/icons/location-05-alt.svg\" width=\"20\" height=\"20\" class=\"locationIcon\" alt=\"\" aria-hidden=\"true\" />\n <span class=\"locationText\">{{ locationText() }}</span>\n </div>\n </div>\n\n <div class=\"ratingRow\">\n <div class=\"ratingInfo\">\n <div class=\"starRow\">\n @for (star of [1, 2, 3, 4, 5]; track star) {\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n [class]=\"star <= filledStars() ? 'starIconActive' : 'starIconInactive'\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z\" />\n </svg>\n }\n </div>\n <span class=\"ratingSummary\">{{ ratingValue().toFixed(1) }} \u2014 {{ ratingSummary() }}</span>\n @if (reviewerAvatars().length > 0) {\n <div class=\"reviewerList\" aria-hidden=\"true\">\n @for (avatar of reviewerAvatars(); track avatar) {\n <img [src]=\"avatar\" alt=\"\" class=\"reviewerAvatar\" width=\"32\" height=\"32\" />\n }\n </div>\n }\n </div>\n </div>\n\n @if (canRequestContract()) {\n <div class=\"actionsRow\">\n <button type=\"button\" class=\"primaryAction\" (click)=\"requestContract.emit()\">\n {{ 'engineeringOffices.detail.requestContract' | translate }}\n </button>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
10969
11128
  }], propDecorators: { officeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeName", required: true }] }], verificationStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "verificationStatus", required: false }] }], locationText: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationText", required: false }] }], filledStars: [{ type: i0.Input, args: [{ isSignal: true, alias: "filledStars", required: false }] }], ratingValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingValue", required: false }] }], ratingSummary: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingSummary", required: false }] }], reviewerAvatars: [{ type: i0.Input, args: [{ isSignal: true, alias: "reviewerAvatars", required: false }] }], canRequestContract: [{ type: i0.Input, args: [{ isSignal: true, alias: "canRequestContract", required: false }] }], requestContract: [{ type: i0.Output, args: ["requestContract"] }] } });
10970
11129
 
11130
+ /** Tab bar of the office-detail page, showing the office's brand logo and name beside the tab buttons and emitting `tabChange` on selection. */
10971
11131
  class SceOfficeDetailTabsBarComponent {
10972
11132
  tabItems = input.required(...(ngDevMode ? [{ debugName: "tabItems" }] : /* istanbul ignore next */ []));
10973
11133
  activeTab = input.required(...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
@@ -10982,6 +11142,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10982
11142
  args: [{ selector: 'sce-office-detail-tabs-bar', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceOfficeBrandLogoComponent], host: { class: 'sce-office-detail-tabs-bar' }, template: "<div class=\"tabsSurface\">\n <div class=\"tabsViewport\">\n <div class=\"relative w-[64px] sm:w-[130px]\">\n <div class=\"logoBadge\">\n <div class=\"logoBadgeInner\">\n <sce-office-brand-logo\n [src]=\"logoObjectUrl()\"\n [alt]=\"officeName()\"\n className=\"logoBadgePhoto\"\n iconClassName=\"logoBadgeIcon\"\n size=\"7rem\"\n />\n </div>\n </div>\n </div>\n <div class=\"tabsRow\">\n @for (tab of tabItems(); track tab.key) {\n <button\n type=\"button\"\n class=\"tabLink\"\n [class.tabLinkActive]=\"activeTab() === tab.key\"\n [class.tabLinkInactive]=\"activeTab() !== tab.key\"\n (click)=\"tabChange.emit(tab.key)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
10983
11143
  }], propDecorators: { tabItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabItems", required: true }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: true }] }], logoObjectUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoObjectUrl", required: false }] }], officeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeName", required: false }] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }] } });
10984
11144
 
11145
+ /** Overview tab of the office-detail page, showing the office bio, an OSM map of its location and rows of experience and compatibility metric cards. */
10985
11146
  class SceOfficeDetailOverviewPanelComponent {
10986
11147
  officeBio = input('', ...(ngDevMode ? [{ debugName: "officeBio" }] : /* istanbul ignore next */ []));
10987
11148
  locationText = input('', ...(ngDevMode ? [{ debugName: "locationText" }] : /* istanbul ignore next */ []));
@@ -10996,6 +11157,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
10996
11157
  args: [{ selector: 'sce-office-detail-overview-panel', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceOfficeMetricCardsRowComponent, SceOsmOfficesMapComponent, TranslatePipe], host: { class: 'sce-office-detail-overview-panel' }, template: "<div class=\"overviewPanel\">\n <div class=\"overviewMain\">\n <div class=\"overviewCard\">\n <h2 class=\"overviewCardTitle\">{{ 'engineeringOffices.overview.about' | translate }}</h2>\n <p class=\"overviewCardBody\">\n @if (officeBio()) {\n {{ officeBio() }}\n } @else {\n {{ 'engineeringOffices.overview.defaultBio' | translate }}\n }\n </p>\n </div>\n\n <div class=\"overviewCard\">\n <div class=\"overviewCardInner\">\n <h2 class=\"overviewCardTitle\">{{ 'engineeringOffices.overview.experience' | translate }}</h2>\n <p class=\"overviewCardBody\">{{ officeBio() }}</p>\n </div>\n <sce-office-metric-cards-row [items]=\"experienceMetricItems()\" variant=\"accent\" [columns]=\"3\" />\n </div>\n </div>\n\n <aside class=\"overviewSidebar\">\n <div class=\"overviewCard\">\n <h2 class=\"overviewCardTitle\">{{ 'engineeringOffices.overview.location' | translate }}</h2>\n <span class=\"overviewLocationRow\">\n <img src=\"/assets/icons/location-05-alt.svg\" width=\"20\" height=\"20\" class=\"overviewLocationIcon\" alt=\"\" aria-hidden=\"true\" />\n <p class=\"overviewCardBody\">{{ locationText() }}</p>\n </span>\n @defer (on viewport) {\n <sce-osm-offices-map [offices]=\"mapPoints()\" [showTooltip]=\"false\" class=\"detailSidebarMap\" />\n } @placeholder {\n <div class=\"detailSidebarMap\" aria-hidden=\"true\"></div>\n }\n </div>\n </aside>\n</div>\n", styles: [":host{display:block}\n"] }]
10997
11158
  }], ctorParameters: null, propDecorators: { officeBio: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeBio", required: false }] }], locationText: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationText", required: false }] }], mapPoints: [{ type: i0.Input, args: [{ isSignal: true, alias: "mapPoints", required: false }] }], experienceMetricItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "experienceMetricItems", required: false }] }], compatibilityMetricItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "compatibilityMetricItems", required: false }] }] } }) });
10998
11159
 
11160
+ /** Projects tab of the office-detail page, rendering each of the office's projects alongside its image gallery. */
10999
11161
  class SceOfficeDetailProjectsPanelComponent {
11000
11162
  projects = input([], ...(ngDevMode ? [{ debugName: "projects" }] : /* istanbul ignore next */ []));
11001
11163
  projectGalleryImages = input([], ...(ngDevMode ? [{ debugName: "projectGalleryImages" }] : /* istanbul ignore next */ []));
@@ -11008,6 +11170,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
11008
11170
  args: [{ selector: 'sce-office-detail-projects-panel', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SceOfficeProjectGalleryComponent, TranslatePipe], host: { class: 'sce-office-detail-projects-panel' }, template: "<div class=\"projectsPanel\">\n @if (projects().length === 0) {\n <p class=\"projectsEmpty\">{{ 'engineeringOffices.detail.emptyProjects' | translate }}</p>\n } @else {\n @for (project of projects(); track project.title; let idx = $index) {\n <article class=\"projectCard\">\n <header class=\"projectContent\">\n <h3 class=\"projectTitle\">{{ project.title }}</h3>\n @if (project.description) {\n <p class=\"projectDesc\">{{ project.description }}</p>\n }\n <div class=\"projectBadges\">\n @if (project.status === 'completed') {\n <span class=\"projectBadge projectBadgeCompleted\">\n {{ 'engineeringOffices.detail.projectStatusCompleted' | translate }}\n </span>\n } @else if (project.status === 'inProgress') {\n <span class=\"projectBadge projectBadgeInProgress\">\n {{ 'engineeringOffices.detail.projectStatusInProgress' | translate }}\n </span>\n } @else if (project.status === 'new') {\n <span class=\"projectBadge projectBadgeNew\">\n {{ 'engineeringOffices.detail.projectStatusNew' | translate }}\n </span>\n }\n @if (project.typeLabel) {\n <span class=\"projectBadge projectBadgeCategory\">\n {{ project.typeLabel }}\n </span>\n }\n </div>\n </header>\n @defer (on viewport) {\n <sce-office-project-gallery\n [imageUrls]=\"projectGalleryImages()[idx].urls\"\n [title]=\"project.title\"\n [locale]=\"locale() === 'ar' ? 'ar' : 'en'\"\n />\n } @placeholder {\n <div class=\"projectGalleryPlaceholder\" aria-hidden=\"true\"></div>\n }\n </article>\n }\n }\n</div>\n", styles: [":host{display:block}\n"] }]
11009
11171
  }], ctorParameters: null, propDecorators: { projects: [{ type: i0.Input, args: [{ isSignal: true, alias: "projects", required: false }] }], projectGalleryImages: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectGalleryImages", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }] } }) });
11010
11172
 
11173
+ /** Reviews tab of the office-detail page, showing the overall rating, the per-star rating distribution and the individual reviews. */
11011
11174
  class SceOfficeDetailReviewsPanelComponent {
11012
11175
  reviews = input([], ...(ngDevMode ? [{ debugName: "reviews" }] : /* istanbul ignore next */ []));
11013
11176
  totalReviews = input(0, ...(ngDevMode ? [{ debugName: "totalReviews" }] : /* istanbul ignore next */ []));
@@ -11072,6 +11235,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11072
11235
  args: [{ selector: 'sce-form-rich-text', standalone: true, imports: [ReactiveFormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-form-rich-text' }, template: "<label class=\"sce-form-rich-text__label\" [for]=\"fieldId\">{{ labelTranslateKey() | translate }}</label>\n<textarea\n [id]=\"fieldId\"\n class=\"sce-form-rich-text__area\"\n [formControl]=\"inner\"\n [style.min-height]=\"editorHeight()\"\n (blur)=\"onBlur()\"\n></textarea>\n", styles: [":host{display:block}.sce-form-rich-text__label{display:block;margin-block-end:var(--space-8);font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-form-rich-text__area{inline-size:100%;padding:var(--space-12);border:var(--border-width-1) solid var(--color-border-default);border-radius:var(--radius-lg);font:inherit;resize:block}\n"] }]
11073
11236
  }], ctorParameters: () => [], propDecorators: { labelTranslateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelTranslateKey", required: false }] }], editorHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "editorHeight", required: false }] }] } });
11074
11237
 
11238
+ /** Picks the `<key>Ar`/`<key>En` property of an object matching the active language (falling back to the other language, then to the bare `key`, then to ''); pure, so it does not re-run on a language switch unless the object reference changes. */
11075
11239
  class LocalizedValuePipe {
11076
11240
  translate = inject(TranslateService);
11077
11241
  transform(obj, key, options) {
@@ -11100,6 +11264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11100
11264
  }]
11101
11265
  }] });
11102
11266
 
11267
+ /** Displays a phone number with an optional leading icon and a copy-to-clipboard button (shown by default). */
11103
11268
  class ScePhoneNumberComponent {
11104
11269
  value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
11105
11270
  showCopy = input(true, ...(ngDevMode ? [{ debugName: "showCopy" }] : /* istanbul ignore next */ []));
@@ -11113,6 +11278,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11113
11278
  args: [{ selector: 'sce-phone-number', standalone: true, imports: [SceCopyButtonComponent, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-phone-number' }, template: "<div class=\"sce-phone-number__row\">\n @if (showIcon()) {\n <sce-icon class=\"sce-phone-number__icon\" name=\"phone\" [size]=\"iconSize()\" />\n }\n @if (showCopy()) {\n <sce-copy-button class=\"sce-phone-number__copy\" [value]=\"value()\" [showValue]=\"true\" />\n } @else {\n <span class=\"sce-phone-number__value\" dir=\"ltr\">{{ value() }}</span>\n }\n</div>\n", styles: [":host{display:block;display:inline-flex;align-items:center;gap:var(--space-8)}.sce-phone-number__value{direction:ltr}\n"] }]
11114
11279
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], showCopy: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCopy", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }] } });
11115
11280
 
11281
+ /** Title-and-description row with a trailing edit button (shown by default, labelled from the translated "edit" key unless overridden). */
11116
11282
  class SceInfoRowComponent {
11117
11283
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
11118
11284
  description = input.required(...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
@@ -11130,6 +11296,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11130
11296
  args: [{ selector: 'sce-info-row', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-info-row' }, template: "<div class=\"sce-info-row__content\">\n <span class=\"sce-info-row__title\">{{ title() }}</span>\n <span class=\"sce-info-row__description\" [attr.dir]=\"ltr() ? 'ltr' : null\">{{ description() }}</span>\n</div>\n\n@if (showEdit()) {\n <button type=\"button\" class=\"sce-info-row__edit\" (click)=\"editClick.emit()\">\n {{ resolvedEditLabel() }}\n </button>\n}\n", styles: [":host{display:block}\n"] }]
11131
11297
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: true }] }], editLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "editLabel", required: false }] }], showEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEdit", required: false }] }], ltr: [{ type: i0.Input, args: [{ isSignal: true, alias: "ltr", required: false }] }], editClick: [{ type: i0.Output, args: ["editClick"] }] } });
11132
11298
 
11299
+ /** Compact summary tile pairing an icon with a label, a primary value and an optional secondary value. */
11133
11300
  class SceSummaryCardComponent {
11134
11301
  icon = input.required(...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
11135
11302
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
@@ -11143,6 +11310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11143
11310
  args: [{ selector: 'sce-summary-card', standalone: true, imports: [SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-summary-card' }, template: "<div class=\"sce-summary-card__icon\" aria-hidden=\"true\">\n <sce-icon [name]=\"icon()\" [size]=\"30\" />\n</div>\n<div class=\"sce-summary-card__info\">\n <span class=\"sce-summary-card__label\">{{ label() }}</span>\n <div class=\"sce-summary-card__value\">\n <span>{{ value() }}</span>\n @if (subValue()) {\n <span class=\"sce-summary-card__sub-value\">{{ subValue() }}</span>\n }\n </div>\n</div>\n", styles: [":host{display:block;display:flex;align-items:center;gap:var(--space-4);padding:var(--space-4);border:1px solid var(--color-neutral-200, var(--color-border-subtle));border-radius:var(--radius-lg, .75rem);background:var(--color-surface, var(--app-surface));box-shadow:var(--shadow-xs, none)}.sce-summary-card__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;inline-size:var(--space-12);block-size:var(--space-12);border-radius:var(--radius-lg);background:var(--app-surface-hover, var(--color-surface-secondary));color:var(--color-brand-primary)}.sce-summary-card__info{display:flex;flex-direction:column;gap:var(--space-1);min-width:0}.sce-summary-card__label{font-family:var(--font-family-arabic-primary);font-size:var(--details-label-size, var(--font-size-sm));font-weight:var(--details-label-weight, 500);color:var(--details-label-color, var(--color-text-secondary))}.sce-summary-card__value{display:flex;align-items:baseline;flex-wrap:wrap;gap:var(--space-2);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-xl);font-weight:700;line-height:1.2;color:var(--details-value-color, var(--color-text-primary))}.sce-summary-card__sub-value{font-size:var(--font-size-sm);font-weight:500;color:var(--color-text-secondary)}\n"] }]
11144
11311
  }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], subValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "subValue", required: false }] }] } });
11145
11312
 
11313
+ /** Card identifying an entity by logo (or fallback icon), name, subtitle and ID, with a tone-coloured badge label that defaults to the success tone. */
11146
11314
  class SceEntityInfoCardComponent {
11147
11315
  labelKey = input.required(...(ngDevMode ? [{ debugName: "labelKey" }] : /* istanbul ignore next */ []));
11148
11316
  nameKey = input('', ...(ngDevMode ? [{ debugName: "nameKey" }] : /* istanbul ignore next */ []));
@@ -11169,6 +11337,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11169
11337
  }, template: "<span class=\"sce-entity-info-card__badge\">{{ labelKey() | translate }}</span>\n\n<div class=\"sce-entity-info-card__main\">\n <div class=\"sce-entity-info-card__logo\">\n @if (logoSrc()) {\n <img class=\"sce-entity-info-card__logo-img\" [src]=\"logoSrc()!\" [alt]=\"logoAlt()\" width=\"64\" height=\"64\" loading=\"lazy\" />\n } @else {\n <sce-icon [name]=\"iconName()\" [size]=\"iconSize()\" />\n }\n </div>\n\n <div class=\"sce-entity-info-card__copy\">\n <h3 class=\"sce-entity-info-card__name\">\n @if (nameText()) {\n {{ nameText() }}\n } @else {\n {{ nameKey() | translate }}\n }\n </h3>\n @if (subtitleText()) {\n <p class=\"sce-entity-info-card__subtitle\">{{ subtitleText() }}</p>\n }\n @if (idLabelKey() && idValue()) {\n <p class=\"sce-entity-info-card__id\">\n <span class=\"sce-entity-info-card__id-label\">{{ idLabelKey() | translate }}</span>\n <span class=\"sce-entity-info-card__id-value\" dir=\"ltr\">{{ idValue() }}</span>\n </p>\n }\n </div>\n</div>\n", styles: [":host{display:block;padding:var(--space-5);border:1px solid var(--color-neutral-200, var(--color-border-subtle));border-radius:var(--radius-lg, .75rem);background:var(--color-surface, var(--app-surface))}.sce-entity-info-card__badge{display:inline-block;margin-block-end:var(--space-4);padding:var(--space-1) var(--space-3);border-radius:var(--radius-full);font-size:var(--font-size-xs);font-weight:600;letter-spacing:.01em;background:var(--color-status-success-bg);color:var(--color-status-success-text)}:host(.sce-entity-info-card--badge-info) .sce-entity-info-card__badge{background:var(--color-status-info-bg, var(--color-surface-secondary));color:var(--color-status-info-text, var(--color-text-primary))}:host(.sce-entity-info-card--badge-warning) .sce-entity-info-card__badge{background:var(--color-status-warning-bg);color:var(--color-status-warning-text)}:host(.sce-entity-info-card--badge-error) .sce-entity-info-card__badge{background:var(--color-status-danger-bg);color:var(--color-status-danger-text)}:host(.sce-entity-info-card--badge-neutral) .sce-entity-info-card__badge{background:var(--color-neutral-100);color:var(--color-neutral-700)}.sce-entity-info-card__main{display:flex;align-items:center;gap:var(--space-4)}.sce-entity-info-card__logo{display:flex;align-items:center;justify-content:center;flex-shrink:0;inline-size:var(--space-16);block-size:var(--space-16);border:1px solid var(--color-neutral-200, var(--color-border-subtle));border-radius:var(--radius-lg);background:var(--app-surface-hover, var(--color-surface-secondary));overflow:hidden}.sce-entity-info-card__logo-img{inline-size:100%;block-size:100%;object-fit:cover}.sce-entity-info-card__name{margin:0 0 var(--space-1);font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);font-weight:600;color:var(--color-text-primary)}.sce-entity-info-card__subtitle{margin:0 0 var(--space-2);font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-entity-info-card__id{margin:0;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.sce-entity-info-card__id-value{margin-inline-start:var(--space-1);font-weight:600;color:var(--color-text-primary)}\n"] }]
11170
11338
  }], propDecorators: { labelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelKey", required: true }] }], nameKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "nameKey", required: false }] }], nameText: [{ type: i0.Input, args: [{ isSignal: true, alias: "nameText", required: false }] }], subtitleText: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitleText", required: false }] }], idLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "idLabelKey", required: false }] }], idValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "idValue", required: false }] }], logoSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoSrc", required: false }] }], logoAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoAlt", required: false }] }], iconName: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconName", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], badgeTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeTone", required: false }] }] } });
11171
11339
 
11340
+ /** Card that either shows a completion progress bar or, in `cta` mode, an illustrated call-to-action button emitting `nextStep`. */
11172
11341
  class SceProgressCardComponent {
11173
11342
  mode = input('progress', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
11174
11343
  titleKey = input('', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));
@@ -11190,6 +11359,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11190
11359
  }, template: "@if (titleText() || titleKey()) {\n <h4 class=\"sce-progress-card__title\">{{ titleText() || (titleKey() | translate) }}</h4>\n}\n@if (illustrationSrc()) {\n <div class=\"sce-progress-card__illustration\">\n <img [src]=\"illustrationSrc()\" alt=\"\" loading=\"lazy\" />\n </div>\n}\n@if (descriptionText() || descriptionKey()) {\n <p class=\"sce-progress-card__desc\">{{ descriptionText() || (descriptionKey() | translate) }}</p>\n}\n@if (mode() === 'progress') {\n <sce-progress-bar [progress]=\"progress()\" [max]=\"100\" [showLabel]=\"true\" />\n}\n<ng-content select=\"[data-actions]\" />\n@if (buttonKey()) {\n <button type=\"button\" class=\"sce-progress-card__action\" (click)=\"nextStep.emit()\">\n {{ buttonKey() | translate }}\n </button>\n}\n", styles: [":host{display:block;display:grid;gap:var(--space-5);padding:var(--space-24);border:1px solid var(--color-primary-100, var(--card-border-subtle));border-radius:var(--radius-xl, var(--space-4));background:var(--color-surface, var(--app-surface))}:host(.sce-progress-card--cta){gap:var(--space-4)}.sce-progress-card__title{margin:0;color:var(--text-text-primary-900, var(--color-text-primary));font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold)}.sce-progress-card__desc{margin:0;color:var(--text-text-secondary-700, var(--color-text-secondary));font-size:var(--font-size-md);font-weight:var(--font-weight-regular)}.sce-progress-card__illustration{display:flex;justify-content:center}.sce-progress-card__illustration img{max-inline-size:100%;block-size:auto}.sce-progress-card__action{inline-size:100%;border:0;border-radius:var(--radius-lg, var(--space-3));padding:var(--space-3-5, var(--space-3)) var(--space-24);background:var(--button-background-primary-bg-primary, var(--color-brand-primary));color:var(--text-text-primaryon-brand, var(--color-on-primary));font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);cursor:pointer}\n"] }]
11191
11360
  }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], titleKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleKey", required: false }] }], descriptionKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptionKey", required: false }] }], titleText: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleText", required: false }] }], descriptionText: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptionText", required: false }] }], buttonKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonKey", required: false }] }], progress: [{ type: i0.Input, args: [{ isSignal: true, alias: "progress", required: false }] }], illustrationSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "illustrationSrc", required: false }] }], nextStep: [{ type: i0.Output, args: ["nextStep"] }] } });
11192
11361
 
11362
+ /** Prose block that renders the translated `contentKey` as a paragraph, unless `contentHtml` is supplied, in which case that raw HTML is rendered instead. */
11193
11363
  class SceContentBlockComponent {
11194
11364
  contentKey = input.required(...(ngDevMode ? [{ debugName: "contentKey" }] : /* istanbul ignore next */ []));
11195
11365
  contentHtml = input(null, ...(ngDevMode ? [{ debugName: "contentHtml" }] : /* istanbul ignore next */ []));
@@ -11201,6 +11371,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11201
11371
  args: [{ selector: 'sce-content-block', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-content-block' }, template: "@if (contentHtml()) {\n <div class=\"sce-content-block__body sce-content-block__body--rich\" [innerHTML]=\"contentHtml()\"></div>\n} @else {\n <p class=\"sce-content-block__body\">{{ contentKey() | translate }}</p>\n}\n", styles: [":host{display:block}\n"] }]
11202
11372
  }], propDecorators: { contentKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentKey", required: true }] }], contentHtml: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentHtml", required: false }] }] } });
11203
11373
 
11374
+ /** Renders `items` (translation keys) as an icon-bulleted list, laid out across `maxColumns` columns (default 1). */
11204
11375
  class SceBulletListComponent {
11205
11376
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
11206
11377
  maxColumns = input(1, ...(ngDevMode ? [{ debugName: "maxColumns" }] : /* istanbul ignore next */ []));
@@ -11212,6 +11383,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11212
11383
  args: [{ selector: 'sce-bullet-list', standalone: true, imports: [TranslatePipe, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-bullet-list' }, template: "<ul class=\"sce-bullet-list__grid\" [style.grid-template-columns]=\"'repeat(' + maxColumns() + ', minmax(0, 1fr))'\">\n <!-- track $index: static bullet text list, fully replaced per input change -->\n @for (item of items(); track $index) {\n <li class=\"sce-bullet-list__item\">\n <sce-icon name=\"checked\" [size]=\"15\" class=\"sce-bullet-list__icon\" />\n <span>{{ item | translate }}</span>\n </li>\n }\n</ul>\n", styles: [":host{display:block}.sce-bullet-list__grid{display:grid;gap:var(--space-3);margin:0;padding:0;list-style:none}.sce-bullet-list__item{display:flex;align-items:flex-start;gap:var(--space-2);font-size:var(--font-size-sm);color:var(--color-text-primary)}.sce-bullet-list__icon{flex-shrink:0;margin-block-start:var(--space-1);color:var(--color-brand-primary)}\n"] }]
11213
11384
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], maxColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxColumns", required: false }] }] } });
11214
11385
 
11386
+ /** Dashboard KPI card showing a headline value, an up/down trend percentage and an optional sparkline chart. */
11215
11387
  class SceStatsAnalyticsCardComponent {
11216
11388
  title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
11217
11389
  titleLinkText = input('', ...(ngDevMode ? [{ debugName: "titleLinkText" }] : /* istanbul ignore next */ []));
@@ -11232,6 +11404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11232
11404
  args: [{ selector: 'sce-stats-analytics-card', standalone: true, imports: [SceIcon, SceOverviewStatSparklineComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-stats-analytics-card' }, template: "<article class=\"sce-stats-analytics-card__surface\">\n <div class=\"sce-stats-analytics-card__header\">\n @if (titleLinkText()) {\n <a\n class=\"sce-stats-analytics-card__link\"\n [href]=\"titleLinkUrl() || '#'\"\n [attr.target]=\"titleLinkUrl() ? '_blank' : null\"\n [attr.rel]=\"titleLinkUrl() ? 'noopener noreferrer' : null\"\n >\n {{ titleLinkText() }}\n </a>\n }\n <h3 class=\"sce-stats-analytics-card__title\">{{ title() }}</h3>\n </div>\n\n <div class=\"sce-stats-analytics-card__body\">\n @if (showChart()) {\n <div class=\"sce-stats-analytics-card__chart\" aria-hidden=\"true\">\n <sce-overview-stat-sparkline [color]=\"chartColor()\" />\n </div>\n }\n\n <div class=\"sce-stats-analytics-card__metric\">\n @if (percentage() != null) {\n <div class=\"sce-stats-analytics-card__trend\">\n @if (trendLabel()) {\n <span class=\"sce-stats-analytics-card__trend-label\">{{ trendLabel() }}</span>\n }\n <span class=\"sce-stats-analytics-card__trend-percent\">{{ percentage() }}%</span>\n </div>\n }\n <div class=\"sce-stats-analytics-card__value-row\">\n <span class=\"sce-stats-analytics-card__value\">{{ value() }}</span>\n @if (showTrendIcon()) {\n <sce-icon [name]=\"trendIcon()\" [size]=\"24\" />\n }\n </div>\n </div>\n </div>\n</article>\n", styles: [":host{display:block}.sce-stats-analytics-card__surface{padding:var(--space-4);border:1px solid var(--color-border-subtle);border-radius:var(--radius-lg);background:var(--color-surface-primary)}.sce-stats-analytics-card__header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);margin-block-end:var(--space-3)}.sce-stats-analytics-card__title{margin:0;font-size:var(--font-size-sm);font-weight:500;color:var(--color-text-secondary)}.sce-stats-analytics-card__link{font-size:var(--font-size-sm);color:var(--color-brand-primary);text-decoration:none}.sce-stats-analytics-card__body{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--space-4)}.sce-stats-analytics-card__value-row{display:flex;align-items:center;gap:var(--space-2)}.sce-stats-analytics-card__value{font-size:var(--font-size-2xl);font-weight:700;color:var(--color-text-primary)}.sce-stats-analytics-card__trend{margin-block-end:var(--space-1);font-size:var(--font-size-xs);color:var(--color-text-secondary)}\n"] }]
11233
11405
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], titleLinkText: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleLinkText", required: false }] }], titleLinkUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleLinkUrl", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], percentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "percentage", required: false }] }], trend: [{ type: i0.Input, args: [{ isSignal: true, alias: "trend", required: false }] }], trendLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "trendLabel", required: false }] }], showTrendIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTrendIcon", required: false }] }], showChart: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChart", required: false }] }], chartColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartColor", required: false }] }] } });
11234
11406
 
11407
+ /** Result screen shown after office-profile changes are submitted, rendering either the success or the pending-review outcome with links to the profile and the requests list. */
11235
11408
  class SceOfficeProfileSubmitResultComponent {
11236
11409
  result = input.required(...(ngDevMode ? [{ debugName: "result" }] : /* istanbul ignore next */ []));
11237
11410
  viewProfile = output();
@@ -11244,6 +11417,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11244
11417
  args: [{ selector: 'sce-office-profile-submit-result', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-submit-result' }, imports: [TranslatePipe], template: "<div class=\"submitResultPage\">\n <section class=\"submitResultCard\">\n <div class=\"submitResultIconWrap\" aria-hidden=\"true\">\n @if (result() === 'success') {\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"96\" height=\"96\" viewBox=\"0 0 96 96\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"48\" cy=\"48\" r=\"48\" fill=\"var(--color-kiwi-200)\" />\n <path d=\"M28 50l13 13 27-27\" stroke=\"var(--color-jade-700)\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n } @else {\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"88\" height=\"88\" viewBox=\"0 0 88 88\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"44\" cy=\"44\" r=\"44\" fill=\"var(--color-yellow-100)\" />\n <path d=\"M44 26v22M44 60v2\" stroke=\"var(--color-warning-700)\" stroke-width=\"5\" stroke-linecap=\"round\" />\n </svg>\n }\n </div>\n\n @if (result() === 'success') {\n <h2 class=\"submitResultTitle\">\n {{ 'dashboard.officeProfileEdit.success.title' | translate }}\n </h2>\n <p class=\"submitResultSubtitle\">\n {{ 'dashboard.officeProfileEdit.success.subtitle' | translate }}\n </p>\n <p class=\"submitResultNotice\">\n {{ 'dashboard.officeProfileEdit.success.notice' | translate }}\n </p>\n <div class=\"submitResultActions\">\n <button type=\"button\" class=\"primaryButton\" (click)=\"viewProfile.emit()\">\n {{ 'dashboard.officeProfileEdit.success.viewProfile' | translate }}\n </button>\n <button type=\"button\" class=\"cancelButton\" (click)=\"viewProfile.emit()\">\n {{ 'dashboard.officeProfileEdit.success.backHome' | translate }}\n </button>\n </div>\n } @else {\n <h2 class=\"submitResultTitle\">\n {{ 'dashboard.officeProfileEdit.pending.title' | translate }}\n </h2>\n <p class=\"submitResultSubtitle\">\n {{ 'dashboard.officeProfileEdit.pending.subtitle' | translate }}\n </p>\n <p class=\"submitResultNotice\">\n {{ 'dashboard.officeProfileEdit.pending.notice' | translate }}\n </p>\n <div class=\"submitResultActions\">\n <button type=\"button\" class=\"primaryButton\" (click)=\"viewRequests.emit()\">\n {{ 'dashboard.officeProfileEdit.pending.viewRequests' | translate }}\n </button>\n <button type=\"button\" class=\"cancelButton\" (click)=\"viewProfile.emit()\">\n {{ 'dashboard.officeProfileEdit.pending.backHome' | translate }}\n </button>\n </div>\n }\n </section>\n</div>\n", styles: [":host{display:block}\n"] }]
11245
11418
  }], propDecorators: { result: [{ type: i0.Input, args: [{ isSignal: true, alias: "result", required: true }] }], viewProfile: [{ type: i0.Output, args: ["viewProfile"] }], viewRequests: [{ type: i0.Output, args: ["viewRequests"] }] } });
11246
11419
 
11420
+ /** Static banner telling the user their office-profile update is awaiting review, with a link to the requests page; it takes no inputs. */
11247
11421
  class ScePendingUpdateBannerComponent {
11248
11422
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ScePendingUpdateBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11249
11423
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.17", type: ScePendingUpdateBannerComponent, isStandalone: true, selector: "sce-pending-update-banner", host: { classAttribute: "sce-pending-update-banner" }, ngImport: i0, template: "<div class=\"pendingBanner\" role=\"alert\">\n <div class=\"pendingBannerIcon\" aria-hidden=\"true\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"10\" fill=\"var(--color-yellow-100)\" />\n <path d=\"M10 6v5M10 13v1\" stroke=\"var(--color-warning-700)\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </div>\n <div class=\"pendingBannerBody\">\n <p class=\"pendingBannerTitle\">\n {{ 'dashboard.officeProfileEdit.pendingBannerTitle' | translate }}\n </p>\n <p class=\"pendingBannerText\">\n {{ 'dashboard.officeProfileEdit.pendingBannerBody' | translate }}\n </p>\n </div>\n <a routerLink=\"/dashboard/data-requests\" class=\"pendingBannerLink\">\n {{ 'dashboard.officeProfileEdit.pendingBannerViewRequest' | translate }}\n </a>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -11253,6 +11427,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11253
11427
  args: [{ selector: 'sce-pending-update-banner', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-pending-update-banner' }, imports: [TranslatePipe, RouterLink], template: "<div class=\"pendingBanner\" role=\"alert\">\n <div class=\"pendingBannerIcon\" aria-hidden=\"true\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <circle cx=\"10\" cy=\"10\" r=\"10\" fill=\"var(--color-yellow-100)\" />\n <path d=\"M10 6v5M10 13v1\" stroke=\"var(--color-warning-700)\" stroke-width=\"2\" stroke-linecap=\"round\" />\n </svg>\n </div>\n <div class=\"pendingBannerBody\">\n <p class=\"pendingBannerTitle\">\n {{ 'dashboard.officeProfileEdit.pendingBannerTitle' | translate }}\n </p>\n <p class=\"pendingBannerText\">\n {{ 'dashboard.officeProfileEdit.pendingBannerBody' | translate }}\n </p>\n </div>\n <a routerLink=\"/dashboard/data-requests\" class=\"pendingBannerLink\">\n {{ 'dashboard.officeProfileEdit.pendingBannerViewRequest' | translate }}\n </a>\n</div>\n", styles: [":host{display:block}\n"] }]
11254
11428
  }] });
11255
11429
 
11430
+ /** Bio section of the office-profile edit form, binding the parent's `FormGroup` to the summary field, the services multi-select and the availability select. */
11256
11431
  class SceOfficeProfileEditBioSectionComponent {
11257
11432
  form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
11258
11433
  serviceOptions = input.required(...(ngDevMode ? [{ debugName: "serviceOptions" }] : /* istanbul ignore next */ []));
@@ -11266,6 +11441,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11266
11441
  args: [{ selector: 'sce-office-profile-edit-bio-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-edit-bio-section' }, imports: [TranslatePipe, ReactiveFormsModule, SceMultiSelectFieldComponent, SceSelectFieldComponent], template: "<section class=\"editFormSection\" [formGroup]=\"form()\">\n <h3 class=\"editFormSectionTitle\">\n {{ 'dashboard.officeProfileEdit.bioAndServices' | translate }}\n </h3>\n\n <div class=\"editFormFields\">\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-summary\">\n {{ 'dashboard.officeProfileEdit.officeSummary' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <textarea\n id=\"office-summary\"\n class=\"editFormTextarea\"\n formControlName=\"summary\"\n rows=\"4\"\n [placeholder]=\"'dashboard.officeProfileEdit.summaryPlaceholder' | translate\"\n ></textarea>\n @if (form().controls['summary'].errors?.['maxlength'] && form().controls['summary'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.MAX_LENGTH' | translate: { max: 2000 } }}\n </span>\n }\n @if (form().controls['summary'].errors?.['required'] && form().controls['summary'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.REQUIRED' | translate }}\n </span>\n }\n </div>\n\n <sce-multi-select-field\n id=\"serviceIds\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"('dashboard.officeProfileEdit.services' | translate) + ' ' + ('dashboard.officeProfileEdit.servicesHint' | translate)\"\n [options]=\"serviceOptions()\"\n [value]=\"form().controls['serviceIds'].value\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [showClear]=\"false\"\n [required]=\"true\"\n [minSelected]=\"1\"\n [maxSelected]=\"10\"\n [placeholder]=\"'COMMON.CHOOSE' | translate\"\n (valueChange)=\"form().controls['serviceIds'].setValue($event)\"\n [containerClassName]=\"''\"\n />\n\n <sce-select-field\n id=\"availabilityStatus\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"'dashboard.officeProfileEdit.availabilityStatus' | translate\"\n [options]=\"availabilityOptions()\"\n [value]=\"form().controls['availabilityStatus'].value\"\n [dir]=\"dir()\"\n [required]=\"true\"\n [showClear]=\"true\"\n [placeholder]=\"'COMMON.CHOOSE' | translate\"\n (valueChange)=\"form().controls['availabilityStatus'].setValue($event ?? '')\"\n [containerClassName]=\"''\"\n />\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
11267
11442
  }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], serviceOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "serviceOptions", required: true }] }], availabilityOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "availabilityOptions", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }] } });
11268
11443
 
11444
+ /** Media section of the office-profile edit form, with file-upload zones for the cover image and logo; the busy and error states come from the parent's save request rather than from an upload of its own. */
11269
11445
  class SceOfficeProfileEditMediaSectionComponent {
11270
11446
  locale = input('ar', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
11271
11447
  coverExistingUrl = input('', ...(ngDevMode ? [{ debugName: "coverExistingUrl" }] : /* istanbul ignore next */ []));
@@ -11286,6 +11462,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11286
11462
  args: [{ selector: 'sce-office-profile-edit-media-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-edit-media-section' }, imports: [TranslatePipe, SceFileUploadZoneComponent], template: "<section class=\"card\">\n <div class=\"section withDivider\">\n <h3 class=\"sectionTitle editFormSectionTitle\">\n {{ 'dashboard.officeProfileEdit.logoAndCover' | translate }}\n </h3>\n <div class=\"uploadGrid\">\n <div class=\"formField\">\n <sce-file-upload-zone\n [locale]=\"locale()\"\n [accept]=\"'.pdf,.png,.jpg,.jpeg'\"\n [label]=\"'dashboard.officeProfileEdit.cover' | translate\"\n [description]=\"'dashboard.officeProfileEdit.uploadCoverHint' | translate\"\n [uploading]=\"uploading()\"\n [uploadError]=\"uploadError()\"\n [existingItems]=\"\n coverExistingUrl() && !coverFile()\n ? [{ id: 'cover', url: coverExistingUrl(), alt: ('dashboard.officeProfileEdit.cover' | translate) }]\n : []\n \"\n (fileChange)=\"coverChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField\">\n <sce-file-upload-zone\n [locale]=\"locale()\"\n [accept]=\"'.pdf,.png,.jpg,.jpeg'\"\n [label]=\"'dashboard.officeProfileEdit.logo' | translate\"\n [description]=\"'dashboard.officeProfileEdit.uploadBrandHint' | translate\"\n [uploading]=\"uploading()\"\n [uploadError]=\"uploadError()\"\n [existingItems]=\"\n logoExistingUrl() && !logoFile()\n ? [{ id: 'logo', url: logoExistingUrl(), alt: ('dashboard.officeProfileEdit.logo' | translate) }]\n : []\n \"\n (fileChange)=\"logoChange.emit($event)\"\n />\n </div>\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
11287
11463
  }], propDecorators: { locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], coverExistingUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "coverExistingUrl", required: false }] }], coverFile: [{ type: i0.Input, args: [{ isSignal: true, alias: "coverFile", required: false }] }], logoExistingUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoExistingUrl", required: false }] }], logoFile: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoFile", required: false }] }], uploading: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploading", required: false }] }], uploadError: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadError", required: false }] }], coverChange: [{ type: i0.Output, args: ["coverChange"] }], logoChange: [{ type: i0.Output, args: ["logoChange"] }] } });
11288
11464
 
11465
+ /** Official-data section of the office-profile edit form, binding the parent's `FormGroup` to the bank, city and preferred-project-size selects plus the geo-location picker. */
11289
11466
  class SceOfficeProfileEditOfficialSectionComponent {
11290
11467
  form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
11291
11468
  bankOptions = input.required(...(ngDevMode ? [{ debugName: "bankOptions" }] : /* istanbul ignore next */ []));
@@ -11310,6 +11487,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
11310
11487
  ], template: "<section class=\"editFormSection\" [formGroup]=\"form()\">\n <h3 class=\"editFormSectionTitle\">\n {{ 'dashboard.officeProfileEdit.officialData' | translate }}\n </h3>\n\n <div class=\"editFormGrid\">\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-vat\">\n {{ 'dashboard.officeProfileEdit.taxRegNo' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-vat\"\n type=\"text\"\n dir=\"ltr\"\n class=\"editFormInput\"\n formControlName=\"vatRegistrationNumber\"\n inputmode=\"numeric\"\n maxlength=\"15\"\n [placeholder]=\"'dashboard.officeProfileEdit.taxRegPlaceholder' | translate\"\n />\n </div>\n\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-cr\">\n {{ 'dashboard.officeProfileEdit.unifiedNumber' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-cr\"\n type=\"text\"\n dir=\"ltr\"\n class=\"editFormInput\"\n formControlName=\"crNationalNumber\"\n inputmode=\"numeric\"\n [placeholder]=\"'dashboard.officeProfileEdit.unifiedNoPlaceholder' | translate\"\n />\n </div>\n\n <sce-select-field\n id=\"bankName\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"'dashboard.officeProfileEdit.bank' | translate\"\n [options]=\"bankOptions()\"\n [value]=\"form().controls['bankName'].value\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [required]=\"true\"\n [showClear]=\"false\"\n [placeholder]=\"'dashboard.officeProfileEdit.selectBank' | translate\"\n (valueChange)=\"form().controls['bankName'].setValue($event ?? '')\"\n />\n\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-short-address\">\n {{ 'dashboard.officeProfileEdit.shortNationalAddress' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-short-address\"\n type=\"text\"\n dir=\"ltr\"\n class=\"editFormInput\"\n formControlName=\"shortNationalAddress\"\n maxlength=\"8\"\n [placeholder]=\"'dashboard.officeProfileEdit.shortAddressPlaceholder' | translate\"\n />\n </div>\n\n <div class=\"editFormControl editFormControl--full\">\n <label class=\"editFormLabel\" for=\"office-iban\">\n {{ 'dashboard.officeProfileEdit.iban' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <!-- IBANs always read left-to-right: \"SA\" prefix then digits \u2014 keep the whole row LTR. -->\n <div class=\"editFormInputWithPrefix\" dir=\"ltr\">\n <span class=\"editFormInputPrefix\" aria-hidden=\"true\">SA</span>\n <input\n id=\"office-iban\"\n type=\"text\"\n dir=\"ltr\"\n class=\"editFormInput editFormInput--prefixed\"\n formControlName=\"iban\"\n maxlength=\"22\"\n [placeholder]=\"'dashboard.officeProfileEdit.ibanPlaceholder' | translate\"\n (input)=\"ibanInput.emit($event)\"\n />\n </div>\n </div>\n\n <div class=\"editFormControl editFormControl--full\">\n @defer (on idle) {\n <sce-geo-location-field\n [label]=\"'dashboard.officeProfileEdit.geoLocation'\"\n [value]=\"geoLocation()\"\n [locale]=\"locale()\"\n (valueChange)=\"locationSelect.emit($event)\"\n />\n } @placeholder {\n <div class=\"editFormInput editFormInput--skeleton\" aria-hidden=\"true\"></div>\n }\n </div>\n\n <div class=\"editFormControl editFormControl--full\">\n <label class=\"editFormLabel\" for=\"office-address\">\n {{ 'dashboard.officeProfileEdit.officeAddress' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input id=\"office-address\" type=\"text\" class=\"editFormInput\" formControlName=\"address\" />\n </div>\n\n <sce-select-field\n id=\"cityID\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"'dashboard.officeProfileEdit.city' | translate\"\n [options]=\"cityOptions()\"\n [value]=\"form().controls['cityID'].value\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [required]=\"true\"\n [showClear]=\"false\"\n [placeholder]=\"'dashboard.officeProfileEdit.selectCity' | translate\"\n (valueChange)=\"form().controls['cityID'].setValue($event ?? '')\"\n />\n\n <sce-multi-select-field\n id=\"preferredProjectSizes\"\n labelClassName=\"editFormLabel\"\n fieldClassName=\"editFormFieldWrap\"\n [label]=\"'dashboard.officeProfileEdit.preferredProjectSizes' | translate\"\n [options]=\"preferredSizeOptions()\"\n [value]=\"form().controls['preferredProjectSizes'].value\"\n [dir]=\"dir()\"\n [required]=\"true\"\n [maxSelected]=\"3\"\n [showClear]=\"false\"\n [placeholder]=\"'COMMON.CHOOSE' | translate\"\n (valueChange)=\"form().controls['preferredProjectSizes'].setValue($event)\"\n [containerClassName]=\"''\"\n />\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
11311
11488
  }], ctorParameters: null, propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], bankOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankOptions", required: true }] }], cityOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "cityOptions", required: true }] }], preferredSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredSizeOptions", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], geoLocation: [{ type: i0.Input, args: [{ isSignal: true, alias: "geoLocation", required: false }] }], locationSelect: [{ type: i0.Output, args: ["locationSelect"] }], ibanInput: [{ type: i0.Output, args: ["ibanInput"] }] } }) });
11312
11489
 
11490
+ /** Contact section of the office-profile edit form, binding the parent's `FormGroup` to the contact detail inputs. */
11313
11491
  class SceOfficeProfileEditContactSectionComponent {
11314
11492
  form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
11315
11493
  dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
@@ -11321,6 +11499,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11321
11499
  args: [{ selector: 'sce-office-profile-edit-contact-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-edit-contact-section' }, imports: [TranslatePipe, ReactiveFormsModule], template: "<section class=\"editFormSection\" [formGroup]=\"form()\">\n <h3 class=\"editFormSectionTitle\">\n {{ 'dashboard.officeProfileEdit.contactInfo' | translate }}\n </h3>\n\n <div class=\"editFormGrid\">\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-phone\">\n {{ 'dashboard.officeProfileEdit.phone' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-phone\"\n type=\"tel\"\n class=\"editFormInput\"\n formControlName=\"phone\"\n inputmode=\"tel\"\n [placeholder]=\"'dashboard.officeProfileEdit.phonePlaceholder' | translate\"\n />\n @if (form().controls['phone'].invalid && form().controls['phone'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.REQUIRED' | translate }}\n </span>\n }\n </div>\n\n <div class=\"editFormControl\">\n <label class=\"editFormLabel\" for=\"office-email\">\n {{ 'dashboard.officeProfileEdit.email' | translate }}\n <span class=\"editFormRequired\" aria-hidden=\"true\">*</span>\n </label>\n <input\n id=\"office-email\"\n type=\"email\"\n class=\"editFormInput\"\n formControlName=\"email\"\n inputmode=\"email\"\n [placeholder]=\"'dashboard.officeProfileEdit.emailPlaceholder' | translate\"\n />\n @if (form().controls['email'].invalid && form().controls['email'].touched) {\n <span class=\"formError\" role=\"alert\">\n @if (form().controls['email'].errors?.['required']) {\n {{ 'VALIDATION.REQUIRED' | translate }}\n } @else if (form().controls['email'].errors?.['email']) {\n {{ 'VALIDATION.EMAIL' | translate }}\n }\n </span>\n }\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
11322
11500
  }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }] } });
11323
11501
 
11502
+ /** Projects section of the office-profile edit form, listing each project as a hero image with up to two thumbnails and emitting add, edit and delete requests by list index. */
11324
11503
  class SceOfficeProfileEditProjectsSectionComponent {
11325
11504
  projects = input.required(...(ngDevMode ? [{ debugName: "projects" }] : /* istanbul ignore next */ []));
11326
11505
  addProject = output();
@@ -11339,6 +11518,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11339
11518
  args: [{ selector: 'sce-office-profile-edit-projects-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-edit-projects-section' }, imports: [TranslatePipe], template: "<section class=\"card\">\n <div class=\"section withDivider\">\n <div class=\"projectsEditHeader\">\n <h3 class=\"sectionTitle\">\n {{ 'dashboard.officeProfileEdit.projectsManagement' | translate }}\n </h3>\n <button type=\"button\" class=\"addProjectBtn\" (click)=\"addProject.emit()\">\n <span aria-hidden=\"true\">+</span>\n {{ 'dashboard.officeProfileEdit.addProject' | translate }}\n </button>\n </div>\n\n <div class=\"editProjectList\">\n @for (project of projectsView(); track project.id) {\n <div class=\"editProjectRow\">\n <div class=\"editProjectGallery\" dir=\"ltr\" aria-hidden=\"true\">\n <div class=\"editProjectGalleryMain\">\n @if (project.heroUrl) {\n <img [src]=\"project.heroUrl\" alt=\"\" class=\"editProjectGalleryMainImg\" loading=\"lazy\" />\n }\n </div>\n @if (project.thumbUrls.length > 0) {\n <div class=\"editProjectGalleryStack\">\n @for (thumb of project.thumbUrls; track thumb) {\n <img [src]=\"thumb\" alt=\"\" class=\"editProjectGalleryThumb\" loading=\"lazy\" />\n }\n </div>\n }\n </div>\n\n <div class=\"editProjectInfo\">\n <p class=\"editProjectCardTitle\">{{ project.titleAr }}</p>\n <div class=\"editProjectMeta\">\n <span\n class=\"projectBadge\"\n [class.projectBadgeCompleted]=\"project.isCompleted\"\n [class.projectBadgeInProgress]=\"!project.isCompleted\"\n >\n @if (project.isCompleted) {\n {{ 'dashboard.officeProfileEdit.completed' | translate }}\n } @else {\n {{ 'dashboard.officeProfileEdit.inProgress' | translate }}\n }\n </span>\n @if (project.typeLabel) {\n <span class=\"editProjectMetaSep\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"editProjectCategory\">{{ project.typeLabel }}</span>\n }\n </div>\n </div>\n\n <div class=\"editProjectActions\" dir=\"ltr\">\n <button\n type=\"button\"\n class=\"editProjectIconBtn\"\n [attr.aria-label]=\"'dashboard.officeProfileEdit.editProjectAction' | translate\"\n (click)=\"editProject.emit(project.id)\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"editProjectIconBtn\"\n [attr.aria-label]=\"'dashboard.officeProfileEdit.deleteProjectAction' | translate\"\n (click)=\"deleteProject.emit(project.id)\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6\" />\n <path d=\"M10 11v6M14 11v6\" />\n <path d=\"M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2\" />\n </svg>\n </button>\n </div>\n </div>\n } @empty {\n <p class=\"editProjectEmptyMsg\">\n {{ 'dashboard.officeProfileEdit.noProjects' | translate }}\n </p>\n }\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
11340
11519
  }], propDecorators: { projects: [{ type: i0.Input, args: [{ isSignal: true, alias: "projects", required: true }] }], addProject: [{ type: i0.Output, args: ["addProject"] }], editProject: [{ type: i0.Output, args: ["editProject"] }], deleteProject: [{ type: i0.Output, args: ["deleteProject"] }] } });
11341
11520
 
11521
+ /** Dialog for adding or editing an office project, binding the parent's project `FormGroup` alongside an image upload zone whose minimum image count defaults to three. */
11342
11522
  class SceOfficeProfileProjectEditorDialogComponent {
11343
11523
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
11344
11524
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
@@ -11362,6 +11542,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11362
11542
  args: [{ selector: 'sce-office-profile-project-editor-dialog', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-project-editor-dialog' }, imports: [TranslatePipe, ReactiveFormsModule, Dialog, Button, SceSelectFieldComponent, SceFileUploadZoneComponent], template: "<p-dialog\n [visible]=\"visible()\"\n (visibleChange)=\"!$event && closeDialog.emit()\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [style]=\"{ width: '580px', maxWidth: '95vw' }\"\n [header]=\"title()\"\n [closeAriaLabel]=\"'COMMON.CLOSE' | translate\"\n appendTo=\"body\"\n styleClass=\"sce-project-dialog\"\n>\n <ng-template #content>\n <p class=\"projectDialogSubtitle\">{{ subtitle() }}</p>\n\n <form [formGroup]=\"projectForm()\">\n <div class=\"formField\" style=\"margin-block-end: var(--space-16)\">\n <label class=\"formLabel\" for=\"proj-name\">\n {{ 'dashboard.officeProfileEdit.projectName' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"proj-name\"\n type=\"text\"\n class=\"formInput\"\n formControlName=\"name\"\n maxlength=\"200\"\n [placeholder]=\"'dashboard.officeProfileEdit.projectNamePlaceholder' | translate\"\n />\n @if (projectForm().controls['name'].invalid && projectForm().controls['name'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.REQUIRED' | translate }}\n </span>\n }\n </div>\n\n @if (projectCategoryOptions().length > 0) {\n <div class=\"formField\" style=\"margin-block-end: var(--space-16)\">\n <sce-select-field\n id=\"proj-category\"\n [label]=\"'dashboard.officeProfileEdit.projectCategory' | translate\"\n [options]=\"projectCategoryOptions()\"\n [value]=\"projectForm().controls['category'].value\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [placeholder]=\"'dashboard.officeProfileEdit.projectCategoryPlaceholder' | translate\"\n (valueChange)=\"projectForm().controls['category'].setValue($event ?? '')\"\n />\n </div>\n }\n\n <div class=\"formField\" style=\"margin-block-end: var(--space-16)\">\n <sce-select-field\n id=\"proj-status\"\n [label]=\"'dashboard.officeProfileEdit.projectStatus' | translate\"\n [options]=\"projectStatusOptions()\"\n [value]=\"projectForm().controls['status'].value\"\n [dir]=\"dir()\"\n [showClear]=\"false\"\n (valueChange)=\"projectForm().controls['status'].setValue($event === 'completed' ? 'completed' : 'inprogress')\"\n />\n </div>\n\n <div class=\"formField\" style=\"margin-block-end: var(--space-16)\">\n <label class=\"formLabel\" for=\"proj-desc\">\n {{ 'dashboard.officeProfileEdit.projectDescription' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <textarea\n id=\"proj-desc\"\n class=\"formTextarea\"\n formControlName=\"description\"\n rows=\"4\"\n maxlength=\"2000\"\n [placeholder]=\"'dashboard.officeProfileEdit.projectDescriptionPlaceholder' | translate\"\n ></textarea>\n @if (projectForm().controls['description'].invalid && projectForm().controls['description'].touched) {\n <span class=\"formError\" role=\"alert\">\n {{ 'VALIDATION.REQUIRED' | translate }}\n </span>\n }\n </div>\n\n <div class=\"formField\">\n <span class=\"formLabel\">\n {{ 'dashboard.officeProfileEdit.projectImages' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </span>\n <sce-file-upload-zone\n [locale]=\"locale()\"\n [multiple]=\"true\"\n [maxFiles]=\"10\"\n [accept]=\"'.png,.jpg,.jpeg'\"\n [label]=\"'dashboard.officeProfileEdit.projectImagesRequired' | translate\"\n [description]=\"'dashboard.officeProfileEdit.projectImagesHint' | translate: { count: projectMinImageCount() }\"\n [showPreviews]=\"true\"\n [variant]=\"'dialog'\"\n (filesChange)=\"filesChange.emit($event)\"\n />\n @if (projectError()) {\n <span class=\"formError\" role=\"alert\">{{ projectError() }}</span>\n }\n </div>\n </form>\n </ng-template>\n\n <ng-template #footer>\n <p-button [label]=\"'dashboard.officeProfileEdit.cancel' | translate\" severity=\"secondary\" (onClick)=\"closeDialog.emit()\" />\n <!-- severity=\"contrast\": the raw preset primary (#10b981) fails AA contrast at 2.53:1\n with white label text. -->\n <p-button [label]=\"saveLabel()\" severity=\"contrast\" (onClick)=\"saveProject.emit()\" />\n </ng-template>\n</p-dialog>\n", styles: [":host{display:block}\n"] }]
11363
11543
  }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: true }] }], projectForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectForm", required: true }] }], projectCategoryOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectCategoryOptions", required: false }] }], projectStatusOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectStatusOptions", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], projectError: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectError", required: false }] }], saveLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveLabel", required: true }] }], projectMinImageCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectMinImageCount", required: false }] }], closeDialog: [{ type: i0.Output, args: ["closeDialog"] }], saveProject: [{ type: i0.Output, args: ["saveProject"] }], filesChange: [{ type: i0.Output, args: ["filesChange"] }] } });
11364
11544
 
11545
+ /** Confirmation dialog asking the user to confirm deleting an office project. */
11365
11546
  class SceOfficeProfileProjectDeleteDialogComponent {
11366
11547
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
11367
11548
  closeDialog = output();
@@ -11374,6 +11555,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11374
11555
  args: [{ selector: 'sce-office-profile-project-delete-dialog', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-office-profile-project-delete-dialog' }, imports: [TranslatePipe, Dialog, Button], template: "<p-dialog\n [visible]=\"visible()\"\n (visibleChange)=\"!$event && closeDialog.emit()\"\n [modal]=\"true\"\n [draggable]=\"false\"\n [resizable]=\"false\"\n [style]=\"{ width: '440px', maxWidth: '95vw' }\"\n [header]=\"'dashboard.officeProfileEdit.deleteProjectConfirmTitle' | translate\"\n [closeAriaLabel]=\"'COMMON.CLOSE' | translate\"\n styleClass=\"sce-project-dialog\"\n>\n <ng-template #content>\n <p style=\"margin: 0; color: var(--text-text-secondary-700); line-height: 1.6\">\n {{ 'dashboard.officeProfileEdit.deleteProjectConfirmBody' | translate }}\n </p>\n </ng-template>\n\n <ng-template #footer>\n <p-button [label]=\"'dashboard.officeProfileEdit.cancel' | translate\" severity=\"secondary\" (onClick)=\"closeDialog.emit()\" />\n <p-button [label]=\"'dashboard.officeProfileEdit.deleteProject' | translate\" severity=\"danger\" (onClick)=\"confirmDelete.emit()\" />\n </ng-template>\n</p-dialog>\n", styles: [":host{display:block}\n"] }]
11375
11556
  }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], closeDialog: [{ type: i0.Output, args: ["closeDialog"] }], confirmDelete: [{ type: i0.Output, args: ["confirmDelete"] }] } });
11376
11557
 
11558
+ /** Hero header of the office profile view — banner, logo, name, city, rating and verification badge — plus the profile's tab bar and an optional active/inactive status switch. */
11377
11559
  class SceOfficeProfileHeroComponent {
11378
11560
  bannerUrl = input(null, ...(ngDevMode ? [{ debugName: "bannerUrl" }] : /* istanbul ignore next */ []));
11379
11561
  logoUrl = input(null, ...(ngDevMode ? [{ debugName: "logoUrl" }] : /* istanbul ignore next */ []));
@@ -11406,6 +11588,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11406
11588
  args: [{ selector: 'sce-office-profile-hero', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-hero' }, imports: [TranslatePipe, SceEngineeringOfficeVerificationBadgeComponent, SceSwitchComponent], template: "<section class=\"card\">\n <!-- Hero + Logo -->\n <div class=\"heroWrap\">\n <div class=\"heroCoverPlaceholder\" aria-hidden=\"true\">\n @if (bannerUrl()) {\n <img [src]=\"bannerUrl()\" alt=\"\" class=\"heroCoverImage\" loading=\"lazy\" />\n } @else {\n <img src=\"/assets/icons/building-03.svg\" width=\"48\" height=\"48\" alt=\"\" />\n }\n </div>\n <div class=\"heroLogo\">\n <div class=\"logoPlaceholder\" aria-hidden=\"true\">\n @if (logoUrl()) {\n <img [src]=\"logoUrl()\" alt=\"\" class=\"logoImage\" loading=\"lazy\" />\n } @else {\n <img src=\"/assets/icons/office1.svg\" width=\"56\" height=\"56\" alt=\"\" aria-hidden=\"true\" />\n }\n </div>\n </div>\n </div>\n\n <!-- Update data button / system-user status switch -->\n <div class=\"updateDataRow\">\n @if (showOfficeStatusSwitch()) {\n <sce-switch\n [checked]=\"officeIsActive()\"\n [disabled]=\"officeStatusSaving()\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.individualUsers.status.active' | translate\"\n [inactiveLabel]=\"'dashboard.individualUsers.status.inactive' | translate\"\n (checkedChange)=\"statusChange.emit($event)\"\n />\n } @else {\n <button type=\"button\" class=\"updateDataBtn\" (click)=\"updateDataClick.emit()\" [disabled]=\"updateDataChecking()\">\n @if (updateDataChecking()) {\n {{ 'dashboard.officeProfile.incompleteAlert.checking' | translate }}\n } @else {\n {{ 'dashboard.officeProfile.actions.updateData' | translate }}\n }\n </button>\n }\n </div>\n\n <!-- Office name & badges -->\n <div class=\"officeIdentity\">\n <div class=\"officeNameRow\">\n <sce-engineering-office-verification-badge [status]=\"verificationStatus()\" [size]=\"22\" />\n <h2 class=\"officeName\">{{ officeName() || '\u2014' }}</h2>\n </div>\n <div class=\"officeBadgesRow\">\n <span class=\"badgeLocation\">\uD83D\uDCCD{{ cityName() || '\u2014' }}</span>\n <span class=\"badgeRating\">\uD83C\uDFC6 {{ 'dashboard.officeProfile.verified' | translate }}</span>\n <span class=\"badgeRating\"> \u2B50{{ rating() }} ({{ ratingCount() }}) {{ 'dashboard.officeProfile.rating' | translate }} </span>\n @if (isAvailable()) {\n <span class=\"badgeAvailable\">\n <span class=\"availableDot\" aria-hidden=\"true\"></span>\n {{ 'dashboard.officeProfile.available' | translate }}\n </span>\n }\n </div>\n </div>\n\n <!-- Tab bar -->\n <div class=\"tabs\">\n @for (tab of tabKeys(); track tab) {\n <button type=\"button\" class=\"tab\" [class.tabActive]=\"activeTab() === tab\" (click)=\"tabChange.emit(tab)\">\n {{ tabLabels()[tab] }}\n </button>\n }\n </div>\n <div class=\"tabsContentDivider\"></div>\n</section>\n", styles: [":host{display:block}\n"] }]
11407
11589
  }], propDecorators: { bannerUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "bannerUrl", required: false }] }], logoUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoUrl", required: false }] }], officeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeName", required: false }] }], cityName: [{ type: i0.Input, args: [{ isSignal: true, alias: "cityName", required: false }] }], rating: [{ type: i0.Input, args: [{ isSignal: true, alias: "rating", required: false }] }], ratingCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingCount", required: false }] }], isAvailable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isAvailable", required: false }] }], verificationStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "verificationStatus", required: false }] }], showOfficeStatusSwitch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOfficeStatusSwitch", required: false }] }], officeIsActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeIsActive", required: false }] }], officeStatusSaving: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeStatusSaving", required: false }] }], updateDataChecking: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateDataChecking", required: false }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }], tabKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabKeys", required: false }] }], tabLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabLabels", required: false }] }], updateDataClick: [{ type: i0.Output, args: ["updateDataClick"] }], statusChange: [{ type: i0.Output, args: ["statusChange"] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }] } });
11408
11590
 
11591
+ /** Row of headline office statistics: years of experience, project count and service count. */
11409
11592
  class SceOfficeProfileStatsRowComponent {
11410
11593
  yearsOfExperience = input('—', ...(ngDevMode ? [{ debugName: "yearsOfExperience" }] : /* istanbul ignore next */ []));
11411
11594
  projectsCount = input(0, ...(ngDevMode ? [{ debugName: "projectsCount" }] : /* istanbul ignore next */ []));
@@ -11418,6 +11601,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11418
11601
  args: [{ selector: 'sce-office-profile-stats-row', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-stats-row' }, imports: [TranslatePipe], template: "<div class=\"statsRow\">\n <div class=\"metricCard\">\n <div class=\"metricIcon\">\n <img src=\"/assets/icons/audit-01-alt.svg\" width=\"28\" height=\"28\" alt=\"\" />\n </div>\n <div class=\"metricText\">\n <p class=\"metricValue\">{{ yearsOfExperience() }}</p>\n <p class=\"metricLabel\">{{ 'dashboard.officeProfile.yearsExperience' | translate }}</p>\n </div>\n </div>\n <div class=\"metricCard\">\n <div class=\"metricIcon\">\n <img src=\"/assets/icons/building-03.svg\" width=\"28\" height=\"28\" alt=\"\" />\n </div>\n <div class=\"metricText\">\n <p class=\"metricValue\">{{ projectsCount() }}</p>\n <p class=\"metricLabel\">{{ 'dashboard.officeProfile.projectsMetric' | translate }}</p>\n </div>\n </div>\n <div class=\"metricCard\">\n <div class=\"metricIcon\">\n <img src=\"/assets/icons/calendar-04-alt.svg\" width=\"28\" height=\"28\" alt=\"\" aria-hidden=\"true\" />\n </div>\n <div class=\"metricText\">\n <p class=\"metricValue\">{{ servicesCount() }}</p>\n <p class=\"metricLabel\">{{ 'dashboard.officeProfile.servicesMetric' | translate }}</p>\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
11419
11602
  }], propDecorators: { yearsOfExperience: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearsOfExperience", required: false }] }], projectsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectsCount", required: false }] }], servicesCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "servicesCount", required: false }] }] } });
11420
11603
 
11604
+ /** Overview tab of the office profile view, showing the summary, services, license number, expiry and status, and office type as info-field cards. */
11421
11605
  class SceOfficeProfileOverviewTabComponent {
11422
11606
  summary = input('', ...(ngDevMode ? [{ debugName: "summary" }] : /* istanbul ignore next */ []));
11423
11607
  servicesDisplay = input([], ...(ngDevMode ? [{ debugName: "servicesDisplay" }] : /* istanbul ignore next */ []));
@@ -11433,6 +11617,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11433
11617
  args: [{ selector: 'sce-office-profile-overview-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-overview-tab' }, imports: [TranslatePipe, SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<section class=\"card overviewCard\">\n <div class=\"overviewSection\">\n <h3 class=\"overviewSectionTitle\">{{ 'dashboard.officeProfile.aboutOffice' | translate }}</h3>\n <p class=\"overviewSummaryText\">{{ summary() || '\u2014' }}</p>\n </div>\n <div class=\"overviewSectionDivider\"></div>\n <div class=\"overviewSection\">\n <h3 class=\"overviewSectionTitle\">{{ 'dashboard.officeProfile.servicesProvided' | translate }}</h3>\n @if (servicesDisplay().length > 0) {\n <div class=\"overviewServicesChips\">\n @for (service of servicesDisplay(); track service) {\n <span class=\"overviewServiceChip\">{{ service }}</span>\n }\n </div>\n }\n </div>\n</section>\n\n<section class=\"card overviewCard\">\n <div class=\"section withDivider overviewSection\">\n <h3 class=\"sectionTitle overviewSectionTitle\">{{ 'dashboard.officeProfile.licenseInfo' | translate }}</h3>\n <sce-info-fields-grid gap=\"sm\" class=\"overviewInfoFieldsGrid\">\n <sce-info-field-card [label]=\"'dashboard.officeProfile.licenseNumber' | translate\" [value]=\"licenseNumber() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.licenseExpiry' | translate\" [value]=\"licenseExpiryFormatted()\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.licenseStatus' | translate\" [value]=\"licenseStatus()\" />\n @if (officeTypeDisplay()) {\n <sce-info-field-card [label]=\"'dashboard.officeProfile.officeType' | translate\" [value]=\"officeTypeDisplay()\" [fullWidth]=\"true\" />\n }\n </sce-info-fields-grid>\n </div>\n</section>\n", styles: [":host{display:contents}\n"] }]
11434
11618
  }], propDecorators: { summary: [{ type: i0.Input, args: [{ isSignal: true, alias: "summary", required: false }] }], servicesDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "servicesDisplay", required: false }] }], licenseNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "licenseNumber", required: false }] }], licenseExpiryFormatted: [{ type: i0.Input, args: [{ isSignal: true, alias: "licenseExpiryFormatted", required: false }] }], licenseStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "licenseStatus", required: false }] }], officeTypeDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeTypeDisplay", required: false }] }] } });
11435
11619
 
11620
+ /** Projects tab of the office profile view, rendering each project with its image gallery and showing skeletons while the project images load. */
11436
11621
  class SceOfficeProfileProjectsTabComponent {
11437
11622
  displayProjects = input([], ...(ngDevMode ? [{ debugName: "displayProjects" }] : /* istanbul ignore next */ []));
11438
11623
  projectImagesLoading = input(false, ...(ngDevMode ? [{ debugName: "projectImagesLoading" }] : /* istanbul ignore next */ []));
@@ -11445,6 +11630,7 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.17", n
11445
11630
  args: [{ selector: 'sce-office-profile-projects-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-projects-tab' }, imports: [TranslatePipe, SceSkeleton, SceOfficeProjectGalleryComponent], template: "<section class=\"card\">\n <div class=\"section\">\n <h3 class=\"sectionTitle\">{{ 'dashboard.officeProfile.projectsList' | translate }}</h3>\n <div class=\"projectList\">\n @if (displayProjects().length === 0) {\n <p class=\"emptyText\">{{ 'dashboard.officeProfile.noProjects' | translate }}</p>\n }\n @for (proj of displayProjects(); track proj.id) {\n <article class=\"projectCard\">\n <div class=\"projectCardTop\">\n <div class=\"projectCardHeader\">\n @if (proj.typeLabel) {\n <span class=\"projectCategoryBadge\">{{ proj.typeLabel }}</span>\n }\n <h4 class=\"projectCardTitle\">{{ proj.title || '\u2014' }}</h4>\n </div>\n <span\n class=\"projectStatusBadge\"\n [class.projectStatusCompleted]=\"proj.isCompleted\"\n [class.projectStatusInProgress]=\"!proj.isCompleted\"\n >\n @if (proj.isCompleted) {\n {{ 'dashboard.officeProfile.projectStatusCompleted' | translate }}\n } @else {\n {{ 'dashboard.officeProfile.projectStatusInProgress' | translate }}\n }\n </span>\n </div>\n\n <div class=\"projectCardBody\" [class.projectCardBodySingle]=\"proj.imageUrls.length === 0 && !projectImagesLoading()\">\n @if (proj.imageUrls.length > 0) {\n @defer (on viewport) {\n <sce-office-project-gallery [imageUrls]=\"proj.imageUrls\" [title]=\"proj.title\" [locale]=\"locale()\" [pending]=\"false\" />\n } @placeholder {\n <sce-skeleton variant=\"image\" aspectRatio=\"16/9\" animation=\"wave\" aria-hidden=\"true\" />\n }\n } @else if (projectImagesLoading()) {\n <sce-skeleton variant=\"image\" aspectRatio=\"16/9\" animation=\"wave\" aria-hidden=\"true\" />\n }\n\n <div class=\"projectCardContent\">\n <div class=\"projectDescription\">\n <p class=\"projectDescriptionLabel\">\n {{ 'dashboard.officeProfile.projectDescription' | translate }}\n </p>\n <p class=\"projectCardDescription\">{{ proj.description || '\u2014' }}</p>\n </div>\n </div>\n </div>\n </article>\n }\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
11446
11631
  }], ctorParameters: null, propDecorators: { displayProjects: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayProjects", required: false }] }], projectImagesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectImagesLoading", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }] } }) });
11447
11632
 
11633
+ /** Contact tab of the office profile view, showing email, phone, city and address as info-field cards beside an embedded map and a link out to Google Maps. */
11448
11634
  class SceOfficeProfileContactTabComponent {
11449
11635
  email = input('', ...(ngDevMode ? [{ debugName: "email" }] : /* istanbul ignore next */ []));
11450
11636
  phone = input('', ...(ngDevMode ? [{ debugName: "phone" }] : /* istanbul ignore next */ []));
@@ -11460,6 +11646,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11460
11646
  args: [{ selector: 'sce-office-profile-contact-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-contact-tab' }, imports: [TranslatePipe, SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<section class=\"card overviewCard\">\n <div class=\"section overviewSection\">\n <h3 class=\"sectionTitle overviewSectionTitle\">{{ 'dashboard.officeProfile.contactInfo' | translate }}</h3>\n <sce-info-fields-grid gap=\"sm\" class=\"overviewInfoFieldsGrid\">\n <sce-info-field-card [label]=\"'dashboard.officeProfile.email' | translate\" [value]=\"email() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.phone' | translate\" [value]=\"phone() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.city' | translate\" [value]=\"cityName() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.address' | translate\" [value]=\"addressDisplay() || '\u2014'\" [fullWidth]=\"true\" />\n </sce-info-fields-grid>\n\n <div class=\"locationSection\">\n <div class=\"mapWrap\">\n @if (safeMapEmbedSrc()) {\n <iframe\n class=\"mapFrame\"\n [src]=\"safeMapEmbedSrc()\"\n loading=\"lazy\"\n referrerpolicy=\"no-referrer-when-downgrade\"\n [title]=\"'dashboard.officeProfile.location' | translate\"\n ></iframe>\n } @else {\n <!-- role=\"img\": aria-label is prohibited on a plain div (axe: aria-prohibited-attr). -->\n <div class=\"mapPlaceholder\" role=\"img\" [attr.aria-label]=\"'dashboard.officeProfile.location' | translate\">\n <img src=\"/assets/icons/maps.svg\" width=\"48\" height=\"48\" alt=\"\" aria-hidden=\"true\" />\n </div>\n }\n </div>\n @if (addressDisplay()) {\n <a [href]=\"googleMapsLink()\" target=\"_blank\" rel=\"noreferrer\" class=\"mapLink\">\n {{ addressDisplay() }}\n </a>\n }\n </div>\n </div>\n</section>\n", styles: [":host{display:block}\n"] }]
11461
11647
  }], propDecorators: { email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: false }] }], phone: [{ type: i0.Input, args: [{ isSignal: true, alias: "phone", required: false }] }], cityName: [{ type: i0.Input, args: [{ isSignal: true, alias: "cityName", required: false }] }], addressDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "addressDisplay", required: false }] }], safeMapEmbedSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "safeMapEmbedSrc", required: false }] }], googleMapsLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "googleMapsLink", required: false }] }] } });
11462
11648
 
11649
+ /** Official-data tab of the office profile view, showing VAT number, commercial registration, bank/IBAN and national address as info-field cards, with preferred project sizes rendered as PrimeNG tag chips when `useTagChips` is set. */
11463
11650
  class SceOfficeProfileOfficialTabComponent {
11464
11651
  vatNumber = input('', ...(ngDevMode ? [{ debugName: "vatNumber" }] : /* istanbul ignore next */ []));
11465
11652
  commercialRegistrationNumber = input('', ...(ngDevMode ? [{ debugName: "commercialRegistrationNumber" }] : /* istanbul ignore next */ []));
@@ -11478,6 +11665,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11478
11665
  args: [{ selector: 'sce-office-profile-official-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-office-profile-official-tab' }, imports: [TranslatePipe, Tag, SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<section class=\"card overviewCard\">\n <div class=\"section overviewSection\">\n <h3 class=\"sectionTitle overviewSectionTitle\">{{ 'dashboard.officeProfile.officialData' | translate }}</h3>\n <sce-info-fields-grid gap=\"sm\" class=\"overviewInfoFieldsGrid\">\n <sce-info-field-card [label]=\"'dashboard.officeProfile.taxRegNo' | translate\" [value]=\"vatNumber() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.unifiedNo' | translate\" [value]=\"commercialRegistrationNumber() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.city' | translate\" [value]=\"cityName() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.bankName' | translate\" [value]=\"bankNameDisplay() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.shortAddress' | translate\" [value]=\"shortNationalAddress() || '\u2014'\" />\n <sce-info-field-card [label]=\"'dashboard.officeProfile.iban' | translate\" [value]=\"ibanNumber() || '\u2014'\" [fullWidth]=\"true\" />\n @if (preferredProjectSizesDisplay().length > 0) {\n <sce-info-field-card\n [label]=\"'dashboard.officeProfile.preferredProjectSize' | translate\"\n [fullWidth]=\"true\"\n [value]=\"useTagChips() ? '' : preferredProjectSizesLabel() || '\u2014'\"\n >\n @if (useTagChips()) {\n <div class=\"preferredSizesChips\">\n @for (size of preferredProjectSizesDisplay(); track size) {\n <p-tag [value]=\"size\" severity=\"secondary\" />\n }\n </div>\n }\n </sce-info-field-card>\n }\n </sce-info-fields-grid>\n </div>\n</section>\n", styles: [":host{display:contents}.preferredSizesChips{display:flex;flex-wrap:wrap;gap:var(--space-2)}\n"] }]
11479
11666
  }], propDecorators: { vatNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "vatNumber", required: false }] }], commercialRegistrationNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "commercialRegistrationNumber", required: false }] }], cityName: [{ type: i0.Input, args: [{ isSignal: true, alias: "cityName", required: false }] }], bankNameDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankNameDisplay", required: false }] }], shortNationalAddress: [{ type: i0.Input, args: [{ isSignal: true, alias: "shortNationalAddress", required: false }] }], ibanNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "ibanNumber", required: false }] }], preferredProjectSizesDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredProjectSizesDisplay", required: false }] }], preferredProjectSizesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredProjectSizesLabel", required: false }] }], useTagChips: [{ type: i0.Input, args: [{ isSignal: true, alias: "useTagChips", required: false }] }] } });
11480
11667
 
11668
+ /** Collapsible `<details>` panel (open by default) showing the reviewer's rejection note, or an em dash when the note is empty. */
11481
11669
  class SceDataRequestRejectionPanelComponent {
11482
11670
  /** The rejection note text from the API. Empty string shows a dash. */
11483
11671
  note = input('', ...(ngDevMode ? [{ debugName: "note" }] : /* istanbul ignore next */ []));
@@ -11513,6 +11701,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11513
11701
  }]
11514
11702
  }], propDecorators: { note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }] } });
11515
11703
 
11704
+ /** Header card of a data-change request showing its number, status badge and office info grid, revealing the rejection panel only when `statusCode` is rejected. */
11516
11705
  class SceDataRequestHeaderCardComponent {
11517
11706
  /** Human-readable request number (e.g. "REQ-00123"). */
11518
11707
  requestNumber = input.required(...(ngDevMode ? [{ debugName: "requestNumber" }] : /* istanbul ignore next */ []));
@@ -11551,6 +11740,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11551
11740
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'sce-data-request-header-card' }, template: "<article class=\"detailCard\">\n <header class=\"detailHeaderRow\">\n <div class=\"detailTitleGroup\">\n <h1 class=\"detailTitle\">\n {{ 'dashboard.contractDetails.requestLabel' | translate }}\n <sce-bidi-isolate>#{{ requestNumber() }}</sce-bidi-isolate>\n </h1>\n <sce-business-status-tag [label]=\"statusLabel()\" size=\"sm\" />\n </div>\n <p class=\"detailSubmissionDate\">\n {{ 'dashboard.dataRequests.details.requestInfo.submissionDate' | translate }}:\n {{ submissionDate() }}\n </p>\n </header>\n\n @if (statusCode() === 'rejected') {\n <sce-data-request-rejection-panel [note]=\"rejectionNote()\" />\n }\n\n <sce-info-fields-grid>\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.licenseNumber' | translate\" [value]=\"licenseNumber()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.officeName' | translate\" [value]=\"officeName()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.submissionDate' | translate\" [value]=\"submissionDate()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.requestedBy' | translate\" [value]=\"representativeName()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.reviewRequired' | translate\" [value]=\"reviewRequired()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.requestInfo.requestStatus' | translate\" [value]=\"requestStatusLabel()\" />\n <sce-info-field-card\n [label]=\"'dashboard.dataRequests.details.requestInfo.lastActionDate' | translate\"\n [value]=\"lastActionDate() || submissionDate()\"\n />\n </sce-info-fields-grid>\n</article>\n" }]
11552
11741
  }], propDecorators: { requestNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestNumber", required: true }] }], statusLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusLabel", required: true }] }], statusCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusCode", required: true }] }], submissionDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "submissionDate", required: true }] }], rejectionNote: [{ type: i0.Input, args: [{ isSignal: true, alias: "rejectionNote", required: false }] }], licenseNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "licenseNumber", required: true }] }], officeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "officeName", required: true }] }], representativeName: [{ type: i0.Input, args: [{ isSignal: true, alias: "representativeName", required: true }] }], reviewRequired: [{ type: i0.Input, args: [{ isSignal: true, alias: "reviewRequired", required: true }] }], requestStatusLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "requestStatusLabel", required: true }] }], lastActionDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "lastActionDate", required: false }] }] } });
11553
11742
 
11743
+ /** Titled table contrasting each field's current and updated value in a data-change request, flagging the rows that changed. */
11554
11744
  class SceDataRequestComparisonTableComponent {
11555
11745
  /** Section heading text. */
11556
11746
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
@@ -11564,6 +11754,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11564
11754
  args: [{ selector: 'sce-data-request-comparison-table', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'sce-data-request-comparison-table' }, template: "<section class=\"comparisonSection\">\n <h2 class=\"comparisonSectionTitle\">{{ title() }}</h2>\n <div class=\"comparisonTableHeader\">\n <span>{{ 'dashboard.dataRequests.details.table.field' | translate }}</span>\n <span>{{ 'dashboard.dataRequests.details.table.currentValue' | translate }}</span>\n <span>{{ 'dashboard.dataRequests.details.table.updatedValue' | translate }}</span>\n </div>\n @for (row of rows(); track row.label) {\n <div class=\"comparisonTableRow\" [class.comparisonTableRowChanged]=\"row.changed\">\n <span class=\"comparisonField\">{{ row.label }}</span>\n <span class=\"comparisonCurrent\" [attr.data-label]=\"'dashboard.dataRequests.details.table.currentValue' | translate\">{{\n row.current\n }}</span>\n <span class=\"comparisonUpdated\" [attr.data-label]=\"'dashboard.dataRequests.details.table.updatedValue' | translate\">{{\n row.updated\n }}</span>\n </div>\n }\n</section>\n" }]
11565
11755
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }] } });
11566
11756
 
11757
+ /** Side-by-side before/after image frames for a data-change request, sized square for `logo` and widescreen for `cover`, emitting a click per side. */
11567
11758
  class SceDataRequestMediaComparisonComponent {
11568
11759
  /** Block heading (e.g. "Logo" or "Cover"). */
11569
11760
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
@@ -11587,6 +11778,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11587
11778
  args: [{ selector: 'sce-data-request-media-comparison', standalone: true, imports: [TranslatePipe, SceSkeleton, SceIcon], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'sce-data-request-media-comparison' }, template: "<div class=\"mediaCompareBlock\">\n <p class=\"mediaCompareTitle\">{{ title() }}</p>\n <div class=\"mediaCompareRow\">\n <!-- Current image column -->\n <div class=\"mediaCompareColumn\">\n <span class=\"mediaCompareBadge mediaCompareBadgeCurrent\">\n {{ 'dashboard.dataRequests.details.logoCover.current' | translate }}\n </span>\n <div\n class=\"mediaCompareFrame\"\n [class.mediaCompareLogoFrame]=\"variant() === 'logo'\"\n [class.mediaCompareCoverFrame]=\"variant() === 'cover'\"\n [class.mediaCompareLogoFrameCurrent]=\"variant() === 'logo'\"\n [class.mediaCompareCoverFrameCurrent]=\"variant() === 'cover'\"\n >\n @if (loading()) {\n <sce-skeleton variant=\"rectangular\" width=\"100%\" height=\"100%\" animation=\"wave\" aria-hidden=\"true\" />\n } @else if (currentUrl()) {\n <button type=\"button\" class=\"mediaCompareImageButton\" [attr.aria-label]=\"title()\" (click)=\"currentImageClick.emit()\">\n <img [src]=\"currentUrl()\" alt=\"\" class=\"mediaCompareImage\" loading=\"lazy\" />\n </button>\n } @else {\n <span class=\"mediaComparePlaceholder\">\u2014</span>\n }\n </div>\n </div>\n\n <!-- Direction arrow -->\n <div class=\"mediaCompareArrow\" aria-hidden=\"true\">\n <sce-icon name=\"media-compare-arrow\" [size]=\"23\" [height]=\"9\" />\n </div>\n\n <!-- New image column -->\n <div class=\"mediaCompareColumn\">\n <span class=\"mediaCompareBadge mediaCompareBadgeUpdated\">\n {{ 'dashboard.dataRequests.details.logoCover.updated' | translate }}\n </span>\n <div\n class=\"mediaCompareFrame\"\n [class.mediaCompareLogoFrame]=\"variant() === 'logo'\"\n [class.mediaCompareCoverFrame]=\"variant() === 'cover'\"\n [class.mediaCompareLogoFrameUpdated]=\"variant() === 'logo'\"\n [class.mediaCompareCoverFrameUpdated]=\"variant() === 'cover'\"\n >\n @if (loading()) {\n <sce-skeleton variant=\"rectangular\" width=\"100%\" height=\"100%\" animation=\"wave\" aria-hidden=\"true\" />\n } @else if (newUrl()) {\n <button type=\"button\" class=\"mediaCompareImageButton\" [attr.aria-label]=\"title()\" (click)=\"newImageClick.emit()\">\n <img [src]=\"newUrl()\" alt=\"\" class=\"mediaCompareImage\" loading=\"lazy\" />\n </button>\n } @else {\n <span class=\"mediaComparePlaceholder\">\u2014</span>\n }\n </div>\n </div>\n </div>\n</div>\n" }]
11588
11779
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], currentUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentUrl", required: false }] }], newUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "newUrl", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], currentImageClick: [{ type: i0.Output, args: ["currentImageClick"] }], newImageClick: [{ type: i0.Output, args: ["newImageClick"] }] } });
11589
11780
 
11781
+ /** Newsletter subscription dialog collecting a name, email and optional Saudi mobile number with its own touch-based validation, resetting all fields whenever it is closed. */
11590
11782
  class SceNewsletterSubscriptionDialogComponent {
11591
11783
  translate = inject(TranslateService);
11592
11784
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
@@ -11693,6 +11885,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11693
11885
  args: [{ host: { class: 'sce-newsletter-subscription-dialog' }, selector: 'sce-newsletter-subscription-dialog', standalone: true, imports: [TranslatePipe, SceFormDialogComponent, SceFormDialogSectionComponent, SceTextFieldComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<sce-form-dialog\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"titleText()\"\n [subtitle]=\"subtitleText()\"\n [isSubmitting]=\"isSubmitting()\"\n [errorMessage]=\"apiError() || undefined\"\n [submitLabel]=\"submitLabelText()\"\n [cancelLabel]=\"cancelLabelText()\"\n size=\"sm\"\n (close)=\"onClose()\"\n (submitForm)=\"onSubmit()\"\n>\n <sce-form-dialog-section>\n <sce-text-field\n id=\"newsletter-client-name\"\n [label]=\"'newsletter.form.clientName' | translate\"\n [value]=\"clientName()\"\n [placeholder]=\"'newsletter.form.clientNamePlaceholder' | translate\"\n [required]=\"true\"\n [error]=\"clientNameError()\"\n validationMode=\"never\"\n autocomplete=\"name\"\n (valueChange)=\"clientName.set($event); clientNameTouched.set(true)\"\n />\n <sce-text-field\n id=\"newsletter-email\"\n type=\"email\"\n [label]=\"'newsletter.form.email' | translate\"\n [value]=\"email()\"\n [placeholder]=\"'newsletter.form.emailPlaceholder' | translate\"\n [required]=\"true\"\n [error]=\"emailError()\"\n validationMode=\"never\"\n autocomplete=\"email\"\n (valueChange)=\"email.set($event); emailTouched.set(true)\"\n />\n <sce-text-field\n id=\"newsletter-mobile\"\n type=\"tel\"\n [label]=\"'newsletter.form.mobile' | translate\"\n [value]=\"mobile()\"\n [placeholder]=\"'newsletter.form.mobilePlaceholder' | translate\"\n [error]=\"mobileError()\"\n validationMode=\"never\"\n autocomplete=\"tel\"\n (valueChange)=\"mobile.set($event); mobileTouched.set(true)\"\n />\n </sce-form-dialog-section>\n</sce-form-dialog>\n", styles: [":host{display:block;display:contents}\n"] }]
11694
11886
  }], ctorParameters: () => [], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], isSubmitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmitting", required: false }] }], apiError: [{ type: i0.Input, args: [{ isSignal: true, alias: "apiError", required: false }] }], closeDialog: [{ type: i0.Output, args: ["closeDialog"] }], submitForm: [{ type: i0.Output, args: ["submitForm"] }] } });
11695
11887
 
11888
+ /** Profile-photo panel with a hidden file input: emits `photoFileSelected` on pick (resetting the input so the same file can be re-chosen) and `viewClick` only when `hasRealPhoto` is true; uses `ViewEncapsulation.None`. */
11696
11889
  class SceProfilePhotoSectionComponent {
11697
11890
  /** Currently displayed photo URL. Null or undefined shows the default avatar. */
11698
11891
  photoUrl = input(null, ...(ngDevMode ? [{ debugName: "photoUrl" }] : /* istanbul ignore next */ []));
@@ -11740,6 +11933,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11740
11933
  }] } });
11741
11934
 
11742
11935
  const EMPTY_DISPLAY = '—';
11936
+ /** Personal-profile panel that flips between a read-only field grid and an edit form (`editing`), showing skeletons while `profile` is null and an inline banner for `error`; uses `ViewEncapsulation.None`. */
11743
11937
  class SceProfileInfoSectionComponent {
11744
11938
  /** Resolved profile data for the read (view) mode. Null shows skeleton. */
11745
11939
  profile = input(null, ...(ngDevMode ? [{ debugName: "profile" }] : /* istanbul ignore next */ []));
@@ -11844,6 +12038,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11844
12038
  ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'sce-profile-info-section' }, template: "<section class=\"card\">\n @if (error()) {\n <sce-inline-api-error [message]=\"error()\" />\n }\n\n @if (loading()) {\n <sce-info-fields-skeleton [count]=\"8\" />\n }\n\n @if (profile()) {\n @if (!editing()) {\n @for (section of viewSections(); track section.titleKey) {\n <div class=\"cardHeader\">\n <h4 class=\"sectionTitle\">{{ section.titleKey | translate }}</h4>\n @if (section.showEditAction) {\n <sce-button variant=\"primary\" size=\"medium\" [fullWidth]=\"false\" (click)=\"editClick.emit()\">\n {{ 'dashboard.profile.updateProfile' | translate }}\n </sce-button>\n }\n </div>\n\n <sce-info-fields-grid gap=\"sm\">\n @for (field of section.fields; track field.labelKey) {\n <sce-info-field-card [label]=\"field.labelKey | translate\" [value]=\"field.value\" [fullWidth]=\"field.fullWidth === true\" />\n }\n </sce-info-fields-grid>\n }\n } @else {\n <div class=\"headerActions\">\n <h3 class=\"sectionTitle\">\n {{ 'dashboard.profile.editData' | translate }}\n </h3>\n </div>\n\n <div class=\"formContainer\" [attr.dir]=\"fieldDir()\">\n <div class=\"formField\">\n <sce-text-field\n id=\"profile-email\"\n type=\"email\"\n [dir]=\"fieldDir()\"\n [label]=\"'dashboard.profile.email' | translate\"\n [placeholder]=\"'dashboard.profile.emailPlaceholder' | translate\"\n [value]=\"editEmail()\"\n [required]=\"true\"\n validationMode=\"never\"\n [error]=\"emailError() || null\"\n (valueChange)=\"emailChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField\">\n <sce-text-field\n id=\"profile-phone\"\n type=\"tel\"\n [dir]=\"fieldDir()\"\n [label]=\"'dashboard.profile.mobileNumber' | translate\"\n [placeholder]=\"'dashboard.profile.phonePlaceholder' | translate\"\n [value]=\"editPhone()\"\n [maxLength]=\"15\"\n [required]=\"true\"\n validationMode=\"never\"\n [error]=\"phoneError() || null\"\n (valueChange)=\"phoneChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField fullRow\">\n <sce-text-field\n id=\"profile-short-national-address\"\n [dir]=\"fieldDir()\"\n [label]=\"'dashboard.profile.shortNationalAddress' | translate\"\n [placeholder]=\"'dashboard.profile.addressPlaceholder' | translate\"\n [value]=\"editAddress()\"\n [maxLength]=\"20\"\n [required]=\"true\"\n validationMode=\"never\"\n [error]=\"addressError() || null\"\n (valueChange)=\"addressChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField fullRow\">\n <sce-select-field\n id=\"profile-bank\"\n [label]=\"'dashboard.profile.bank' | translate\"\n [placeholder]=\"'dashboard.profile.selectBank' | translate\"\n [options]=\"bankSelectOptions()\"\n [value]=\"bankSelectValue()\"\n [dir]=\"locale() === 'ar' ? 'rtl' : 'ltr'\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [required]=\"true\"\n [borderless]=\"false\"\n validationMode=\"never\"\n inputClassName=\"profileBankSelect\"\n (valueChange)=\"onBankSelectChange($event)\"\n />\n </div>\n <div class=\"formField fullRow\">\n <sce-text-field\n id=\"profile-bank-account\"\n inputClassName=\"profileIbanInput\"\n [label]=\"'dashboard.profile.bankAccount' | translate\"\n [placeholder]=\"'dashboard.profile.bankAccountPlaceholder' | translate\"\n prefix=\"SA\"\n prefixMode=\"inline\"\n [value]=\"editBankAccount()\"\n [required]=\"true\"\n [maxLength]=\"22\"\n validationMode=\"never\"\n [error]=\"bankAccountError() || null\"\n (valueChange)=\"bankAccountChange.emit($event)\"\n />\n </div>\n </div>\n\n <div class=\"formActions fullRow\">\n <sce-button\n type=\"button\"\n variant=\"primary\"\n size=\"large\"\n [fullWidth]=\"false\"\n [disabled]=\"saving()\"\n [loading]=\"saving()\"\n (click)=\"saveClick.emit()\"\n >\n {{ saving() ? ('dashboard.profile.saving' | translate) : ('dashboard.profile.save' | translate) }}\n </sce-button>\n <sce-button type=\"button\" variant=\"outline\" size=\"large\" [fullWidth]=\"false\" [disabled]=\"saving()\" (click)=\"cancelClick.emit()\">\n {{ 'dashboard.profile.cancel' | translate }}\n </sce-button>\n </div>\n }\n }\n</section>\n", styles: ["@charset \"UTF-8\";.sce-profile-info-section{display:block;width:100%;min-width:0}.sce-profile-info-section>.card{display:flex;flex-direction:column;gap:var(--space-16);width:100%;min-width:0;box-sizing:border-box;overflow:hidden;padding:clamp(var(--space-16),4vi,var(--space-30));background:var(--app-surface);border-radius:var(--radius-brand-sm)}.sce-profile-info-section .cardHeader,.sce-profile-info-section .headerActions{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:var(--space-12)}.sce-profile-info-section .sectionTitle{margin:0;color:var(--text-text-primary-900);font-size:var(--font-size-lg-18);font-weight:var(--font-weight-bold);text-align:start}.sce-profile-info-section .cardHeader sce-button,.sce-profile-info-section .formActions sce-button{width:fit-content;max-width:100%}.sce-profile-info-section .formActions sce-button .btn{width:var(--size-179);min-width:var(--size-179);box-sizing:border-box}.sce-profile-info-section .fullRow{grid-column:1/-1}.sce-profile-info-section .formContainer{display:grid;grid-template-columns:1fr;gap:var(--space-20)}.sce-profile-info-section .formField{display:flex;flex-direction:column;gap:var(--space-6);min-width:0}.sce-profile-info-section .sce-field{gap:var(--space-6)}.sce-profile-info-section .sce-field__label{font-size:var(--font-size-md);font-weight:var(--font-weight-medium);color:var(--text-text-secondary-700)}.sce-profile-info-section .formContainer[dir=rtl] sce-text-field .p-inputtext.w-full,.sce-profile-info-section .formContainer[dir=ltr] sce-text-field .p-inputtext.w-full{width:100%;min-height:var(--size-52);box-sizing:border-box;padding-block:0;padding-inline:var(--space-16);font-size:var(--font-size-lg);background:var(--app-surface);border-radius:var(--radius-brand-sm)}.sce-profile-info-section .formContainer[dir=ltr] sce-text-field .p-inputtext.w-full{text-align:start}.sce-profile-info-section .formContainer[dir=rtl] sce-text-field .p-inputtext.w-full{direction:ltr;text-align:end}.sce-profile-info-section .formContainer sce-text-field .inlineContainer .inlineInput{font-size:var(--font-size-lg);color:var(--form-input-value-color)}.sce-profile-info-section .formContainer sce-text-field .inlineContainer .inlineInput::placeholder{color:var(--form-field-text-placeholder)}.sce-profile-info-section .root .profileBankSelect.p-select{min-height:var(--size-52);border-radius:var(--radius-brand-sm);background:var(--app-surface)}.sce-profile-info-section .root .profileBankSelect.p-select .p-select-label{display:flex;align-items:center;width:100%;min-height:var(--size-52);padding-block:0;padding-inline:var(--space-16);font-size:var(--font-size-lg);color:var(--text-text-primary-900)}.sce-profile-info-section .root .profileBankSelect.p-select .p-select-label.p-placeholder{color:var(--form-field-text-placeholder)}.sce-profile-info-section .formContainer[dir=rtl] .profileBankSelect.p-select .p-select-label{direction:ltr;justify-content:flex-end;text-align:end;padding-inline-start:var(--space-8);padding-inline-end:var(--space-16)}.sce-profile-info-section .formContainer[dir=ltr] .profileBankSelect.p-select .p-select-label{justify-content:flex-start;text-align:start}.sce-profile-info-section sce-button .btn{font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-semibold);border-radius:var(--radius-brand-sm);letter-spacing:normal}.sce-profile-info-section sce-button .btn--primary{background-color:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.sce-profile-info-section sce-button .btn--outline{border:1.5px solid var(--color-brand-primary-900);color:var(--color-brand-primary-900);background:var(--background-bg-primary)}.sce-profile-info-section sce-button .btn--outline:hover:not(:disabled){background:var(--color-surface-2);border-color:var(--color-brand-primary-900);color:var(--color-brand-primary-900)}.sce-profile-info-section sce-button .btn--outline:active:not(:disabled){background:var(--color-surface-2);border-color:var(--color-brand-primary-900);color:var(--color-brand-primary-900)}.sce-profile-info-section .cardHeader sce-button .btn--medium{height:var(--space-48);padding-inline:var(--space-24);font-size:var(--font-size-md)}.sce-profile-info-section .formActions sce-button .btn--large{height:var(--size-56);padding-inline:var(--space-24);font-size:var(--font-size-lg)}.sce-profile-info-section .formActions{display:flex;gap:var(--space-12);padding-block-start:var(--space-16);direction:ltr}@media(min-width:768px){.sce-profile-info-section .formContainer{grid-template-columns:repeat(2,1fr)}.sce-profile-info-section .formField{grid-column:1/-1}.sce-profile-info-section .formField:nth-child(1),.sce-profile-info-section .formField:nth-child(2){grid-column:span 1}}@media(max-width:768px){.sce-profile-info-section .cardHeader,.sce-profile-info-section .headerActions{flex-direction:column;align-items:stretch}.sce-profile-info-section .cardHeader sce-button,.sce-profile-info-section .formActions sce-button{width:100%;min-width:0}.sce-profile-info-section .formActions sce-button .btn{width:100%;min-width:0}.sce-profile-info-section>.card{padding:var(--space-20)}.sce-profile-info-section .formActions{flex-direction:column;align-items:stretch}}@media(max-width:480px){.sce-profile-info-section>.card{padding:var(--space-16)}}\n"] }]
11845
12039
  }], propDecorators: { profile: [{ type: i0.Input, args: [{ isSignal: true, alias: "profile", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], editing: [{ type: i0.Input, args: [{ isSignal: true, alias: "editing", required: false }] }], saving: [{ type: i0.Input, args: [{ isSignal: true, alias: "saving", required: false }] }], editEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "editEmail", required: false }] }], editPhone: [{ type: i0.Input, args: [{ isSignal: true, alias: "editPhone", required: false }] }], editAddress: [{ type: i0.Input, args: [{ isSignal: true, alias: "editAddress", required: false }] }], editBankId: [{ type: i0.Input, args: [{ isSignal: true, alias: "editBankId", required: false }] }], editBankAccount: [{ type: i0.Input, args: [{ isSignal: true, alias: "editBankAccount", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], phoneError: [{ type: i0.Input, args: [{ isSignal: true, alias: "phoneError", required: false }] }], addressError: [{ type: i0.Input, args: [{ isSignal: true, alias: "addressError", required: false }] }], bankAccountError: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankAccountError", required: false }] }], banks: [{ type: i0.Input, args: [{ isSignal: true, alias: "banks", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], editClick: [{ type: i0.Output, args: ["editClick"] }], cancelClick: [{ type: i0.Output, args: ["cancelClick"] }], saveClick: [{ type: i0.Output, args: ["saveClick"] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], phoneChange: [{ type: i0.Output, args: ["phoneChange"] }], addressChange: [{ type: i0.Output, args: ["addressChange"] }], bankIdChange: [{ type: i0.Output, args: ["bankIdChange"] }], bankAccountChange: [{ type: i0.Output, args: ["bankAccountChange"] }] } });
11846
12040
 
12041
+ /** Info-field grid summarising the entity's current contact and registration data on a data-change request; each unset field falls back to an em dash. */
11847
12042
  class SceDataRequestCurrentSummaryComponent {
11848
12043
  currentPhone = input('—', ...(ngDevMode ? [{ debugName: "currentPhone" }] : /* istanbul ignore next */ []));
11849
12044
  currentEmail = input('—', ...(ngDevMode ? [{ debugName: "currentEmail" }] : /* istanbul ignore next */ []));
@@ -11858,6 +12053,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11858
12053
  args: [{ selector: 'sce-data-request-current-summary', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-data-request-current-summary' }, imports: [TranslatePipe, SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<section class=\"comparisonSection\">\n <h2 class=\"comparisonSectionTitle\">\n {{ 'dashboard.dataRequests.details.sections.currentSummary' | translate }}\n </h2>\n <sce-info-fields-grid>\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.summary.phone' | translate\" [value]=\"currentPhone()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.summary.email' | translate\" [value]=\"currentEmail()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.summary.city' | translate\" [value]=\"currentCity()\" />\n <sce-info-field-card [label]=\"'dashboard.dataRequests.details.summary.unifiedNumber' | translate\" [value]=\"unifiedNumber()\" />\n <sce-info-field-card\n [label]=\"'dashboard.dataRequests.details.summary.vatRegistrationNumber' | translate\"\n [value]=\"currentVatNumber()\"\n />\n </sce-info-fields-grid>\n</section>\n", styles: [":host{display:block}\n"] }]
11859
12054
  }], propDecorators: { currentPhone: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPhone", required: false }] }], currentEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentEmail", required: false }] }], currentCity: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentCity", required: false }] }], unifiedNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "unifiedNumber", required: false }] }], currentVatNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentVatNumber", required: false }] }] } });
11860
12055
 
12056
+ /** Lists the added, updated and removed portfolio projects in a data-change request, emitting the project and image index when a preview is clicked. */
11861
12057
  class SceDataRequestProjectChangesComponent {
11862
12058
  projectChanges = input([], ...(ngDevMode ? [{ debugName: "projectChanges" }] : /* istanbul ignore next */ []));
11863
12059
  isSystemUser = input(false, ...(ngDevMode ? [{ debugName: "isSystemUser" }] : /* istanbul ignore next */ []));
@@ -11870,6 +12066,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11870
12066
  args: [{ selector: 'sce-data-request-project-changes', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-data-request-project-changes' }, imports: [TranslatePipe], template: "@if (projectChanges().length > 0) {\n <section class=\"projectsChangesSection\">\n <div class=\"projectsChangesHeader\">\n <h2 class=\"projectsChangesTitle\">\n {{ 'dashboard.dataRequests.details.projectsChanges.title' | translate }}\n </h2>\n @if (!isSystemUser()) {\n <span class=\"projectsChangesCount\">\n {{ 'dashboard.dataRequests.details.projectsChanges.countLabel' | translate: { count: projectChanges().length } }}\n </span>\n }\n </div>\n\n @if (isSystemUser()) {\n @for (change of projectChanges(); track change.id) {\n <article class=\"projectChangeCard\">\n <header class=\"projectChangeCardHeader\">\n <div class=\"projectChangeTitleGroup\">\n <h3 class=\"projectChangeTitle\" [class.projectChangeTitleDeleted]=\"change.isRemoved\">{{ change.title }}</h3>\n @if (change.category !== '\u2014') {\n <span class=\"projectChangeCategoryTag\">{{ change.category }}</span>\n }\n </div>\n <span\n class=\"projectChangeBadge\"\n [class.projectChangeBadgeAdded]=\"change.type === 'added'\"\n [class.projectChangeBadgeUpdated]=\"change.type === 'updated'\"\n [class.projectChangeBadgeRemoved]=\"change.type === 'removed'\"\n >{{ change.badgeLabel }}</span\n >\n </header>\n\n <div class=\"projectChangeBody\">\n <div class=\"projectChangeDetails\">\n <div class=\"projectChangeDescriptionBlock\">\n <p class=\"projectChangeDescriptionLabel\">\n {{ 'dashboard.dataRequests.details.projectsChanges.description' | translate }}\n </p>\n <p class=\"projectChangeDescriptionText\">\n @if (change.descriptionChanged) {\n <span class=\"projectCompareValue\">\n <span class=\"projectCompareNew\">{{ change.nextDescription }}</span>\n <span class=\"projectCompareArrow\" aria-hidden=\"true\">\u2190</span>\n <span class=\"projectCompareOld\">{{ change.prevDescription }}</span>\n </span>\n } @else {\n {{ change.description }}\n }\n </p>\n </div>\n\n <div class=\"projectChangeMetrics\">\n @for (metric of change.metrics; track metric.key) {\n <div class=\"projectChangeMetric\" [class.projectChangeMetricChanged]=\"metric.changed\">\n <p class=\"projectChangeMetricLabel\">{{ metric.label }}</p>\n <p class=\"projectChangeMetricValue\">\n @if (metric.changed) {\n <span class=\"projectCompareValue\">\n <span class=\"projectCompareNew\">{{ metric.nextValue }}</span>\n <span class=\"projectCompareArrow\" aria-hidden=\"true\">\u2190</span>\n <span class=\"projectCompareOld\">{{ metric.currentValue }}</span>\n </span>\n } @else {\n {{ metric.nextValue }}\n }\n </p>\n </div>\n }\n </div>\n </div>\n\n @if (change.imageUrls.length > 0) {\n <div class=\"projectChangeGallery\">\n <button\n type=\"button\"\n class=\"projectChangeMainImage\"\n (click)=\"imageClick.emit({ change, index: 0 })\"\n [attr.aria-label]=\"'dashboard.dataRequests.details.projectsChanges.viewImages' | translate\"\n >\n <img [src]=\"change.imageUrls[0]\" [alt]=\"change.title\" class=\"projectChangeImage\" loading=\"lazy\" />\n </button>\n @if (change.imageUrls.length > 1) {\n <div class=\"projectChangeThumbRow\">\n <!-- track $index: fixed max-3 thumbnail slice, positions never reorder -->\n @for (thumbUrl of change.imageUrls.slice(1, 4); track $index) {\n <button\n type=\"button\"\n class=\"projectChangeThumb\"\n (click)=\"imageClick.emit({ change, index: $index + 1 })\"\n [attr.aria-label]=\"'dashboard.dataRequests.details.projectsChanges.viewImages' | translate\"\n >\n <img [src]=\"thumbUrl\" alt=\"\" class=\"projectChangeImage\" loading=\"lazy\" />\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </article>\n }\n } @else {\n <div class=\"projectChangeCompactList\">\n @for (change of projectChanges(); track change.id) {\n <article class=\"projectChangeCompactRow\">\n <div class=\"projectChangeCompactMain\">\n @if (change.imageUrls.length > 0) {\n <button\n type=\"button\"\n class=\"projectChangeCompactThumb\"\n (click)=\"imageClick.emit({ change, index: 0 })\"\n [attr.aria-label]=\"'dashboard.dataRequests.details.projectsChanges.viewImages' | translate\"\n >\n <img [src]=\"change.imageUrls[0]\" alt=\"\" class=\"projectChangeImage\" loading=\"lazy\" />\n </button>\n }\n <div class=\"projectChangeCompactText\">\n <h3 class=\"projectChangeCompactTitle\" [class.projectChangeTitleDeleted]=\"change.isRemoved\">{{ change.title }}</h3>\n <p class=\"projectChangeCompactSubtitle\">{{ change.compactSubtitle || '\u2014' }}</p>\n </div>\n </div>\n <span\n class=\"projectChangeBadge\"\n [class.projectChangeBadgeAdded]=\"change.type === 'added'\"\n [class.projectChangeBadgeUpdated]=\"change.type === 'updated'\"\n [class.projectChangeBadgeRemoved]=\"change.type === 'removed'\"\n >{{ change.badgeLabel }}</span\n >\n </article>\n }\n </div>\n }\n </section>\n}\n", styles: [":host{display:block}\n"] }]
11871
12067
  }], propDecorators: { projectChanges: [{ type: i0.Input, args: [{ isSignal: true, alias: "projectChanges", required: false }] }], isSystemUser: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSystemUser", required: false }] }], imageClick: [{ type: i0.Output, args: ["imageClick"] }] } });
11872
12068
 
12069
+ /** Grid of knowledge-center categories that also owns its loading, error and empty states and emits category/retry/ticket actions. */
11873
12070
  class SceKnowledgeCenterCategoryGridComponent {
11874
12071
  categories = input([], ...(ngDevMode ? [{ debugName: "categories" }] : /* istanbul ignore next */ []));
11875
12072
  isLoadingCategories = input(false, ...(ngDevMode ? [{ debugName: "isLoadingCategories" }] : /* istanbul ignore next */ []));
@@ -11886,6 +12083,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11886
12083
  args: [{ selector: 'sce-knowledge-center-category-grid', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-knowledge-center-category-grid' }, imports: [TranslatePipe, SceSkeleton, SceIcon, SceButton, SceApiErrorStateComponent, SceEmptyStateComponent], template: "<section class=\"kc-landing__browse\">\n <h2 class=\"kc-landing__section-title\">{{ 'knowledge.browseTitle' | translate }}</h2>\n\n @if (isLoadingCategories()) {\n <div class=\"kc-landing__grid\">\n @for (i of [0, 1, 2, 3]; track i) {\n <div class=\"kc-landing__skeleton-card\">\n <sce-skeleton variant=\"circular\" />\n <sce-skeleton variant=\"header\" width=\"75%\" />\n <sce-skeleton variant=\"paragraph\" [count]=\"2\" />\n </div>\n }\n </div>\n } @else if (categoriesError()) {\n <sce-api-error-state (retry)=\"retry.emit()\" />\n } @else if (!categories().length) {\n <sce-empty-state titleKey=\"knowledge.noCategories\" [compact]=\"true\" />\n } @else {\n <div class=\"kc-landing__grid\">\n @for (category of categories(); track category.slug) {\n <button\n class=\"kc-landing__category-card\"\n type=\"button\"\n [style.background-color]=\"category.background\"\n (click)=\"categoryClick.emit(category.slug)\"\n >\n <div class=\"kc-landing__category-icon\" aria-hidden=\"true\">\n <sce-icon [name]=\"category.icon\" [size]=\"32\" />\n </div>\n <h3 class=\"kc-landing__category-title\">{{ category.titleKey }}</h3>\n <p class=\"kc-landing__category-desc\">{{ category.descriptionKey }}</p>\n </button>\n }\n </div>\n\n <div class=\"kc-landing__support\">\n <div class=\"kc-landing__support-copy\">\n <h3 class=\"kc-landing__support-title\">{{ 'knowledge.supportTitle' | translate }}</h3>\n <p class=\"kc-landing__support-text\">{{ 'knowledge.supportSubtitle' | translate }}</p>\n </div>\n <div class=\"kc-landing__support-actions\">\n <sce-button variant=\"primary\" [fullWidth]=\"false\" (click)=\"newTicket.emit()\">\n {{ 'knowledge.newTicket' | translate }}\n </sce-button>\n <sce-button variant=\"outline\" [fullWidth]=\"false\" (click)=\"viewTickets.emit()\">\n {{ 'knowledge.viewTickets' | translate }}\n </sce-button>\n </div>\n </div>\n }\n</section>\n", styles: [":host{display:block}\n"] }]
11887
12084
  }], propDecorators: { categories: [{ type: i0.Input, args: [{ isSignal: true, alias: "categories", required: false }] }], isLoadingCategories: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoadingCategories", required: false }] }], categoriesError: [{ type: i0.Input, args: [{ isSignal: true, alias: "categoriesError", required: false }] }], categoryClick: [{ type: i0.Output, args: ["categoryClick"] }], retry: [{ type: i0.Output, args: ["retry"] }], newTicket: [{ type: i0.Output, args: ["newTicket"] }], viewTickets: [{ type: i0.Output, args: ["viewTickets"] }] } });
11888
12085
 
12086
+ /** Read-only contact details panel rendering working hours, response time, phone number, email link and Instagram/Twitter links. */
11889
12087
  class SceContactInfoPanelComponent {
11890
12088
  workingHoursValue = input('', ...(ngDevMode ? [{ debugName: "workingHoursValue" }] : /* istanbul ignore next */ []));
11891
12089
  responseValue = input('', ...(ngDevMode ? [{ debugName: "responseValue" }] : /* istanbul ignore next */ []));
@@ -11902,6 +12100,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11902
12100
  args: [{ selector: 'sce-contact-info-panel', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: { class: 'sce-contact-info-panel' }, imports: [TranslatePipe, ScePhoneNumberComponent, SceBidiIsolate], template: "<aside class=\"contactInfoCol\">\n <div class=\"infoCard\">\n <h3 class=\"infoCardTitle\">{{ 'contact.contactInfo' | translate }}</h3>\n\n <div class=\"infoRow\">\n <div class=\"infoRowLabel\">\n <img src=\"/assets/icons/clock-03.svg\" alt=\"\" width=\"20\" height=\"20\" aria-hidden=\"true\" />\n <span>{{ 'contact.workingHours' | translate }}</span>\n </div>\n <p class=\"infoRowValue\">{{ workingHoursValue() }}</p>\n </div>\n\n <div class=\"infoRow\">\n <div class=\"infoRowLabel\">\n <img src=\"/assets/icons/message-incoming-01.svg\" alt=\"\" width=\"20\" height=\"20\" aria-hidden=\"true\" />\n <span>{{ 'contact.response' | translate }}</span>\n </div>\n <p class=\"infoRowValue\">{{ responseValue() }}</p>\n </div>\n\n <div class=\"infoRow\">\n <div class=\"infoRowLabel\">\n <img src=\"/assets/icons/calling.svg\" alt=\"\" width=\"20\" height=\"20\" aria-hidden=\"true\" />\n <span>{{ 'contact.phone.label' | translate }}</span>\n </div>\n <sce-phone-number class=\"infoRowValue\" [value]=\"phoneValue()\" [showCopy]=\"true\" [showIcon]=\"true\" />\n </div>\n </div>\n\n <div class=\"infoCard\">\n <h3 class=\"infoCardTitle\">{{ 'contact.additionalInfo' | translate }}</h3>\n\n <div class=\"infoRow infoRowEmail\">\n <p class=\"infoRowMuted\">{{ 'contact.email.label' | translate }}</p>\n <a class=\"infoRowLink\" [href]=\"emailHref()\">\n <sce-bidi-isolate [value]=\"emailValue()\" />\n </a>\n </div>\n\n <div class=\"infoRow infoRowSocial\">\n <p class=\"infoRowMuted\">{{ 'contact.social.label' | translate }}</p>\n <div class=\"socialLinks\" dir=\"ltr\">\n <a [href]=\"socialInstagramHref()\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"Instagram\">\n <img src=\"/assets/icons/black-instagram.svg\" alt=\"\" width=\"24\" height=\"24\" />\n </a>\n <a [href]=\"socialTwitterHref()\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"X\" class=\"socialLinkTwitter\">\n <span class=\"iconTwitter\"></span>\n </a>\n </div>\n </div>\n </div>\n</aside>\n", styles: [":host{display:contents}\n"] }]
11903
12101
  }], propDecorators: { workingHoursValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "workingHoursValue", required: false }] }], responseValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "responseValue", required: false }] }], phoneValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "phoneValue", required: false }] }], emailHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailHref", required: false }] }], emailValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailValue", required: false }] }], socialInstagramHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "socialInstagramHref", required: false }] }], socialTwitterHref: [{ type: i0.Input, args: [{ isSignal: true, alias: "socialTwitterHref", required: false }] }] } });
11904
12102
 
12103
+ /** Fully-controlled contact form panel with name, email, message-type and message fields plus a hidden `website` honeypot; it holds no state of its own — every value, error and loading flag is an input and every change is an output. */
11905
12104
  class SceContactFormPanelComponent {
11906
12105
  dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
11907
12106
  fullName = input.required(...(ngDevMode ? [{ debugName: "fullName" }] : /* istanbul ignore next */ []));
@@ -11941,6 +12140,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11941
12140
  args: [{ selector: 'sce-contact-form-panel', standalone: true, imports: [TranslatePipe, SceTextFieldComponent, SceTextareaFieldComponent, SceSelectFieldComponent, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-contact-form-panel' }, template: "<form class=\"sce-contact-form-panel__form\" [attr.dir]=\"dir()\" (submit)=\"formSubmit.emit($event)\">\n <header class=\"sce-contact-form-panel__header\">\n <h2 class=\"sce-contact-form-panel__title\">{{ 'contact.title' | translate }}</h2>\n <p class=\"sce-contact-form-panel__subtitle\">{{ 'contact.subtitle' | translate }}</p>\n </header>\n\n @if (submitSuccess()) {\n <p class=\"sce-contact-form-panel__feedback sce-contact-form-panel__feedback--success\" role=\"status\">\n {{ 'contact.form.success' | translate }}\n </p>\n }\n @if (submitError()) {\n <p class=\"sce-contact-form-panel__feedback sce-contact-form-panel__feedback--error\" role=\"alert\">\n {{ submitError() }}\n </p>\n }\n @if (!messageTypesLoading() && messageTypeUnavailable()) {\n <p class=\"sce-contact-form-panel__feedback sce-contact-form-panel__feedback--error\" role=\"status\">\n {{ 'contact.form.messageTypeUnavailable' | translate }}\n </p>\n }\n\n <input\n type=\"text\"\n class=\"sce-contact-form-panel__honeypot\"\n tabindex=\"-1\"\n autocomplete=\"off\"\n aria-hidden=\"true\"\n [value]=\"website()\"\n (input)=\"websiteChange.emit($any($event.target).value)\"\n />\n\n <div class=\"sce-contact-form-panel__fields\">\n <div class=\"sce-contact-form-panel__input\">\n <sce-text-field\n id=\"contact-full-name\"\n [label]=\"'contact.form.fullName' | translate\"\n [value]=\"fullName()\"\n (valueChange)=\"fullNameChange.emit($event)\"\n [placeholder]=\"'contact.form.fullNamePlaceholder' | translate\"\n [required]=\"true\"\n validationMode=\"onTouched\"\n [validationMessages]=\"fullNameValidationMessages()\"\n [error]=\"fullNameError()\"\n />\n </div>\n <div class=\"sce-contact-form-panel__input\">\n <sce-text-field\n id=\"contact-email\"\n [label]=\"'contact.form.email' | translate\"\n type=\"email\"\n [value]=\"email()\"\n (valueChange)=\"emailChange.emit($event)\"\n [placeholder]=\"'contact.form.emailPlaceholder' | translate\"\n [required]=\"true\"\n validationMode=\"onTouched\"\n [pattern]=\"emailPattern() ?? null\"\n [validationMessages]=\"emailValidationMessages()\"\n [error]=\"emailError()\"\n />\n </div>\n <div class=\"sce-contact-form-panel__select\">\n @if (messageTypesLoading()) {\n <div class=\"sce-contact-form-panel__input\">\n <sce-skeleton variant=\"text\" width=\"35%\" height=\"0.875rem\" animation=\"wave\" />\n <sce-skeleton variant=\"input\" animation=\"wave\" />\n </div>\n } @else {\n <sce-select-field\n id=\"contact-message-type\"\n [label]=\"'contact.form.messageType' | translate\"\n [options]=\"messageTypeOptions()\"\n [value]=\"messageType()\"\n (valueChange)=\"messageTypeChange.emit($event)\"\n [placeholder]=\"messageTypePlaceholder()\"\n [dir]=\"dir()\"\n [required]=\"true\"\n [borderless]=\"false\"\n [validationMessages]=\"messageTypeValidationMessages()\"\n [error]=\"messageTypeError()\"\n />\n }\n </div>\n <div class=\"sce-contact-form-panel__textarea\">\n <sce-textarea-field\n id=\"contact-message\"\n [label]=\"'contact.form.message' | translate\"\n [value]=\"message()\"\n (valueChange)=\"messageChange.emit($event)\"\n [placeholder]=\"'contact.form.messagePlaceholder' | translate\"\n [rows]=\"5\"\n [required]=\"true\"\n validationMode=\"onTouched\"\n [validationMessages]=\"messageValidationMessages()\"\n [error]=\"messageError()\"\n />\n </div>\n </div>\n\n <button type=\"submit\" class=\"sce-contact-form-panel__submit\" [disabled]=\"isSubmitDisabled()\">\n {{ submitLabel() }}\n </button>\n</form>\n", styles: [":host.sce-contact-form-panel{display:block}.sce-contact-form-panel__form{display:grid;gap:var(--space-24);background:var(--background-bg-primary);border-radius:var(--radius-2xl, var(--radius-2xl));padding:var(--space-30);height:100%}.sce-contact-form-panel__header{display:grid;gap:var(--space-8);text-align:start}.sce-contact-form-panel__title{margin:0;font-family:var(--font-family-arabic-primary);font-weight:700;font-size:var(--font-size-2xl, var(--font-size-24));line-height:1.35;color:var(--text-primary-emphasis)}.sce-contact-form-panel__subtitle{margin:0;font-family:var(--font-family-arabic-primary);font-weight:400;font-size:var(--font-size-md);line-height:1.6;color:var(--text-text-secondary)}.sce-contact-form-panel__feedback{margin:0;padding:var(--space-10) var(--space-14);border-radius:var(--radius-lg, var(--radius-lg));font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-contact-form-panel__feedback--success{background:var(--color-success-100);color:var(--color-success-700)}.sce-contact-form-panel__feedback--error{background:var(--color-error-50);color:var(--color-error-600)}.sce-contact-form-panel__honeypot{position:absolute;inset-inline-start:-9999px;opacity:0;pointer-events:none;tab-size:-1}.sce-contact-form-panel__fields{display:grid;gap:var(--space-20)}.sce-contact-form-panel__input,.sce-contact-form-panel__select,.sce-contact-form-panel__textarea{width:100%;min-width:0}.sce-contact-form-panel__submit{min-height:var(--size-52);border-radius:var(--radius-xl);border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);cursor:pointer;transition:opacity .15s ease}.sce-contact-form-panel__submit:disabled{opacity:.55;cursor:not-allowed}\n"] }]
11942
12141
  }], propDecorators: { dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], fullName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullName", required: true }] }], email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: true }] }], messageType: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageType", required: true }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], website: [{ type: i0.Input, args: [{ isSignal: true, alias: "website", required: false }] }], submitSuccess: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitSuccess", required: false }] }], submitError: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitError", required: false }] }], isSubmitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmitting", required: false }] }], isSubmitDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSubmitDisabled", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: true }] }], messageTypesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypesLoading", required: false }] }], messageTypeUnavailable: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypeUnavailable", required: false }] }], messageTypeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypeOptions", required: false }] }], messageTypePlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypePlaceholder", required: false }] }], fullNameError: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullNameError", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], messageTypeError: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypeError", required: false }] }], messageError: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageError", required: false }] }], emailPattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailPattern", required: false }] }], fullNameValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullNameValidationMessages", required: false }] }], emailValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailValidationMessages", required: false }] }], messageTypeValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageTypeValidationMessages", required: false }] }], messageValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageValidationMessages", required: false }] }], fullNameChange: [{ type: i0.Output, args: ["fullNameChange"] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], messageTypeChange: [{ type: i0.Output, args: ["messageTypeChange"] }], messageChange: [{ type: i0.Output, args: ["messageChange"] }], websiteChange: [{ type: i0.Output, args: ["websiteChange"] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }] } });
11943
12142
 
12143
+ /** Renders the platform settings list as read-only info cards or editable controls, emitting a typed update per field kind (boolean, integer, force-majeure durations). */
11944
12144
  class ScePlatformSettingsFieldsComponent {
11945
12145
  viewFields = input.required(...(ngDevMode ? [{ debugName: "viewFields" }] : /* istanbul ignore next */ []));
11946
12146
  isEditMode = input(false, ...(ngDevMode ? [{ debugName: "isEditMode" }] : /* istanbul ignore next */ []));
@@ -11959,6 +12159,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11959
12159
  args: [{ selector: 'sce-platform-settings-fields', standalone: true, imports: [TranslatePipe, SceInfoFieldCardComponent, SceInfoFieldsGridComponent, SceSwitchComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-platform-settings-fields' }, template: "<sce-info-fields-grid>\n @for (field of viewFields(); track field.apiKey) {\n @if (field.type === 'forceMajeureDurations') {\n <div class=\"ps-fields__fm-card\">\n <p class=\"ps-fields__fm-label\">{{ field.label }}</p>\n\n <div class=\"ps-fields__fm-group\">\n <p class=\"ps-fields__fm-group-title\">\n {{ 'dashboard.platformSettings.forceMajeure.notificationDays' | translate }}\n </p>\n <div class=\"ps-fields__fm-input-grid\">\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-nd-general'\">\n {{ 'dashboard.platformSettings.forceMajeure.general' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-nd-general'\"\n [value]=\"field.value.notificationDays.general\"\n [disabled]=\"saving()\"\n (input)=\"\n forceMajeureNotificationUpdate.emit({ apiKey: field.apiKey, sub: 'general', rawInput: $any($event.target).value })\n \"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.notificationDays.general }}</span>\n }\n </div>\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-nd-supervision'\">\n {{ 'dashboard.platformSettings.forceMajeure.supervision' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-nd-supervision'\"\n [value]=\"field.value.notificationDays.supervision\"\n [disabled]=\"saving()\"\n (input)=\"\n forceMajeureNotificationUpdate.emit({ apiKey: field.apiKey, sub: 'supervision', rawInput: $any($event.target).value })\n \"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.notificationDays.supervision }}</span>\n }\n </div>\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-nd-consultancy'\">\n {{ 'dashboard.platformSettings.forceMajeure.consultancy' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-nd-consultancy'\"\n [value]=\"field.value.notificationDays.consultancy\"\n [disabled]=\"saving()\"\n (input)=\"\n forceMajeureNotificationUpdate.emit({ apiKey: field.apiKey, sub: 'consultancy', rawInput: $any($event.target).value })\n \"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.notificationDays.consultancy }}</span>\n }\n </div>\n </div>\n </div>\n\n <div class=\"ps-fields__fm-group\">\n <p class=\"ps-fields__fm-group-title\">\n {{ 'dashboard.platformSettings.forceMajeure.extensionDays' | translate }}\n </p>\n <div class=\"ps-fields__fm-input-grid\">\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-ed-general'\">\n {{ 'dashboard.platformSettings.forceMajeure.general' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-ed-general'\"\n [value]=\"field.value.extensionDays.general\"\n [disabled]=\"saving()\"\n (input)=\"forceMajeureExtensionUpdate.emit({ apiKey: field.apiKey, sub: 'general', rawInput: $any($event.target).value })\"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.extensionDays.general }}</span>\n }\n </div>\n <div class=\"ps-fields__fm-input-row\">\n <label class=\"ps-fields__fm-input-label\" [for]=\"field.apiKey + '-ed-consultancy'\">\n {{ 'dashboard.platformSettings.forceMajeure.consultancy' | translate }}\n </label>\n @if (isEditMode()) {\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"field.apiKey + '-ed-consultancy'\"\n [value]=\"field.value.extensionDays.consultancy\"\n [disabled]=\"saving()\"\n (input)=\"\n forceMajeureExtensionUpdate.emit({ apiKey: field.apiKey, sub: 'consultancy', rawInput: $any($event.target).value })\n \"\n />\n } @else {\n <span class=\"ps-fields__fm-value\">{{ field.value.extensionDays.consultancy }}</span>\n }\n </div>\n </div>\n </div>\n </div>\n } @else if (field.type === 'boolean') {\n <sce-info-field-card [label]=\"field.label\">\n <sce-switch\n [checked]=\"field.value\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.status.active' | translate\"\n [inactiveLabel]=\"'dashboard.status.inactive' | translate\"\n [disabled]=\"!isEditMode() || saving()\"\n (checkedChange)=\"booleanUpdate.emit({ apiKey: field.apiKey, value: $event })\"\n />\n </sce-info-field-card>\n } @else {\n @if (isEditMode()) {\n <div class=\"ps-fields__int-field\">\n <label class=\"ps-fields__int-label\" [for]=\"'ps-' + field.apiKey\">{{ field.label }}</label>\n <input\n class=\"ps-fields__num-input\"\n type=\"text\"\n inputmode=\"numeric\"\n [id]=\"'ps-' + field.apiKey\"\n [value]=\"field.value\"\n [disabled]=\"saving()\"\n (input)=\"integerUpdate.emit({ apiKey: field.apiKey, rawInput: $any($event.target).value })\"\n />\n </div>\n } @else {\n <sce-info-field-card [label]=\"field.label\" [value]=\"'' + field.value\" />\n }\n }\n }\n</sce-info-fields-grid>\n\n@if (isEditMode()) {\n <div class=\"ps-fields__actions-row\">\n <button type=\"button\" class=\"ps-fields__btn ps-fields__btn--secondary\" [disabled]=\"saving()\" (click)=\"editCancel.emit()\">\n {{ 'dashboard.platformSettings.actions.cancel' | translate }}\n </button>\n <button type=\"button\" class=\"ps-fields__btn ps-fields__btn--primary\" [disabled]=\"saving()\" (click)=\"editSave.emit()\">\n {{ 'dashboard.platformSettings.actions.save' | translate }}\n </button>\n </div>\n}\n", styles: [".ps-fields__fm-card{grid-column:1/-1;display:grid;gap:var(--space-3);padding:var(--space-4);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--surface-primary)}.ps-fields__fm-label{margin:0;color:var(--text-text-primary-900);font-size:var(--font-size-lg);font-weight:600}.ps-fields__fm-group{padding:var(--space-3);border:1px solid var(--color-neutral-100);border-radius:var(--radius-10);display:grid;gap:var(--space-3)}.ps-fields__fm-group-title{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-md);font-weight:600}.ps-fields__fm-input-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:var(--space-3)}.ps-fields__fm-input-row{display:grid;gap:var(--space-1)}.ps-fields__fm-input-label{color:var(--color-neutral-700);font-size:var(--font-size-sm);font-weight:500}.ps-fields__fm-value{color:var(--details-value-color);font-size:var(--font-size-md);font-weight:600}.ps-fields__int-field{display:grid;gap:var(--space-1)}.ps-fields__int-label{color:var(--color-neutral-700);font-size:.85rem;font-weight:600}.ps-fields__num-input{height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);padding:0 var(--space-14, var(--space-14));font-family:var(--font-family-arabic-primary);font-size:var(--font-size-md);color:var(--details-value-color);outline:0;background:var(--surface-primary);width:100%;box-sizing:border-box}.ps-fields__num-input:disabled{opacity:.6;cursor:not-allowed}.ps-fields__actions-row{display:flex;align-items:center;gap:var(--space-10);flex-wrap:wrap}.ps-fields__btn{min-height:var(--space-48);border-radius:var(--radius-xl);padding:var(--space-8) var(--space-24);font-size:var(--font-size-md-15);font-weight:var(--font-weight-semibold);cursor:pointer}.ps-fields__btn:disabled{opacity:.55;cursor:not-allowed}.ps-fields__btn--primary{border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.ps-fields__btn--secondary{border:1px solid var(--button-background-primary-bg-primary);background:transparent;color:var(--button-background-primary-bg-primary)}\n"] }]
11960
12160
  }], propDecorators: { viewFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewFields", required: true }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: false }] }], saving: [{ type: i0.Input, args: [{ isSignal: true, alias: "saving", required: false }] }], booleanUpdate: [{ type: i0.Output, args: ["booleanUpdate"] }], integerUpdate: [{ type: i0.Output, args: ["integerUpdate"] }], forceMajeureNotificationUpdate: [{ type: i0.Output, args: ["forceMajeureNotificationUpdate"] }], forceMajeureExtensionUpdate: [{ type: i0.Output, args: ["forceMajeureExtensionUpdate"] }], editCancel: [{ type: i0.Output, args: ["editCancel"] }], editSave: [{ type: i0.Output, args: ["editSave"] }] } });
11961
12161
 
12162
+ /** Presentational entity-profile edit form bound to a caller-owned `FormGroup`; it holds no form state of its own and re-emits each field's raw input `Event` for the host to handle. */
11962
12163
  class SceEntityProfileEditFormComponent {
11963
12164
  form = input.required(...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
11964
12165
  dir = input('rtl', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
@@ -11993,6 +12194,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11993
12194
  ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-entity-profile-edit-form' }, template: "<section class=\"card\">\n <h3 class=\"sectionTitle\">\n {{ 'dashboard.entityProfile.entityData' | translate }}\n </h3>\n\n <form class=\"formContainer\" [formGroup]=\"form()\" (ngSubmit)=\"formSubmit.emit()\">\n <div class=\"formField\">\n <span class=\"formLabel\">{{ 'dashboard.entityProfile.entityName' | translate }}</span>\n <div class=\"formInputReadonly\">{{ entityName() || '\u2014' }}</div>\n </div>\n\n <div class=\"formField\">\n <span class=\"formLabel\">{{ 'dashboard.entityProfile.unifiedNumber' | translate }}</span>\n <div class=\"formInputReadonly\">{{ unifiedNumber() || '\u2014' }}</div>\n </div>\n\n <div class=\"formField\">\n <span class=\"formLabel\">{{ 'dashboard.entityProfile.entityType' | translate }}</span>\n <div class=\"formInputReadonly\">{{ entityType() || '\u2014' }}</div>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.mobileNumber' | translate }}\"\n type=\"phone\"\n formControlName=\"phone\"\n [required]=\"true\"\n [errorMessages]=\"{ pattern: 'dashboard.entityProfile.errors.phoneSaudiFormat' }\"\n (input)=\"phoneInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.email' | translate }}\"\n type=\"email\"\n formControlName=\"email\"\n [required]=\"true\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.licenseNumber' | translate }}\"\n type=\"number\"\n formControlName=\"licenseNumber\"\n [placeholder]=\"'dashboard.entityProfileEdit.licensePlaceholder' | translate\"\n [errorMessages]=\"{ pattern: 'dashboard.entityProfile.errors.licenseFormat' }\"\n (input)=\"licenseInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.taxRegistrationNumber' | translate }}\"\n type=\"number\"\n formControlName=\"taxRegistrationNumber\"\n [required]=\"true\"\n [placeholder]=\"'dashboard.entityProfileEdit.taxPlaceholder' | translate\"\n [errorMessages]=\"{ pattern: 'dashboard.entityProfile.errors.vatFormat' }\"\n (input)=\"taxInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.shortNationalAddress' | translate }}\"\n type=\"text\"\n formControlName=\"shortNationalAddress\"\n [required]=\"true\"\n [placeholder]=\"'dashboard.entityProfileEdit.addressPlaceholder' | translate\"\n [maxLengthOverride]=\"8\"\n [errorMessages]=\"{ pattern: 'dashboard.entityProfile.errors.addressFormat' }\"\n (input)=\"addressInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formField\">\n <sce-select-field\n id=\"bank\"\n [label]=\"'dashboard.entityProfile.bank' | translate\"\n [options]=\"bankOptions()\"\n [value]=\"selectedBankId()\"\n [dir]=\"dir()\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [required]=\"true\"\n [error]=\"bankError()\"\n [validationMode]=\"'never'\"\n [placeholder]=\"'dashboard.entityProfileEdit.bankPlaceholder' | translate\"\n (valueChange)=\"bankChange.emit($event)\"\n />\n </div>\n\n <div class=\"formField\">\n <sce-form-input\n label=\"{{ 'dashboard.entityProfile.bankAccount' | translate }}\"\n type=\"text\"\n formControlName=\"bankAccount\"\n [required]=\"true\"\n [placeholder]=\"'dashboard.entityProfileEdit.bankAccountPlaceholder' | translate\"\n [maxLengthOverride]=\"22\"\n [inlineSuffix]=\"'SA'\"\n [errorMessages]=\"{ invalidIban: 'dashboard.entityProfile.errors.ibanFormat' }\"\n (input)=\"ibanInput.emit($event)\"\n ></sce-form-input>\n </div>\n\n <div class=\"formActions\">\n <sce-button type=\"submit\" variant=\"primary\" size=\"large\" [disabled]=\"submitting()\" [loading]=\"submitting()\">\n {{ 'dashboard.entityProfileEdit.updateData' | translate }}\n </sce-button>\n <sce-button routerLink=\"/dashboard/entity-profile\" variant=\"outline\" size=\"large\">\n {{ 'common.cancel' | translate }}\n </sce-button>\n </div>\n </form>\n</section>\n", styles: [".card{background:var(--app-surface);border-radius:var(--radius-brand-sm);padding:clamp(1rem,4vi,var(--space-30));display:flex;flex-direction:column;gap:var(--space-16);width:100%;min-width:0;box-sizing:border-box;overflow:hidden}.sectionTitle{color:var(--color-violet-800);font-size:var(--space-20);font-weight:var(--font-weight-bold)}.formContainer{display:grid;grid-template-columns:1fr;gap:var(--space-20)}.formField{display:flex;flex-direction:column;gap:var(--space-8)}.formLabel{color:var(--details-label-color);font-size:var(--font-size-md);font-weight:var(--font-weight-medium)}.formRequired{color:var(--color-red-600);margin-inline-start:var(--space-1)}.formInput,.formInputReadonly{width:100%;min-height:var(--space-52, var(--size-52));border-radius:var(--radius-xl);font-size:var(--font-size-lg);color:var(--text-text-disabled);font-family:var(--font-family-arabic-primary);transition:border-color .2s}.formInput{border:1px solid var(--color-neutral-200);background:var(--background-bg-primary);padding:0 1rem}.formInput:focus{outline:none;border-color:var(--button-background-primary-bg-primary)}.formInputWithPrefix{position:relative;display:flex;align-items:center;width:100%}.formInputPrefix{position:absolute;inset-inline-start:var(--space-4);top:50%;transform:translateY(-50%);color:var(--color-muted-fg);-webkit-user-select:none;user-select:none;pointer-events:none;z-index:1}.formInput--prefixed{padding-inline-start:calc(var(--space-4) + var(--space-24))}.formInputReadonly{display:flex;align-items:center;box-sizing:border-box;border:1px solid var(--color-neutral-200);background:var(--details-row-bg);color:var(--details-value-color);cursor:default;padding:0 1rem}.inputError{border-color:var(--color-red-600)}.inputError:focus{border-color:var(--color-red-600)}.errorText{color:var(--color-red-600);font-size:var(--font-size-xs);margin-block-start:var(--space-4)}.formActions{display:flex;gap:var(--space-12);direction:ltr}.primaryButton,.secondaryButton{min-width:var(--size-200);height:var(--space-52, var(--size-52));border-radius:var(--radius-xl);font-weight:var(--font-weight-semibold);text-decoration:none;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;font-size:var(--font-size-lg)}.primaryButton{border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.primaryButton:disabled{opacity:.7;cursor:not-allowed}.secondaryButton{border:1px solid var(--button-background-primary-bg-primary);color:var(--button-background-primary-bg-primary);background:transparent}@media(max-width:768px){.formActions{flex-direction:column;align-items:stretch}.primaryButton,.secondaryButton{width:100%;min-width:0;box-sizing:border-box}}\n"] }]
11994
12195
  }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], entityName: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityName", required: false }] }], entityType: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityType", required: false }] }], unifiedNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "unifiedNumber", required: false }] }], bankOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankOptions", required: false }] }], selectedBankId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedBankId", required: false }] }], bankError: [{ type: i0.Input, args: [{ isSignal: true, alias: "bankError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], phoneInput: [{ type: i0.Output, args: ["phoneInput"] }], licenseInput: [{ type: i0.Output, args: ["licenseInput"] }], taxInput: [{ type: i0.Output, args: ["taxInput"] }], addressInput: [{ type: i0.Output, args: ["addressInput"] }], ibanInput: [{ type: i0.Output, args: ["ibanInput"] }], bankChange: [{ type: i0.Output, args: ["bankChange"] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }] } });
11995
12196
 
12197
+ /** Title bar with account-users / engineering-staff tabs and an optional Add button (`showAddButton`, off by default); it emits clicks and never switches `activeTab` itself. */
11996
12198
  class SceAccountUsersTabsBarComponent {
11997
12199
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
11998
12200
  activeTab = input.required(...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
@@ -12008,6 +12210,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12008
12210
  args: [{ selector: 'sce-account-users-tabs-bar', standalone: true, imports: [TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-users-tabs-bar' }, template: "<div class=\"sce-account-users-tabs-bar__header\">\n <h2 class=\"sce-account-users-tabs-bar__title\">{{ title() }}</h2>\n @if (showAddButton() && activeTab() === 'account-users') {\n <button class=\"sce-account-users-tabs-bar__add-btn\" type=\"button\" (click)=\"addUserClick.emit()\">\n {{ 'dashboard.users.addUser' | translate }}\n </button>\n }\n</div>\n\n<div class=\"sce-account-users-tabs-bar__tabs\">\n <div>\n <button\n class=\"sce-account-users-tabs-bar__tab-btn\"\n [class.sce-account-users-tabs-bar__tab-btn--active]=\"activeTab() === 'account-users'\"\n type=\"button\"\n (click)=\"accountUsersTabClick.emit()\"\n >\n {{ 'dashboard.accountUsers.tabs.accountUsers' | translate }}\n </button>\n <button\n class=\"sce-account-users-tabs-bar__tab-btn\"\n [class.sce-account-users-tabs-bar__tab-btn--active]=\"activeTab() === 'engineering-staff'\"\n type=\"button\"\n (click)=\"staffTabClick.emit()\"\n >\n {{ 'dashboard.accountUsers.tabs.engineeringStaff' | translate }}\n </button>\n </div>\n @if (activeTab() === 'engineering-staff') {\n <p class=\"sce-account-users-tabs-bar__hint\">\n {{ 'dashboard.accountUsers.engineeringStaff.staffHint' | translate }}\n </p>\n }\n</div>\n", styles: [":host.sce-account-users-tabs-bar{display:block}.sce-account-users-tabs-bar__header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);margin-block-end:var(--space-4)}.sce-account-users-tabs-bar__title{font-size:var(--font-size-xl);font-weight:500;color:var(--text-text-display);margin:0}.sce-account-users-tabs-bar__add-btn{border:0;border-radius:var(--radius-md);padding:var(--space-12) var(--space-24);display:inline-flex;align-items:center;justify-content:center;gap:var(--space-4);background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);cursor:pointer}.sce-account-users-tabs-bar__tabs{display:flex;gap:0;border-block-end:1px solid var(--color-neutral-200);margin-block-end:var(--space-20);justify-content:space-between;align-items:center}.sce-account-users-tabs-bar__tab-btn{padding:var(--space-10) var(--space-24);border:0;border-block-end:var(--space-2) solid transparent;background:transparent;color:var(--text-text-secondary);font-size:var(--font-size-md);font-weight:var(--font-weight-medium);cursor:pointer;transition:color .15s ease,border-color .15s ease;margin-block-end:-1px}.sce-account-users-tabs-bar__tab-btn:hover{color:var(--text-text-brand-primary)}.sce-account-users-tabs-bar__tab-btn--active{color:var(--text-text-brand-primary);border-block-end-color:var(--button-background-primary-bg-primary);font-weight:var(--font-weight-semibold)}.sce-account-users-tabs-bar__hint{color:var(--color-brand-primary-600);font-size:var(--font-size-sm);margin-block-end:var(--space-12)}\n"] }]
12009
12211
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: true }] }], showAddButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAddButton", required: false }] }], accountUsersTabClick: [{ type: i0.Output, args: ["accountUsersTabClick"] }], staffTabClick: [{ type: i0.Output, args: ["staffTabClick"] }], addUserClick: [{ type: i0.Output, args: ["addUserClick"] }] } });
12010
12212
 
12213
+ /** Dialog that collects a national ID and birth date (Hijri or Gregorian via `calendarSystem`) to verify a user before assigning them; fully controlled, emitting `submitVerify` rather than calling any API. */
12011
12214
  class SceAccountUserVerifyDialogComponent {
12012
12215
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
12013
12216
  locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -12030,6 +12233,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12030
12233
  args: [{ selector: 'sce-account-user-verify-dialog', standalone: true, imports: [FormsModule, TranslatePipe, SceDialogShellComponent, SceDateFieldComponent, SceInlineApiErrorComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-verify-dialog' }, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"'dashboard.accountUsers.dialog.addTitle' | translate\"\n [subtitle]=\"'dashboard.accountUsers.dialog.verifyDescription' | translate\"\n size=\"md\"\n [centerHeader]=\"false\"\n [style]=\"{ 'min-height': '380px' }\"\n (close)=\"dialogClose.emit()\"\n>\n <div class=\"sce-account-user-verify-dialog__group\">\n <div class=\"sce-account-user-verify-dialog__field\">\n <p class=\"sce-account-user-verify-dialog__label\">{{ 'dashboard.accountUsers.dialog.nationalId' | translate }} *</p>\n <input\n class=\"sce-account-user-verify-dialog__input\"\n [class.sce-account-user-verify-dialog__input--error]=\"nationalIdError()\"\n [placeholder]=\"'dashboard.accountUsers.dialog.nationalIdPlaceholder' | translate\"\n inputmode=\"numeric\"\n maxlength=\"10\"\n [ngModel]=\"nationalId()\"\n (ngModelChange)=\"nationalIdChange.emit($event)\"\n />\n @if (nationalIdError()) {\n <p class=\"sce-account-user-verify-dialog__error\">{{ nationalIdError() }}</p>\n }\n </div>\n <div class=\"sce-account-user-verify-dialog__field\">\n <sce-date-field\n id=\"verify-birth-date\"\n [label]=\"'dashboard.accountUsers.dialog.birthDate' | translate\"\n [calendarSystem]=\"calendarSystem()\"\n [locale]=\"locale()\"\n [value]=\"birthDate()\"\n [error]=\"birthDateError()\"\n displayFormat=\"iso\"\n [showIcon]=\"true\"\n (valueChange)=\"birthDateChange.emit($event)\"\n />\n </div>\n @if (actionError()) {\n <sce-inline-api-error [message]=\"actionError()\" />\n }\n </div>\n <div class=\"sce-account-user-verify-dialog__actions\" dialogFooter>\n <button\n class=\"sce-account-user-verify-dialog__btn sce-account-user-verify-dialog__btn--secondary\"\n type=\"button\"\n (click)=\"dialogClose.emit()\"\n >\n {{ 'dashboard.accountUsers.dialog.cancel' | translate }}\n </button>\n <button\n class=\"sce-account-user-verify-dialog__btn sce-account-user-verify-dialog__btn--primary\"\n type=\"button\"\n [disabled]=\"submitting()\"\n (click)=\"submitVerify.emit()\"\n >\n {{ 'dashboard.accountUsers.dialog.verify' | translate }}\n </button>\n </div>\n</sce-dialog-shell>\n", styles: [":host.sce-account-user-verify-dialog{display:contents}.sce-account-user-verify-dialog__group{display:grid;gap:var(--space-12)}.sce-account-user-verify-dialog__field{display:grid;gap:.4rem;width:100%;min-width:0}.sce-account-user-verify-dialog__label{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--details-label-weight)}.sce-account-user-verify-dialog__input{width:100%;box-sizing:border-box;height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl, var(--radius-xl));background:var(--color-surface);padding:var(--space-12) var(--space-16);font-size:var(--font-size-md);font-weight:var(--font-weight-normal);color:var(--color-neutral-500);outline:0}.sce-account-user-verify-dialog__input::placeholder{color:var(--color-neutral-500)}.sce-account-user-verify-dialog__input--error{border:1.5px solid var(--text-text-error-primary)}.sce-account-user-verify-dialog__input--error:focus{border-color:var(--text-text-error-primary)}.sce-account-user-verify-dialog__error{color:var(--text-text-error-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-account-user-verify-dialog__actions{display:flex;gap:.6rem}.sce-account-user-verify-dialog__btn{border-radius:var(--radius-10);padding:var(--space-10) var(--space-24);font-size:var(--font-size-md-15);font-weight:var(--font-weight-semibold);cursor:pointer;width:50%}.sce-account-user-verify-dialog__btn:disabled{opacity:.55;cursor:not-allowed}.sce-account-user-verify-dialog__btn--primary{border:0;flex:1;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.sce-account-user-verify-dialog__btn--secondary{border:1px solid var(--button-background-primary-bg-primary);background:transparent;color:var(--button-background-primary-bg-primary)}\n"] }]
12031
12234
  }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], nationalId: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalId", required: true }] }], nationalIdError: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalIdError", required: false }] }], birthDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDate", required: true }] }], birthDateError: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDateError", required: false }] }], calendarSystem: [{ type: i0.Input, args: [{ isSignal: true, alias: "calendarSystem", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], actionError: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionError", required: false }] }], dialogClose: [{ type: i0.Output, args: ["dialogClose"] }], nationalIdChange: [{ type: i0.Output, args: ["nationalIdChange"] }], birthDateChange: [{ type: i0.Output, args: ["birthDateChange"] }], submitVerify: [{ type: i0.Output, args: ["submitVerify"] }] } });
12032
12235
 
12236
+ /** Dialog for assigning an account user roles and contact details; fully controlled — it mutates nothing, emitting every field change and `submitAssign` to the host — and uses `ViewEncapsulation.None`. */
12033
12237
  class SceAccountUserAssignDialogComponent {
12034
12238
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
12035
12239
  locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -12058,6 +12262,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12058
12262
  args: [{ selector: 'sce-account-user-assign-dialog', standalone: true, imports: [FormsModule, TranslatePipe, MultiSelect, SceDialogShellComponent, SceSwitchComponent, SceSkeleton], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-assign-dialog' }, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"'dashboard.accountUsers.dialog.addTitle' | translate\"\n [subtitle]=\"description()\"\n size=\"md\"\n [centerHeader]=\"false\"\n (close)=\"dialogClose.emit()\"\n>\n <div class=\"sce-account-user-assign-dialog__readonly-grid\">\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.nationalId' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().nationalId || '\u2014' }}</p>\n </div>\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.birthDate' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().birthDate || '\u2014' }}</p>\n </div>\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.fullName' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().userName || '\u2014' }}</p>\n </div>\n @if (requireEmail()) {\n <div class=\"sce-account-user-assign-dialog__field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.email' | translate }} *</p>\n <input\n class=\"sce-account-user-assign-dialog__input\"\n [class.sce-account-user-assign-dialog__input--error]=\"emailError()\"\n [ngModel]=\"assignForm().email\"\n (ngModelChange)=\"emailChange.emit($event)\"\n inputmode=\"email\"\n />\n @if (emailError()) {\n <p class=\"sce-account-user-assign-dialog__error\">{{ emailError() }}</p>\n }\n </div>\n } @else {\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.email' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().email || '\u2014' }}</p>\n </div>\n }\n @if (requireMobile()) {\n <div class=\"sce-account-user-assign-dialog__field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.mobile' | translate }} *</p>\n <input\n class=\"sce-account-user-assign-dialog__input\"\n [class.sce-account-user-assign-dialog__input--error]=\"mobileError()\"\n [ngModel]=\"assignForm().mobile\"\n (ngModelChange)=\"mobileChange.emit($event)\"\n inputmode=\"numeric\"\n maxlength=\"15\"\n />\n @if (mobileError()) {\n <p class=\"sce-account-user-assign-dialog__error\">{{ mobileError() }}</p>\n }\n </div>\n } @else {\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <p class=\"sce-account-user-assign-dialog__label\">{{ 'dashboard.accountUsers.dialog.mobile' | translate }}</p>\n <p class=\"sce-account-user-assign-dialog__value\">{{ assignForm().mobile || '\u2014' }}</p>\n </div>\n }\n </div>\n\n <div class=\"sce-account-user-assign-dialog__group\">\n <h4 class=\"sce-account-user-assign-dialog__group-title\">{{ 'dashboard.accountUsers.dialog.permissions' | translate }}</h4>\n <div class=\"sce-account-user-assign-dialog__multi-select\">\n @if (rolesLoading()) {\n <sce-skeleton variant=\"input\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n <p-multiSelect\n [options]=\"roleOptions()\"\n [ngModel]=\"assignForm().roleIds\"\n (ngModelChange)=\"roleIdsChange.emit($event)\"\n display=\"chip\"\n [selectedItemsLabel]=\"'dashboard.accountUsers.dialog.selectedItems' | translate\"\n [placeholder]=\"'dashboard.accountUsers.dialog.selectPermissions' | translate\"\n optionLabel=\"label\"\n optionValue=\"value\"\n appendTo=\"body\"\n />\n }\n </div>\n @if (rolesError()) {\n <p class=\"sce-account-user-assign-dialog__error\">{{ rolesError() }}</p>\n }\n\n <div class=\"sce-account-user-assign-dialog__status-row\">\n <div class=\"sce-account-user-assign-dialog__readonly-field\">\n <h4 class=\"sce-account-user-assign-dialog__group-title sce-account-user-assign-dialog__status-title\">\n {{ 'dashboard.accountUsers.dialog.userStatus' | translate }}\n </h4>\n <sce-switch\n [checked]=\"assignForm().isActive\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.accountUsers.dialog.active' | translate\"\n [inactiveLabel]=\"'dashboard.accountUsers.dialog.inactive' | translate\"\n (checkedChange)=\"isActiveChange.emit($event)\"\n />\n </div>\n </div>\n\n @if (actionError()) {\n <p class=\"sce-account-user-assign-dialog__error\">{{ actionError() }}</p>\n }\n </div>\n\n <div class=\"sce-account-user-assign-dialog__actions\" dialogFooter>\n <button\n class=\"sce-account-user-assign-dialog__btn sce-account-user-assign-dialog__btn--secondary\"\n type=\"button\"\n (click)=\"dialogClose.emit()\"\n >\n {{ 'dashboard.accountUsers.dialog.cancel' | translate }}\n </button>\n <button\n class=\"sce-account-user-assign-dialog__btn sce-account-user-assign-dialog__btn--primary\"\n type=\"button\"\n [disabled]=\"submitting()\"\n (click)=\"submitAssign.emit()\"\n >\n {{ 'dashboard.accountUsers.dialog.addUser' | translate }}\n </button>\n </div>\n</sce-dialog-shell>\n", styles: [".sce-account-user-assign-dialog__readonly-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}@media(max-width:640px){.sce-account-user-assign-dialog__readonly-grid{grid-template-columns:1fr}}.sce-account-user-assign-dialog__readonly-field{background:var(--app-surface-hover);border-radius:var(--radius-xl, var(--radius-xl));min-height:var(--size-89);padding:var(--space-16);display:grid;align-content:center;gap:var(--space-8);width:100%}.sce-account-user-assign-dialog__field{display:grid;gap:.4rem;width:100%;min-width:0}.sce-account-user-assign-dialog__label{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--details-label-weight)}.sce-account-user-assign-dialog__value{color:var(--details-value-color);font-size:var(--details-value-size);font-weight:var(--details-value-weight)}.sce-account-user-assign-dialog__input{width:100%;box-sizing:border-box;height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl, var(--radius-xl));background:var(--color-surface);padding:var(--space-12) var(--space-16);font-size:var(--font-size-md);color:var(--color-neutral-500);outline:0}.sce-account-user-assign-dialog__input--error{border:1.5px solid var(--text-text-error-primary)}.sce-account-user-assign-dialog__group{display:grid;gap:var(--space-12)}.sce-account-user-assign-dialog__group-title{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--details-label-weight)}.sce-account-user-assign-dialog__multi-select{width:100%;min-width:0}.sce-account-user-assign-dialog__multi-select .p-multiselect{width:100%;min-height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl, var(--radius-xl));background:var(--color-surface);font-size:var(--font-size-md)}.sce-account-user-assign-dialog__status-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-12);width:100%}.sce-account-user-assign-dialog__status-title{color:var(--details-label-color);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);text-align:start}.sce-account-user-assign-dialog__error{color:var(--text-text-error-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-account-user-assign-dialog__actions{display:flex;gap:.6rem}.sce-account-user-assign-dialog__btn{border-radius:var(--radius-10);padding:var(--space-10) var(--space-24);font-size:var(--font-size-md-15);font-weight:var(--font-weight-semibold);cursor:pointer;width:50%}.sce-account-user-assign-dialog__btn:disabled{opacity:.55;cursor:not-allowed}.sce-account-user-assign-dialog__btn--primary{border:0;flex:1;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.sce-account-user-assign-dialog__btn--secondary{border:1px solid var(--button-background-primary-bg-primary);background:transparent;color:var(--button-background-primary-bg-primary)}\n"] }]
12059
12263
  }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: true }] }], assignForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignForm", required: true }] }], requireEmail: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireEmail", required: false }] }], requireMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "requireMobile", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], mobileError: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileError", required: false }] }], rolesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesLoading", required: false }] }], roleOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleOptions", required: false }] }], rolesError: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesError", required: false }] }], actionError: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], dialogClose: [{ type: i0.Output, args: ["dialogClose"] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], mobileChange: [{ type: i0.Output, args: ["mobileChange"] }], roleIdsChange: [{ type: i0.Output, args: ["roleIdsChange"] }], isActiveChange: [{ type: i0.Output, args: ["isActiveChange"] }], submitAssign: [{ type: i0.Output, args: ["submitAssign"] }] } });
12060
12264
 
12265
+ /** Dialog for editing an existing account user's roles and active state over a read-only identity summary; fully controlled and uses `ViewEncapsulation.None`. */
12061
12266
  class SceAccountUserEditDialogComponent {
12062
12267
  visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
12063
12268
  locale = input.required(...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
@@ -12084,6 +12289,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12084
12289
  args: [{ selector: 'sce-account-user-edit-dialog', standalone: true, imports: [FormsModule, TranslatePipe, MultiSelect, SceDialogShellComponent, SceSwitchComponent, SceSkeleton], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-edit-dialog' }, template: "<sce-dialog-shell\n [visible]=\"visible()\"\n [locale]=\"locale()\"\n [title]=\"title()\"\n [subtitle]=\"subtitle()\"\n size=\"md\"\n [centerHeader]=\"false\"\n (close)=\"closed.emit()\"\n>\n @if (readOnlyFields().length) {\n <div class=\"sce-account-user-edit-dialog__readonly-grid\">\n @for (field of readOnlyFields(); track field.label) {\n <div\n class=\"sce-account-user-edit-dialog__readonly-field\"\n [class.sce-account-user-edit-dialog__readonly-field--full-width]=\"field.fullWidth\"\n >\n <p class=\"sce-account-user-edit-dialog__label\">{{ field.label }}</p>\n <p class=\"sce-account-user-edit-dialog__value\">{{ field.value || '\u2014' }}</p>\n </div>\n }\n </div>\n }\n\n <div class=\"sce-account-user-edit-dialog__group\">\n <h4 class=\"sce-account-user-edit-dialog__group-title\">{{ 'DASHBOARD.STAFF_DETAIL.PERMISSIONS' | translate }} *</h4>\n <div class=\"sce-account-user-edit-dialog__multi-select\">\n @if (rolesLoading()) {\n <sce-skeleton variant=\"input\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n <p-multiSelect\n [options]=\"roleOptions()\"\n [ngModel]=\"draftRoleIds()\"\n (ngModelChange)=\"draftRoleIdsChange.emit($event)\"\n display=\"chip\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'DASHBOARD.STAFF_DETAIL.SELECT_PERMISSION_PLACEHOLDER' | translate\"\n [selectedItemsLabel]=\"'DASHBOARD.STAFF_DETAIL.SELECTED_ITEMS' | translate\"\n appendTo=\"body\"\n />\n }\n </div>\n @if (permissionsError()) {\n <p class=\"sce-account-user-edit-dialog__error\">{{ permissionsError() }}</p>\n }\n\n <div class=\"sce-account-user-edit-dialog__status-card\">\n <p class=\"sce-account-user-edit-dialog__label\">\n {{ 'DASHBOARD.STAFF_DETAIL.USER_STATUS' | translate }}\n </p>\n <div class=\"sce-account-user-edit-dialog__status-switch\">\n <sce-switch\n [checked]=\"isActive()\"\n [showLabel]=\"true\"\n [activeLabel]=\"'DASHBOARD.STAFF_DETAIL.STATUS_ACTIVE' | translate\"\n [inactiveLabel]=\"'DASHBOARD.STAFF_DETAIL.STATUS_INACTIVE' | translate\"\n (checkedChange)=\"isActiveChange.emit($event)\"\n />\n </div>\n </div>\n\n @if (dialogError()) {\n <p class=\"sce-account-user-edit-dialog__error\">{{ dialogError() }}</p>\n }\n </div>\n\n <div class=\"sce-account-user-edit-dialog__actions\" dialogFooter>\n <button class=\"sce-account-user-edit-dialog__btn sce-account-user-edit-dialog__btn--secondary\" type=\"button\" (click)=\"closed.emit()\">\n {{ 'DASHBOARD.STAFF_DETAIL.CANCEL' | translate }}\n </button>\n <button\n class=\"sce-account-user-edit-dialog__btn sce-account-user-edit-dialog__btn--primary\"\n type=\"button\"\n [disabled]=\"submitting()\"\n (click)=\"submitted.emit()\"\n >\n {{ submitLabel() }}\n </button>\n </div>\n</sce-dialog-shell>\n", styles: ["@charset \"UTF-8\";.sce-account-user-edit-dialog__readonly-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-3);margin-block-end:var(--space-5)}@media(max-width:576px){.sce-account-user-edit-dialog__readonly-grid{grid-template-columns:1fr}}.sce-account-user-edit-dialog__readonly-field{background:var(--app-surface-hover);border-radius:var(--radius-lg);min-height:var(--space-80);padding:var(--space-3-5) var(--space-4-5);display:flex;flex-direction:column;justify-content:center;gap:var(--space-24);width:100%}.sce-account-user-edit-dialog__readonly-field--full-width{grid-column:1/-1}.sce-account-user-edit-dialog__label{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--details-label-weight);margin:0;text-align:start}.sce-account-user-edit-dialog__value{color:var(--details-value-color);font-size:var(--details-value-size);font-weight:var(--details-value-weight);margin:0;text-align:start}.sce-account-user-edit-dialog__group{display:flex;flex-direction:column;gap:var(--space-2);margin-block-end:var(--space-5)}.sce-account-user-edit-dialog__group-title{color:var(--details-label-color);font-size:var(--details-label-size);font-weight:var(--font-weight-bold);margin:0;text-align:start}.sce-account-user-edit-dialog__multi-select{width:100%;min-width:0}.sce-account-user-edit-dialog__multi-select .p-multiselect{width:100%;min-height:var(--space-56);border:1px solid var(--color-neutral-200);border-radius:var(--radius-lg);background:var(--color-surface);font-size:var(--font-size-md);display:flex;align-items:center;box-shadow:none}.sce-account-user-edit-dialog__multi-select .p-multiselect:not(.p-disabled):hover{border-color:var(--color-neutral-300)}.sce-account-user-edit-dialog__multi-select .p-multiselect:not(.p-disabled).p-focus{border-color:var(--color-brand-primary-500);box-shadow:0 0 0 2px color-mix(in srgb,var(--color-brand-primary-500) 10%,transparent)}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-label-container{padding:0;width:100%;display:flex}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-label{padding:var(--space-3) var(--space-4);display:flex;flex-wrap:wrap;gap:var(--space-2);align-items:center;width:100%}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-label:has(.p-multiselect-token){padding:var(--space-24) var(--space-4)}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-token{display:inline-flex;flex-direction:row-reverse;align-items:center;background:var(--color-neutral-100);color:var(--color-neutral-700);border-radius:var(--radius-full);padding:var(--space-24) var(--space-4);gap:var(--space-2-5);margin-block:var(--space-2);border:none}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-token .p-multiselect-token-label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-token .p-multiselect-token-icon{font-size:var(--font-size-md);color:var(--color-neutral-600);margin:0;cursor:pointer}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-token .p-multiselect-token-icon:before{content:\"\\d7\"}.sce-account-user-edit-dialog__multi-select .p-multiselect .p-multiselect-trigger{color:var(--color-neutral-600)}.sce-account-user-edit-dialog__status-card{background:var(--app-surface-hover);border-radius:var(--radius-lg);padding:var(--space-3-5) var(--space-4-5);min-height:var(--space-64);margin-block-start:var(--space-1)}.sce-account-user-edit-dialog__status-card .sce-account-user-edit-dialog__label{font-weight:var(--font-weight-bold)}.sce-account-user-edit-dialog__status-switch{margin-block-start:var(--space-2)}.sce-account-user-edit-dialog__status-switch sce-switch{display:inline-flex;align-items:center}.sce-account-user-edit-dialog__status-switch sce-switch .sce-switch-label{font-size:var(--font-size-md-15);font-weight:var(--font-weight-bold);color:var(--color-success-600)}.sce-account-user-edit-dialog__status-switch sce-switch .sce-switch-label--inactive{color:var(--color-neutral-600)}.sce-account-user-edit-dialog__error{color:var(--text-text-error-primary);font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);margin:0;text-align:start}.sce-account-user-edit-dialog__actions{display:flex;gap:var(--space-4);margin-block-start:var(--space-24);width:100%}.sce-account-user-edit-dialog__btn{flex:1;min-height:var(--size-54);border-radius:var(--radius-lg);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .2s ease-in-out}.sce-account-user-edit-dialog__btn:disabled{opacity:.55;cursor:not-allowed}.sce-account-user-edit-dialog__btn--primary{border:0;background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand)}.sce-account-user-edit-dialog__btn--secondary{border:1px solid var(--button-background-primary-bg-primary);background:var(--color-surface);color:var(--button-background-primary-bg-primary)}\n"] }]
12085
12290
  }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: true }] }], readOnlyFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnlyFields", required: false }] }], roleOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleOptions", required: false }] }], draftRoleIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "draftRoleIds", required: false }] }], rolesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesLoading", required: false }] }], isActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isActive", required: false }] }], permissionsError: [{ type: i0.Input, args: [{ isSignal: true, alias: "permissionsError", required: false }] }], dialogError: [{ type: i0.Input, args: [{ isSignal: true, alias: "dialogError", required: false }] }], submitting: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitting", required: false }] }], submitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitLabel", required: true }] }], closed: [{ type: i0.Output, args: ["closed"] }], submitted: [{ type: i0.Output, args: ["submitted"] }], draftRoleIdsChange: [{ type: i0.Output, args: ["draftRoleIdsChange"] }], isActiveChange: [{ type: i0.Output, args: ["isActiveChange"] }] } });
12086
12291
 
12292
+ /** Header of an account-user detail page: name, status tags, membership/national-ID badges, and an Edit button; all labels are passed in already translated. */
12087
12293
  class SceAccountUserDetailHeaderComponent {
12088
12294
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
12089
12295
  statusTags = input([], ...(ngDevMode ? [{ debugName: "statusTags" }] : /* istanbul ignore next */ []));
@@ -12099,6 +12305,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12099
12305
  args: [{ selector: 'sce-account-user-detail-header', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-detail-header' }, imports: [SceBusinessStatusTagComponent], template: "<div class=\"sce-account-user-detail-header__left\">\n <div class=\"sce-account-user-detail-header__name-wrap\">\n <div class=\"sce-account-user-detail-header__title-row\">\n <h2 class=\"sce-account-user-detail-header__title\">{{ title() }}</h2>\n @if (membershipBadge(); as badge) {\n <span class=\"sce-account-user-detail-header__badge\">\n <span class=\"sce-account-user-detail-header__badge-label\">{{ badge.label }}</span>\n <span class=\"sce-account-user-detail-header__badge-value\">{{ badge.value }}</span>\n </span>\n }\n </div>\n <div class=\"sce-account-user-detail-header__status-row\">\n @for (tag of statusTags(); track tag.label) {\n <sce-business-status-tag [label]=\"tag.label\" [tone]=\"tag.tone\" size=\"sm\" />\n }\n </div>\n </div>\n</div>\n<div class=\"sce-account-user-detail-header__actions\">\n @if (nationalIdBadge(); as badge) {\n <span class=\"sce-account-user-detail-header__badge\">\n <span class=\"sce-account-user-detail-header__badge-label\">{{ badge.label }}</span>\n <span class=\"sce-account-user-detail-header__badge-value\">{{ badge.value }}</span>\n </span>\n }\n <button type=\"button\" class=\"sce-account-user-detail-header__edit-btn\" (click)=\"editClick.emit()\">\n {{ editButtonLabel() }}\n </button>\n</div>\n", styles: [":host{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);flex-wrap:wrap;margin-block-end:var(--space-5)}@media(max-width:768px){:host{flex-direction:column;align-items:stretch}}.sce-account-user-detail-header__left{display:flex;flex-direction:column;gap:var(--space-2);flex:1;min-width:0}.sce-account-user-detail-header__name-wrap{display:flex;flex-direction:column;gap:var(--space-2);min-width:0}.sce-account-user-detail-header__title-row{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap}.sce-account-user-detail-header__title{font-size:var(--font-size-xl);font-weight:700;color:var(--color-neutral-950, var(--color-neutral-900));margin:0;overflow-wrap:anywhere}.sce-account-user-detail-header__badge{background:var(--color-neutral-100, var(--app-surface-muted));border-radius:var(--radius-full, var(--radius-100));padding:var(--space-1) var(--space-3);display:inline-flex;align-items:center;gap:var(--space-1-5, var(--space-6));font-size:var(--font-size-2xs, var(--font-size-11));font-family:var(--font-family-arabic-primary)}.sce-account-user-detail-header__badge-label{color:var(--color-neutral-500, var(--text-text-secondary-600));font-weight:500}.sce-account-user-detail-header__badge-value{color:var(--color-neutral-950, var(--color-neutral-900));font-weight:700}.sce-account-user-detail-header__status-row{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;margin-block-start:var(--space-2)}.sce-account-user-detail-header__status-row sce-business-status-tag span.tag,.sce-account-user-detail-header__status-row sce-business-status-tag .tag,.sce-account-user-detail-header__status-row sce-business-status-tag .sce-tag,.sce-account-user-detail-header__status-row sce-business-status-tag .sce-tag--sm,.sce-account-user-detail-header__status-row sce-business-status-tag .tag--sm{border-radius:var(--radius-full);padding:var(--space-1) var(--space-3);font-size:var(--font-size-2xs, var(--font-size-11));font-weight:var(--font-weight-bold);border:none;background-color:var(--color-success-50, var(--color-kiwi-200));color:var(--color-success-700, var(--color-kiwi-600))}.sce-account-user-detail-header__actions{display:flex;align-items:center;gap:var(--space-4)}.sce-account-user-detail-header__edit-btn{padding:var(--space-3) var(--space-7, var(--space-28));border-radius:var(--radius-lg);background:var(--color-brand-primary-900, var(--color-brand-primary-800));color:var(--color-white, var(--background-bg-primary));font-size:var(--font-size-sm);font-weight:700;border:none;cursor:pointer;white-space:nowrap;height:fit-content;transition:background var(--duration-fast, .2s) ease-in-out}.sce-account-user-detail-header__edit-btn:hover{background:var(--color-brand-primary-950, var(--color-brand-primary-900))}@media(max-width:768px){.sce-account-user-detail-header__edit-btn{width:100%;box-sizing:border-box}}\n"] }]
12100
12306
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], statusTags: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusTags", required: false }] }], membershipBadge: [{ type: i0.Input, args: [{ isSignal: true, alias: "membershipBadge", required: false }] }], nationalIdBadge: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalIdBadge", required: false }] }], editButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "editButtonLabel", required: true }] }], editClick: [{ type: i0.Output, args: ["editClick"] }] } });
12101
12307
 
12308
+ /** Titled grid of read-only personal-detail `fields` for an account user; labels and values arrive already translated and formatted. */
12102
12309
  class SceAccountUserPersonalSectionComponent {
12103
12310
  title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
12104
12311
  fields = input.required(...(ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []));
@@ -12110,6 +12317,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12110
12317
  args: [{ selector: 'sce-account-user-personal-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-personal-section' }, imports: [SceInfoFieldCardComponent, SceInfoFieldsGridComponent], template: "<h3 class=\"sce-account-user-personal-section__title\">{{ title() }}</h3>\n<sce-info-fields-grid gap=\"sm\">\n @for (field of fields(); track field.label) {\n <sce-info-field-card [label]=\"field.label\" [value]=\"field.value ?? ''\" [fullWidth]=\"field.fullWidth ?? false\" />\n }\n</sce-info-fields-grid>\n", styles: [":host{display:block}.sce-account-user-personal-section__title{font-size:var(--font-size-xl, var(--font-size-xl));font-weight:700;color:var(--color-brand-primary-900, var(--color-brand-primary-800));margin-block-end:var(--space-4);margin-block-start:var(--space-4)}\n"] }]
12111
12318
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], fields: [{ type: i0.Input, args: [{ isSignal: true, alias: "fields", required: true }] }] } });
12112
12319
 
12320
+ /** Read-only permissions panel listing an account user's roles as `pills`, falling back to `noPermissionsLabel` when empty and to skeletons while `loading`. */
12113
12321
  class SceAccountUserPermissionsSectionComponent {
12114
12322
  sectionTitle = input.required(...(ngDevMode ? [{ debugName: "sectionTitle" }] : /* istanbul ignore next */ []));
12115
12323
  permissionsLabel = input.required(...(ngDevMode ? [{ debugName: "permissionsLabel" }] : /* istanbul ignore next */ []));
@@ -12124,6 +12332,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12124
12332
  args: [{ selector: 'sce-account-user-permissions-section', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-account-user-permissions-section' }, imports: [SceInfoFieldCardComponent, SceInfoFieldsGridComponent, SceSkeleton], template: "<h3 class=\"sce-account-user-permissions-section__title\">{{ sectionTitle() }}</h3>\n<sce-info-fields-grid gap=\"sm\">\n <sce-info-field-card class=\"permissionsCard\" [label]=\"permissionsLabel()\" [fullWidth]=\"true\">\n <div class=\"sce-account-user-permissions-section__list\">\n @if (loading()) {\n <div class=\"sce-account-user-permissions-section__skeleton\">\n @for (i of [1, 2, 3]; track i) {\n <sce-skeleton variant=\"chip\" width=\"6rem\" height=\"1.5rem\" animation=\"wave\" aria-hidden=\"true\" />\n }\n </div>\n } @else if (pills().length > 0) {\n @for (pill of pills(); track pill) {\n <span class=\"sce-account-user-permissions-section__pill\">{{ pill }}</span>\n }\n } @else {\n <span class=\"sce-account-user-permissions-section__no-permissions\">{{ noPermissionsLabel() }}</span>\n }\n </div>\n </sce-info-field-card>\n</sce-info-fields-grid>\n", styles: [":host{display:block}.sce-account-user-permissions-section__title{font-size:var(--font-size-xl, var(--font-size-xl));font-weight:700;color:var(--color-brand-primary-900, var(--color-brand-primary-800));margin-block-end:var(--space-4);margin-block-start:var(--space-4)}.sce-account-user-permissions-section__list{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-block-start:var(--space-1)}.sce-account-user-permissions-section__skeleton{display:flex;flex-wrap:wrap;gap:var(--space-2)}.sce-account-user-permissions-section__pill{padding:var(--space-1-5, var(--space-6)) var(--space-3-5, var(--space-14));border-radius:var(--radius-full, var(--radius-100));background:var(--color-info-50, var(--color-blue-100));color:var(--color-brand-primary-700, var(--color-brand-primary-600));font-size:var(--font-size-xs);font-weight:700;display:inline-block}.sce-account-user-permissions-section__no-permissions{font-size:var(--font-size-sm);color:var(--color-neutral-400, var(--form-label-muted))}\n"] }]
12125
12333
  }], propDecorators: { sectionTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionTitle", required: true }] }], permissionsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "permissionsLabel", required: true }] }], noPermissionsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noPermissionsLabel", required: true }] }], pills: [{ type: i0.Input, args: [{ isSignal: true, alias: "pills", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
12126
12334
 
12335
+ /** Inline (non-dialog) national-ID and birth-date step for verifying an internal user before creation; `calendarSystem` selects Hijri or Gregorian input and `verify` is emitted for the host to call the API. */
12127
12336
  class SceInternalUserVerifySectionComponent {
12128
12337
  nationalId = input.required(...(ngDevMode ? [{ debugName: "nationalId" }] : /* istanbul ignore next */ []));
12129
12338
  birthDate = input.required(...(ngDevMode ? [{ debugName: "birthDate" }] : /* istanbul ignore next */ []));
@@ -12143,6 +12352,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12143
12352
  args: [{ selector: 'sce-internal-user-verify-section', standalone: true, imports: [FormsModule, TranslatePipe, SceDateFieldComponent, SceSkeleton], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-internal-user-verify-section' }, template: "<div class=\"sce-internal-user-verify-section__panel\">\n <p class=\"sce-internal-user-verify-section__hint\">\n {{ 'dashboard.users.dialog.verifySectionDescription' | translate }}\n </p>\n\n <div class=\"sce-internal-user-verify-section__fields\">\n <div class=\"sce-internal-user-verify-section__field\">\n <label for=\"nationalId\" class=\"sce-internal-user-verify-section__label\">\n {{ 'dashboard.internalUserForm.nationalId' | translate }}\n <span aria-hidden=\"true\"> *</span>\n </label>\n <input\n id=\"nationalId\"\n dir=\"ltr\"\n class=\"sce-internal-user-verify-section__input\"\n [class.sce-internal-user-verify-section__input--error]=\"nationalIdError()\"\n [placeholder]=\"'dashboard.internalUserForm.nationalIdPlaceholder' | translate\"\n inputmode=\"numeric\"\n maxlength=\"10\"\n [ngModel]=\"nationalId()\"\n (ngModelChange)=\"nationalIdChange.emit($event)\"\n />\n @if (nationalIdError()) {\n <p class=\"sce-internal-user-verify-section__error\" role=\"alert\">{{ nationalIdError() }}</p>\n }\n </div>\n\n <div class=\"sce-internal-user-verify-section__field\">\n <sce-date-field\n id=\"birthDate\"\n [label]=\"'dashboard.internalUserForm.birthDate' | translate\"\n [calendarSystem]=\"calendarSystem()\"\n [locale]=\"locale()\"\n [value]=\"birthDate()\"\n [error]=\"birthDateError()\"\n displayFormat=\"iso\"\n [showIcon]=\"true\"\n (valueChange)=\"birthDateChange.emit($event)\"\n />\n </div>\n </div>\n\n <div>\n <!-- aria-label: while verifying, the visible content is an aria-hidden skeleton,\n which would otherwise leave the button nameless (axe: button-name). -->\n <button\n type=\"button\"\n class=\"sce-internal-user-verify-section__button\"\n [attr.aria-label]=\"'dashboard.internalUserForm.verify' | translate\"\n [disabled]=\"verifying()\"\n (click)=\"verify.emit()\"\n >\n @if (verifying()) {\n <sce-skeleton variant=\"text\" width=\"5rem\" height=\"1rem\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n {{ 'dashboard.internalUserForm.verify' | translate }}\n }\n </button>\n </div>\n</div>\n", styles: [":host{display:block}.sce-internal-user-verify-section__panel{display:grid;gap:var(--space-16);padding:var(--space-20);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--app-surface-hover)}.sce-internal-user-verify-section__hint{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-verify-section__fields{display:grid;grid-template-columns:1fr;gap:var(--space-12)}@media(min-width:769px){.sce-internal-user-verify-section__fields{grid-template-columns:repeat(2,minmax(0,1fr))}}.sce-internal-user-verify-section__field{display:grid;gap:var(--space-24)}.sce-internal-user-verify-section__label{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-verify-section__input{height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding-inline:var(--space-16);font-size:var(--font-size-md);font-weight:var(--font-weight-normal);color:var(--text-text-primary-900);outline:0;width:100%;box-sizing:border-box;transition:border-color .15s ease}.sce-internal-user-verify-section__input::placeholder{color:var(--color-neutral-500)}.sce-internal-user-verify-section__input:focus{border-color:var(--button-background-primary-bg-primary)}.sce-internal-user-verify-section__input--error{border-color:var(--text-text-error-primary)}.sce-internal-user-verify-section__input--error:focus{border-color:var(--text-text-error-primary);box-shadow:none}.sce-internal-user-verify-section__error{margin:0;color:var(--text-text-error-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-verify-section__button{display:inline-flex;align-items:center;justify-content:center;min-height:var(--space-48);min-width:var(--size-140);padding:var(--space-8) var(--space-24);border:0;border-radius:var(--radius-xl);background:var(--button-background-primary-bg-primary);color:var(--text-text-primaryon-brand);font-weight:var(--font-weight-bold);font-size:var(--font-size-md);cursor:pointer;transition:opacity .15s ease}.sce-internal-user-verify-section__button:disabled{opacity:.6;cursor:not-allowed}\n"] }]
12144
12353
  }], propDecorators: { nationalId: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalId", required: true }] }], birthDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDate", required: true }] }], nationalIdError: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalIdError", required: false }] }], birthDateError: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDateError", required: false }] }], calendarSystem: [{ type: i0.Input, args: [{ isSignal: true, alias: "calendarSystem", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], verifying: [{ type: i0.Input, args: [{ isSignal: true, alias: "verifying", required: false }] }], nationalIdChange: [{ type: i0.Output, args: ["nationalIdChange"] }], birthDateChange: [{ type: i0.Output, args: ["birthDateChange"] }], verify: [{ type: i0.Output, args: ["verify"] }] } });
12145
12354
 
12355
+ /** Contact-detail fields for an internal user: national ID, birth date, and name are read-only, and only email and mobile are editable (emitted back to the host). */
12146
12356
  class SceInternalUserFormFieldsComponent {
12147
12357
  mode = input.required(...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
12148
12358
  nationalId = input('', ...(ngDevMode ? [{ debugName: "nationalId" }] : /* istanbul ignore next */ []));
@@ -12162,6 +12372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12162
12372
  args: [{ selector: 'sce-internal-user-form-fields', standalone: true, imports: [FormsModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-internal-user-form-fields' }, template: "<div class=\"sce-internal-user-form-fields__grid\">\n @if (mode() === 'edit') {\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.nationalId' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ nationalId() || '\u2014' }}</p>\n </div>\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.birthDate' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ birthDate() || '\u2014' }}</p>\n </div>\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.userName' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ userName() || '\u2014' }}</p>\n </div>\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.email' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ email() || '\u2014' }}</p>\n </div>\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.mobile' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ mobile() || '\u2014' }}</p>\n </div>\n } @else {\n <div class=\"sce-internal-user-form-fields__readonly\">\n <p class=\"sce-internal-user-form-fields__label\">{{ 'dashboard.internalUserForm.userName' | translate }}</p>\n <p class=\"sce-internal-user-form-fields__value\">{{ userName() || '\u2014' }}</p>\n </div>\n\n <div class=\"sce-internal-user-form-fields__field\">\n <label for=\"email\" class=\"sce-internal-user-form-fields__label\">\n {{ 'dashboard.internalUserForm.email' | translate }}\n </label>\n <input\n id=\"email\"\n type=\"email\"\n dir=\"ltr\"\n inputmode=\"email\"\n class=\"sce-internal-user-form-fields__input\"\n [class.sce-internal-user-form-fields__input--error]=\"emailError()\"\n [placeholder]=\"'dashboard.internalUserForm.emailPlaceholder' | translate\"\n [ngModel]=\"email()\"\n (ngModelChange)=\"emailChange.emit($event)\"\n />\n @if (emailError()) {\n <p class=\"sce-internal-user-form-fields__error\" role=\"alert\">{{ emailError() }}</p>\n }\n </div>\n\n <div class=\"sce-internal-user-form-fields__field\">\n <label for=\"mobile\" class=\"sce-internal-user-form-fields__label\">\n {{ 'dashboard.internalUserForm.mobile' | translate }}\n </label>\n <input\n id=\"mobile\"\n type=\"tel\"\n dir=\"ltr\"\n inputmode=\"numeric\"\n maxlength=\"15\"\n class=\"sce-internal-user-form-fields__input\"\n [class.sce-internal-user-form-fields__input--error]=\"mobileError()\"\n [placeholder]=\"'dashboard.internalUserForm.mobilePlaceholder' | translate\"\n [ngModel]=\"mobile()\"\n (ngModelChange)=\"mobileChange.emit($event)\"\n />\n @if (mobileError()) {\n <p class=\"sce-internal-user-form-fields__error\" role=\"alert\">{{ mobileError() }}</p>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}.sce-internal-user-form-fields__grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-12)}@media(max-width:576px){.sce-internal-user-form-fields__grid{grid-template-columns:1fr}}.sce-internal-user-form-fields__field{display:grid;gap:var(--space-24)}.sce-internal-user-form-fields__label{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-form-fields__input{height:var(--space-48);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl);background:var(--color-surface);padding-inline:var(--space-16);font-size:var(--font-size-md);font-weight:var(--font-weight-normal);color:var(--text-text-primary-900);outline:0;width:100%;box-sizing:border-box;transition:border-color .15s ease}.sce-internal-user-form-fields__input::placeholder{color:var(--color-neutral-500)}.sce-internal-user-form-fields__input:focus{border-color:var(--button-background-primary-bg-primary)}.sce-internal-user-form-fields__input--error{border-color:var(--text-text-error-primary)}.sce-internal-user-form-fields__input--error:focus{border-color:var(--text-text-error-primary);box-shadow:none}.sce-internal-user-form-fields__error{margin:0;color:var(--text-text-error-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium)}.sce-internal-user-form-fields__readonly{background:var(--app-surface-hover);border-radius:var(--radius-xl);min-height:var(--space-48);padding:var(--space-16);display:grid;align-content:center;gap:var(--space-8)}.sce-internal-user-form-fields__value{margin:0;color:var(--text-text-primary-900);font-size:var(--font-size-md);font-weight:var(--font-weight-medium)}\n"] }]
12163
12373
  }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: true }] }], nationalId: [{ type: i0.Input, args: [{ isSignal: true, alias: "nationalId", required: false }] }], birthDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "birthDate", required: false }] }], userName: [{ type: i0.Input, args: [{ isSignal: true, alias: "userName", required: false }] }], email: [{ type: i0.Input, args: [{ isSignal: true, alias: "email", required: false }] }], mobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobile", required: false }] }], emailError: [{ type: i0.Input, args: [{ isSignal: true, alias: "emailError", required: false }] }], mobileError: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileError", required: false }] }], emailChange: [{ type: i0.Output, args: ["emailChange"] }], mobileChange: [{ type: i0.Output, args: ["mobileChange"] }] } });
12164
12374
 
12375
+ /** Editable permissions panel for an internal user: a roles multi-select (skeletons while `rolesLoading`) plus an active/inactive switch that defaults to on. */
12165
12376
  class SceInternalUserPermissionsSectionComponent {
12166
12377
  roleOptions = input([], ...(ngDevMode ? [{ debugName: "roleOptions" }] : /* istanbul ignore next */ []));
12167
12378
  selectedRoleNumbers = input([], ...(ngDevMode ? [{ debugName: "selectedRoleNumbers" }] : /* istanbul ignore next */ []));
@@ -12177,6 +12388,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12177
12388
  args: [{ selector: 'sce-internal-user-permissions-section', standalone: true, imports: [FormsModule, TranslatePipe, MultiSelect, SceSkeleton, SceSwitchComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-internal-user-permissions-section' }, template: "<div class=\"sce-internal-user-permissions-section__permissions\">\n <label for=\"int-user-permissions\" class=\"sce-internal-user-permissions-section__label\">\n {{ 'dashboard.internalUserForm.permissions' | translate }}\n </label>\n @if (rolesLoading()) {\n <sce-skeleton variant=\"input\" animation=\"wave\" aria-hidden=\"true\" />\n } @else {\n <p-multiSelect\n inputId=\"int-user-permissions\"\n [options]=\"roleOptions()\"\n [ngModel]=\"selectedRoleNumbers()\"\n (ngModelChange)=\"selectedRoleNumbersChange.emit($event)\"\n display=\"chip\"\n [filter]=\"true\"\n [placeholder]=\"'dashboard.internalUserForm.permissionsPlaceholder' | translate\"\n optionLabel=\"label\"\n optionValue=\"value\"\n appendTo=\"body\"\n styleClass=\"w-full\"\n />\n }\n</div>\n\n<div class=\"sce-internal-user-permissions-section__status\">\n <h4 class=\"sce-internal-user-permissions-section__status-title\">\n {{ 'dashboard.internalUserForm.isActive' | translate }}\n </h4>\n <sce-switch\n [checked]=\"isActive()\"\n [showLabel]=\"true\"\n [activeLabel]=\"'dashboard.status.active' | translate\"\n [inactiveLabel]=\"'dashboard.status.inactive' | translate\"\n (checkedChange)=\"isActiveChange.emit($event)\"\n />\n</div>\n", styles: [":host{display:grid;gap:var(--space-16)}.sce-internal-user-permissions-section__permissions{display:grid;gap:var(--space-24)}.sce-internal-user-permissions-section__label{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold)}.sce-internal-user-permissions-section__status{display:flex;flex-direction:column;align-items:start;gap:var(--space-12);padding:var(--space-14) var(--space-16);border:1px solid var(--color-neutral-200);border-radius:var(--radius-xl)}.sce-internal-user-permissions-section__status-title{margin:0;color:var(--text-text-secondary-700);font-size:var(--font-size-md);font-weight:var(--font-weight-semibold)}\n"] }]
12178
12389
  }], propDecorators: { roleOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "roleOptions", required: false }] }], selectedRoleNumbers: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedRoleNumbers", required: false }] }], rolesLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolesLoading", required: false }] }], isActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isActive", required: false }] }], selectedRoleNumbersChange: [{ type: i0.Output, args: ["selectedRoleNumbersChange"] }], isActiveChange: [{ type: i0.Output, args: ["isActiveChange"] }] } });
12179
12390
 
12391
+ /** Segmented grid/list/map switch for the offices browser; fully controlled — it reports `viewModeChange` rather than holding the mode itself. */
12180
12392
  class SceOfficesViewToggleComponent {
12181
12393
  viewMode = input.required(...(ngDevMode ? [{ debugName: "viewMode" }] : /* istanbul ignore next */ []));
12182
12394
  viewModeChange = output();
@@ -12188,6 +12400,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12188
12400
  args: [{ selector: 'sce-offices-view-toggle', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'sce-offices-view-toggle' }, imports: [TranslatePipe], template: "<button\n type=\"button\"\n class=\"sce-offices-view-toggle__btn\"\n [class.sce-offices-view-toggle__btn--active]=\"viewMode() === 'grid'\"\n [attr.aria-label]=\"'engineeringOffices.browser.viewMode.grid' | translate\"\n (click)=\"viewModeChange.emit('grid')\"\n>\n <img src=\"/assets/icons/microsoft.svg\" class=\"sce-offices-view-toggle__icon\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" />\n</button>\n\n<button\n type=\"button\"\n class=\"sce-offices-view-toggle__btn\"\n [class.sce-offices-view-toggle__btn--active]=\"viewMode() === 'list'\"\n [attr.aria-label]=\"'engineeringOffices.browser.viewMode.list' | translate\"\n (click)=\"viewModeChange.emit('list')\"\n>\n <img src=\"/assets/icons/menu.svg\" class=\"sce-offices-view-toggle__icon\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" />\n</button>\n\n<button\n type=\"button\"\n class=\"sce-offices-view-toggle__btn\"\n [class.sce-offices-view-toggle__btn--active]=\"viewMode() === 'map'\"\n [attr.aria-label]=\"'engineeringOffices.browser.viewMode.map' | translate\"\n (click)=\"viewModeChange.emit('map')\"\n>\n <img src=\"/assets/icons/maps.svg\" class=\"sce-offices-view-toggle__icon\" width=\"24\" height=\"24\" alt=\"\" aria-hidden=\"true\" />\n</button>\n", styles: [":host{display:inline-flex;gap:var(--space-2)}.sce-offices-view-toggle__btn{width:var(--space-44);height:var(--space-44);border:1px solid var(--border-subtle);border-radius:var(--space-10);background:var(--surface-primary);color:var(--cta-bg);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background-color .2s ease,color .2s ease}.sce-offices-view-toggle__btn--active{background:var(--cta-bg);color:var(--text-on-brand-primary);border-color:var(--cta-bg)}.sce-offices-view-toggle__btn--active .sce-offices-view-toggle__icon{filter:brightness(0) saturate(100%) invert(100%)}.sce-offices-view-toggle__icon{width:1.35rem;height:1.35rem}\n"] }]
12189
12401
  }], propDecorators: { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: true }] }], viewModeChange: [{ type: i0.Output, args: ["viewModeChange"] }] } });
12190
12402
 
12403
+ /** Paginated grid/list of engineering-office cards with skeleton and empty states; `viewMode` switches the layout and `skeletonCount` is floored at 4. */
12191
12404
  class SceOfficesGridPanelComponent {
12192
12405
  cards = input.required(...(ngDevMode ? [{ debugName: "cards" }] : /* istanbul ignore next */ []));
12193
12406
  isLoading = input.required(...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
@@ -12223,6 +12436,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12223
12436
  ], template: "@if (isLoading()) {\n <div [class]=\"skeletonContainerClass()\">\n @for (i of skeletonIndices(); track i) {\n <sce-engineering-office-card-skeleton [viewMode]=\"viewMode()\" />\n }\n </div>\n} @else if (isEmpty()) {\n <div class=\"sce-offices-grid-panel__empty\" role=\"status\">\n <h3 class=\"sce-offices-grid-panel__empty-title\">{{ 'engineeringOffices.empty.title' | translate }}</h3>\n <p class=\"sce-offices-grid-panel__empty-subtitle\">{{ 'engineeringOffices.empty.subtitle' | translate }}</p>\n </div>\n} @else {\n <div [class]=\"cardsClass()\">\n @for (card of cards(); track card.href ?? card.name) {\n <sce-engineering-office-card\n [office]=\"card\"\n [viewMode]=\"viewMode()\"\n [bookmarked]=\"bookmarkedIds().has(card.href ?? card.name)\"\n (bookmarkClick)=\"bookmarkClick.emit(card)\"\n [bookmarkLabel]=\"bookmarkLabel()\"\n [ratingLabel]=\"ratingLabel()\"\n [locationLabel]=\"locationLabel()\"\n [otherLabel]=\"otherLabel()\"\n />\n }\n </div>\n\n <div class=\"sce-offices-grid-panel__footer\">\n <sce-paginator\n [page]=\"page()\"\n [pageSize]=\"pageSize()\"\n [totalItems]=\"totalItems()\"\n [locale]=\"locale()\"\n [pageSizeOptions]=\"pageSizeOptions()\"\n (pageChange)=\"pageChange.emit($event)\"\n (pageSizeChange)=\"pageSizeChange.emit($event)\"\n />\n </div>\n}\n", styles: [":host{display:grid;gap:var(--space-4)}.sce-offices-grid-panel__cards--grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-4)}.sce-offices-grid-panel__cards--list{display:grid;grid-template-columns:1fr;gap:.9rem}.sce-offices-grid-panel__footer{display:block}.sce-offices-grid-panel__empty{min-height:var(--size-280);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-8);border-radius:var(--radius-brand-sm);background:var(--color-surface);text-align:center}.sce-offices-grid-panel__empty-title{margin:0;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-bold);font-size:var(--font-size-2xl-24);line-height:1.4;color:var(--text-text-primary-900)}.sce-offices-grid-panel__empty-subtitle{margin:0;max-width:42rem;font-family:var(--font-family-arabic-primary);font-weight:var(--font-weight-regular);font-size:var(--font-size-lg);line-height:1.5;color:var(--text-text-secondary-700)}@media(max-width:1200px){.sce-offices-grid-panel__cards--grid{grid-template-columns:1fr}}\n"] }]
12224
12437
  }], propDecorators: { cards: [{ type: i0.Input, args: [{ isSignal: true, alias: "cards", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], isEmpty: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEmpty", required: true }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], skeletonCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonCount", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: true }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: true }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], bookmarkedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookmarkedIds", required: false }] }], bookmarkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookmarkLabel", required: false }] }], ratingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ratingLabel", required: false }] }], locationLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "locationLabel", required: false }] }], otherLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "otherLabel", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }], bookmarkClick: [{ type: i0.Output, args: ["bookmarkClick"] }] } });
12225
12438
 
12439
+ /** Wraps the OSM offices map with a fallback link shown when `mapLoadFailed`; emits `selectOffice` when a marker is picked. */
12226
12440
  class SceOfficesMapPanelComponent {
12227
12441
  mapPoints = input.required(...(ngDevMode ? [{ debugName: "mapPoints" }] : /* istanbul ignore next */ []));
12228
12442
  mapLoadFailed = input.required(...(ngDevMode ? [{ debugName: "mapLoadFailed" }] : /* istanbul ignore next */ []));
@@ -12282,6 +12496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
12282
12496
  }]
12283
12497
  }], ctorParameters: () => [], propDecorators: { sceSliderValuenow: [{ type: i0.Input, args: [{ isSignal: true, alias: "sceSliderValuenow", required: false }] }] } });
12284
12498
 
12499
+ /** Fully controlled sort/size/budget/experience filter sidebar for the offices browser: it owns no state, taking every draft value, slider bound, and budget-histogram bar as a required input and emitting changes back — including the pre-flipped `*SliderLtr` values PrimeNG's slider needs under RTL. */
12285
12500
  class SceOfficesFiltersSidebarComponent {
12286
12501
  /** Current draft sort/filter values */
12287
12502
  draftSort = input.required(...(ngDevMode ? [{ debugName: "draftSort" }] : /* istanbul ignore next */ []));
@@ -13013,6 +13228,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
13013
13228
  args: [{ host: { class: 'sce-tab-panel' }, selector: 'sce-tab-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"sce-tab-panel__box\"\n [class.sce-tab-panel__box--active]=\"isActive()\"\n [attr.id]=\"'panel-' + panelId()\"\n [attr.aria-labelledby]=\"'tab-' + panelId()\"\n [attr.aria-hidden]=\"!isActive()\"\n role=\"tabpanel\"\n>\n @if (isActive()) {\n <ng-content />\n }\n</div>\n", styles: [":host{display:block}.sce-tab-panel__box{display:none;padding-block:var(--space-lg)}.sce-tab-panel__box--active{display:block;animation:sce-tab-panel-fade var(--transition-medium)}@keyframes sce-tab-panel-fade{0%{opacity:0;transform:translateY(var(--space-10))}to{opacity:1;transform:translateY(0)}}\n"] }]
13014
13229
  }], propDecorators: { panelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelId", required: true }] }], activeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeId", required: false }] }] } });
13015
13230
 
13231
+ /** Label-and-value display rendered either as a standalone padded tile or, in `field` layout, as a plain row inside a parent panel. */
13016
13232
  class SceBasicCardComponent {
13017
13233
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
13018
13234
  value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -13029,6 +13245,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
13029
13245
  }, template: "<div class=\"sce-basic-card__box\" [class.sce-basic-card__box--field]=\"layout() === 'field'\">\n <span class=\"sce-basic-card__label\">{{ label() | translate }}</span>\n <span class=\"sce-basic-card__value\">{{ value() | translate }}</span>\n</div>\n", styles: [":host{display:block}:host(.sce-basic-card--full-width){grid-column:1/-1;inline-size:100%}.sce-basic-card__box{display:flex;flex-direction:column;gap:var(--space-6);block-size:100%;padding:var(--space-16);border:var(--border-width-1) solid var(--color-border-subtle);border-radius:var(--radius-xl);background:var(--color-surface-primary)}.sce-basic-card__box--field{padding:0;border:0;border-radius:0;background:transparent}.sce-basic-card__label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);color:var(--color-text-muted);text-align:start}.sce-basic-card__value{font-size:var(--font-size-md);font-weight:var(--font-weight-semibold);line-height:var(--line-height-normal);color:var(--color-text-primary);text-align:start;overflow-wrap:anywhere}\n"] }]
13030
13246
  }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }] } });
13031
13247
 
13248
+ /** Renders a grid of `sce-nav-card` tiles from `items`; stays route-agnostic by taking a required `getItemRoute` factory that turns an item slug into a router link. */
13032
13249
  class SceNavCardsListComponent {
13033
13250
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
13034
13251
  /** Maps an item slug to a router link. Kept as an input so the organism stays route-agnostic. */
@@ -13131,6 +13348,7 @@ function hasObservationFor(item) {
13131
13348
  return Boolean(observation.notes || observation.reasonLabel || observation.attachments?.length);
13132
13349
  }
13133
13350
 
13351
+ /** Card summarising an entity by logo, name and description, listing its sectors as clickable chips (disabled ones emit nothing) with info and optional settings actions. */
13134
13352
  class SceEntitySummaryCardComponent {
13135
13353
  logo = input.required(...(ngDevMode ? [{ debugName: "logo" }] : /* istanbul ignore next */ []));
13136
13354
  name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
@@ -13721,6 +13939,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
13721
13939
 
13722
13940
  /** Tags without an explicit variant cycle through these, so a tag cloud stays visually varied. */
13723
13941
  const VARIANT_CYCLE = ['brand', 'accent', 'info'];
13942
+ /** Titled tag cloud for knowledge articles; any tag without an explicit variant is assigned one by cycling through brand, accent and info so the cloud stays visually varied. */
13724
13943
  class SceArticleTagsListComponent {
13725
13944
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
13726
13945
  titleKey = input('knowledge.tags', ...(ngDevMode ? [{ debugName: "titleKey" }] : /* istanbul ignore next */ []));