@forgeroute/ui 0.4.35 → 0.4.37

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.
@@ -8733,22 +8733,30 @@ i0.ɵɵngDeclareClassMetadata({
8733
8733
  }]
8734
8734
  }
8735
8735
  });
8736
- var ImportSourceGridComponent = class ImportSourceGridComponent {
8736
+ var OptionCardComponent = class OptionCardComponent {
8737
8737
  constructor() {
8738
- this.sources = input.required(...ngDevMode ? [{ debugName: "sources" }] : /* istanbul ignore next */ []);
8739
- this.selected = input("", ...ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []);
8740
- this.appearance = input("tile", ...ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []);
8738
+ this.title = input.required(...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
8739
+ this.description = input("", ...ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []);
8740
+ this.letter = input("", ...ngDevMode ? [{ debugName: "letter" }] : /* istanbul ignore next */ []);
8741
+ this.icon = input("", ...ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []);
8742
+ this.color = input("#64748b", ...ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []);
8743
+ this.actionLabel = input("", ...ngDevMode ? [{ debugName: "actionLabel" }] : /* istanbul ignore next */ []);
8744
+ this.actionVariant = input("secondary", ...ngDevMode ? [{ debugName: "actionVariant" }] : /* istanbul ignore next */ []);
8745
+ this.actionAriaLabel = input("", ...ngDevMode ? [{ debugName: "actionAriaLabel" }] : /* istanbul ignore next */ []);
8746
+ this.actionTestId = input("", ...ngDevMode ? [{ debugName: "actionTestId" }] : /* istanbul ignore next */ []);
8747
+ this.actionLoading = input(false, ...ngDevMode ? [{ debugName: "actionLoading" }] : /* istanbul ignore next */ []);
8741
8748
  this.disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
8742
- this.actionLabel = input("Select", ...ngDevMode ? [{ debugName: "actionLabel" }] : /* istanbul ignore next */ []);
8743
- this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
8744
- this.sourceSelect = output();
8749
+ this.action = output();
8750
+ }
8751
+ iconD() {
8752
+ return this.icon() ? iconPath(this.icon()) ?? null : null;
8745
8753
  }
8746
8754
  static {
8747
8755
  this.ɵfac = i0.ɵɵngDeclareFactory({
8748
8756
  minVersion: "12.0.0",
8749
8757
  version: "22.2.2",
8750
8758
  ngImport: i0,
8751
- type: ImportSourceGridComponent,
8759
+ type: OptionCardComponent,
8752
8760
  deps: [],
8753
8761
  target: i0.ɵɵFactoryTarget.Component
8754
8762
  });
@@ -8757,34 +8765,41 @@ var ImportSourceGridComponent = class ImportSourceGridComponent {
8757
8765
  this.ɵcmp = i0.ɵɵngDeclareComponent({
8758
8766
  minVersion: "17.0.0",
8759
8767
  version: "22.2.2",
8760
- type: ImportSourceGridComponent,
8768
+ type: OptionCardComponent,
8761
8769
  isStandalone: true,
8762
- selector: "ui-import-source-grid",
8770
+ selector: "ui-option-card",
8763
8771
  inputs: {
8764
- sources: {
8765
- classPropertyName: "sources",
8766
- publicName: "sources",
8772
+ title: {
8773
+ classPropertyName: "title",
8774
+ publicName: "title",
8767
8775
  isSignal: true,
8768
8776
  isRequired: true,
8769
8777
  transformFunction: null
8770
8778
  },
8771
- selected: {
8772
- classPropertyName: "selected",
8773
- publicName: "selected",
8779
+ description: {
8780
+ classPropertyName: "description",
8781
+ publicName: "description",
8774
8782
  isSignal: true,
8775
8783
  isRequired: false,
8776
8784
  transformFunction: null
8777
8785
  },
8778
- appearance: {
8779
- classPropertyName: "appearance",
8780
- publicName: "appearance",
8786
+ letter: {
8787
+ classPropertyName: "letter",
8788
+ publicName: "letter",
8781
8789
  isSignal: true,
8782
8790
  isRequired: false,
8783
8791
  transformFunction: null
8784
8792
  },
8785
- disabled: {
8786
- classPropertyName: "disabled",
8787
- publicName: "disabled",
8793
+ icon: {
8794
+ classPropertyName: "icon",
8795
+ publicName: "icon",
8796
+ isSignal: true,
8797
+ isRequired: false,
8798
+ transformFunction: null
8799
+ },
8800
+ color: {
8801
+ classPropertyName: "color",
8802
+ publicName: "color",
8788
8803
  isSignal: true,
8789
8804
  isRequired: false,
8790
8805
  transformFunction: null
@@ -8796,53 +8811,64 @@ var ImportSourceGridComponent = class ImportSourceGridComponent {
8796
8811
  isRequired: false,
8797
8812
  transformFunction: null
8798
8813
  },
8799
- ariaLabel: {
8800
- classPropertyName: "ariaLabel",
8801
- publicName: "ariaLabel",
8814
+ actionVariant: {
8815
+ classPropertyName: "actionVariant",
8816
+ publicName: "actionVariant",
8817
+ isSignal: true,
8818
+ isRequired: false,
8819
+ transformFunction: null
8820
+ },
8821
+ actionAriaLabel: {
8822
+ classPropertyName: "actionAriaLabel",
8823
+ publicName: "actionAriaLabel",
8824
+ isSignal: true,
8825
+ isRequired: false,
8826
+ transformFunction: null
8827
+ },
8828
+ actionTestId: {
8829
+ classPropertyName: "actionTestId",
8830
+ publicName: "actionTestId",
8831
+ isSignal: true,
8832
+ isRequired: false,
8833
+ transformFunction: null
8834
+ },
8835
+ actionLoading: {
8836
+ classPropertyName: "actionLoading",
8837
+ publicName: "actionLoading",
8838
+ isSignal: true,
8839
+ isRequired: false,
8840
+ transformFunction: null
8841
+ },
8842
+ disabled: {
8843
+ classPropertyName: "disabled",
8844
+ publicName: "disabled",
8802
8845
  isSignal: true,
8803
8846
  isRequired: false,
8804
8847
  transformFunction: null
8805
8848
  }
8806
8849
  },
8807
- outputs: { sourceSelect: "sourceSelect" },
8850
+ outputs: { action: "action" },
8808
8851
  ngImport: i0,
8809
8852
  template: `
8810
- <div class="ie-source-grid" [attr.role]="appearance() === 'card' ? 'group' : 'list'" [class.ie-source-grid--cards]="appearance() === 'card'" [attr.aria-label]="ariaLabel() || null">
8811
- @for (src of sources(); track src.value) {
8812
- @if (appearance() === 'card') {
8813
- <ui-detail-card class="ie-source-detail" [showHeader]="false" [fill]="true" [ariaLabel]="src.label" [attr.data-testid]="'source-' + src.value">
8814
- <div class="ie-source-detail-row">
8815
- @if (src.letter) {
8816
- <span class="ie-source-letter" [style.background]="src.color || '#64748b'" aria-hidden="true">{{ src.letter }}</span>
8817
- }
8818
- <span class="ie-source-detail-text">
8819
- <span class="ie-source-label">{{ src.label }}</span>
8820
- @if (src.desc) { <span class="ie-source-desc">{{ src.desc }}</span> }
8821
- </span>
8822
- <ui-button variant="secondary" size="xs" [attr.data-testid]="'source-pick-' + src.value" [disabled]="disabled()" [ariaLabel]="actionLabel() + ' ' + src.label" (click)="sourceSelect.emit(src.value)">{{ actionLabel() }}</ui-button>
8823
- </div>
8824
- </ui-detail-card>
8825
- } @else {
8826
- <button
8827
- class="ie-source-card"
8828
- role="listitem"
8829
- type="button"
8830
- [class.ie-source-card--active]="selected() === src.value"
8831
- [attr.aria-pressed]="selected() === src.value"
8832
- [attr.data-testid]="'source-' + src.value"
8833
- (click)="sourceSelect.emit(src.value)">
8834
- @if (src.letter) {
8835
- <span class="ie-source-letter" [style.background]="src.color || '#64748b'" aria-hidden="true">{{ src.letter }}</span>
8836
- }
8837
- <span class="ie-source-label">{{ src.label }}</span>
8838
- @if (src.desc) { <span class="ie-source-desc">{{ src.desc }}</span> }
8839
- </button>
8853
+ <ui-detail-card class="oc" [showHeader]="false" [ariaLabel]="title()">
8854
+ <div class="oc-row">
8855
+ <span class="oc-tile" [style.background]="color()" aria-hidden="true">
8856
+ @if (letter()) { {{ letter() }} } @else if (iconD(); as d) { <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path [attr.d]="d" /></svg> }
8857
+ </span>
8858
+ <span class="oc-text">
8859
+ <span class="oc-title">{{ title() }}</span>
8860
+ @if (description()) { <span class="oc-desc">{{ description() }}</span> }
8861
+ </span>
8862
+ @if (actionLabel()) {
8863
+ <ui-button size="xs" [variant]="actionVariant()" [disabled]="disabled()" [loading]="actionLoading()" [attr.data-testid]="actionTestId() || null"
8864
+ [ariaLabel]="actionAriaLabel() || (actionLabel() + ' ' + title())" (click)="action.emit()">{{ actionLabel() }}</ui-button>
8840
8865
  }
8841
- }
8842
- </div>
8866
+ </div>
8867
+ <ng-content />
8868
+ </ui-detail-card>
8843
8869
  `,
8844
8870
  isInline: true,
8845
- styles: ["ui-import-source-grid{display:block}.ie-source-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}@media(max-width:520px){.ie-source-grid{grid-template-columns:repeat(2,1fr)}}.ie-source-card{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:12px;border:1px solid #e2e8f0;border-radius:10px;background:#fff;cursor:pointer;font-family:inherit;text-align:left;transition:all .15s}.ie-source-card:hover{border-color:#94a3b8;background:#f8fafc}.ie-source-card.ie-source-card--active{border-color:#3b82f6;background:#eff6ff}.ie-source-card:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.ie-source-letter{width:36px;height:36px;border-radius:8px;color:#fff;font-size:1rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-source-label{font-size:.8125rem;font-weight:600;color:#1e293b;line-height:1.2}.ie-source-desc{font-size:.75rem;color:#64748b}.ie-source-grid--cards{grid-template-columns:repeat(2,1fr)}@media(max-width:520px){.ie-source-grid--cards{grid-template-columns:1fr}}ui-import-source-grid .ie-source-detail.ie-source-detail{margin-bottom:0}.ie-source-detail-row{display:flex;align-items:center;gap:12px}.ie-source-detail-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}\n"],
8871
+ styles: ["ui-option-card{display:block}ui-option-card .oc{margin-bottom:0}.oc-row{display:flex;align-items:center;gap:12px}.oc-tile{width:36px;height:36px;border-radius:8px;color:#fff;font-size:1rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.oc-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.oc-title{font-size:.8125rem;font-weight:600;color:#1e293b;line-height:1.2}.oc-desc{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}\n"],
8846
8872
  dependencies: [{
8847
8873
  kind: "component",
8848
8874
  type: ButtonComponent,
@@ -8912,6 +8938,259 @@ var ImportSourceGridComponent = class ImportSourceGridComponent {
8912
8938
  });
8913
8939
  }
8914
8940
  };
8941
+ i0.ɵɵngDeclareClassMetadata({
8942
+ minVersion: "12.0.0",
8943
+ version: "22.2.2",
8944
+ ngImport: i0,
8945
+ type: OptionCardComponent,
8946
+ decorators: [{
8947
+ type: Component,
8948
+ args: [{
8949
+ selector: "ui-option-card",
8950
+ standalone: true,
8951
+ changeDetection: ChangeDetectionStrategy.OnPush,
8952
+ encapsulation: ViewEncapsulation.None,
8953
+ imports: [ButtonComponent, DetailCardComponent],
8954
+ template: `
8955
+ <ui-detail-card class="oc" [showHeader]="false" [ariaLabel]="title()">
8956
+ <div class="oc-row">
8957
+ <span class="oc-tile" [style.background]="color()" aria-hidden="true">
8958
+ @if (letter()) { {{ letter() }} } @else if (iconD(); as d) { <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path [attr.d]="d" /></svg> }
8959
+ </span>
8960
+ <span class="oc-text">
8961
+ <span class="oc-title">{{ title() }}</span>
8962
+ @if (description()) { <span class="oc-desc">{{ description() }}</span> }
8963
+ </span>
8964
+ @if (actionLabel()) {
8965
+ <ui-button size="xs" [variant]="actionVariant()" [disabled]="disabled()" [loading]="actionLoading()" [attr.data-testid]="actionTestId() || null"
8966
+ [ariaLabel]="actionAriaLabel() || (actionLabel() + ' ' + title())" (click)="action.emit()">{{ actionLabel() }}</ui-button>
8967
+ }
8968
+ </div>
8969
+ <ng-content />
8970
+ </ui-detail-card>
8971
+ `,
8972
+ styles: ["ui-option-card{display:block}ui-option-card .oc{margin-bottom:0}.oc-row{display:flex;align-items:center;gap:12px}.oc-tile{width:36px;height:36px;border-radius:8px;color:#fff;font-size:1rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.oc-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.oc-title{font-size:.8125rem;font-weight:600;color:#1e293b;line-height:1.2}.oc-desc{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}\n"]
8973
+ }]
8974
+ }],
8975
+ propDecorators: {
8976
+ title: [{
8977
+ type: i0.Input,
8978
+ args: [{
8979
+ isSignal: true,
8980
+ alias: "title",
8981
+ required: true
8982
+ }]
8983
+ }],
8984
+ description: [{
8985
+ type: i0.Input,
8986
+ args: [{
8987
+ isSignal: true,
8988
+ alias: "description",
8989
+ required: false
8990
+ }]
8991
+ }],
8992
+ letter: [{
8993
+ type: i0.Input,
8994
+ args: [{
8995
+ isSignal: true,
8996
+ alias: "letter",
8997
+ required: false
8998
+ }]
8999
+ }],
9000
+ icon: [{
9001
+ type: i0.Input,
9002
+ args: [{
9003
+ isSignal: true,
9004
+ alias: "icon",
9005
+ required: false
9006
+ }]
9007
+ }],
9008
+ color: [{
9009
+ type: i0.Input,
9010
+ args: [{
9011
+ isSignal: true,
9012
+ alias: "color",
9013
+ required: false
9014
+ }]
9015
+ }],
9016
+ actionLabel: [{
9017
+ type: i0.Input,
9018
+ args: [{
9019
+ isSignal: true,
9020
+ alias: "actionLabel",
9021
+ required: false
9022
+ }]
9023
+ }],
9024
+ actionVariant: [{
9025
+ type: i0.Input,
9026
+ args: [{
9027
+ isSignal: true,
9028
+ alias: "actionVariant",
9029
+ required: false
9030
+ }]
9031
+ }],
9032
+ actionAriaLabel: [{
9033
+ type: i0.Input,
9034
+ args: [{
9035
+ isSignal: true,
9036
+ alias: "actionAriaLabel",
9037
+ required: false
9038
+ }]
9039
+ }],
9040
+ actionTestId: [{
9041
+ type: i0.Input,
9042
+ args: [{
9043
+ isSignal: true,
9044
+ alias: "actionTestId",
9045
+ required: false
9046
+ }]
9047
+ }],
9048
+ actionLoading: [{
9049
+ type: i0.Input,
9050
+ args: [{
9051
+ isSignal: true,
9052
+ alias: "actionLoading",
9053
+ required: false
9054
+ }]
9055
+ }],
9056
+ disabled: [{
9057
+ type: i0.Input,
9058
+ args: [{
9059
+ isSignal: true,
9060
+ alias: "disabled",
9061
+ required: false
9062
+ }]
9063
+ }],
9064
+ action: [{
9065
+ type: i0.Output,
9066
+ args: ["action"]
9067
+ }]
9068
+ }
9069
+ });
9070
+ var ImportSourceGridComponent = class ImportSourceGridComponent {
9071
+ constructor() {
9072
+ this.sources = input.required(...ngDevMode ? [{ debugName: "sources" }] : /* istanbul ignore next */ []);
9073
+ this.selected = input("", ...ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []);
9074
+ this.appearance = input("tile", ...ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []);
9075
+ this.disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
9076
+ this.actionLabel = input("Select", ...ngDevMode ? [{ debugName: "actionLabel" }] : /* istanbul ignore next */ []);
9077
+ this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
9078
+ this.sourceSelect = output();
9079
+ }
9080
+ static {
9081
+ this.ɵfac = i0.ɵɵngDeclareFactory({
9082
+ minVersion: "12.0.0",
9083
+ version: "22.2.2",
9084
+ ngImport: i0,
9085
+ type: ImportSourceGridComponent,
9086
+ deps: [],
9087
+ target: i0.ɵɵFactoryTarget.Component
9088
+ });
9089
+ }
9090
+ static {
9091
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
9092
+ minVersion: "17.0.0",
9093
+ version: "22.2.2",
9094
+ type: ImportSourceGridComponent,
9095
+ isStandalone: true,
9096
+ selector: "ui-import-source-grid",
9097
+ inputs: {
9098
+ sources: {
9099
+ classPropertyName: "sources",
9100
+ publicName: "sources",
9101
+ isSignal: true,
9102
+ isRequired: true,
9103
+ transformFunction: null
9104
+ },
9105
+ selected: {
9106
+ classPropertyName: "selected",
9107
+ publicName: "selected",
9108
+ isSignal: true,
9109
+ isRequired: false,
9110
+ transformFunction: null
9111
+ },
9112
+ appearance: {
9113
+ classPropertyName: "appearance",
9114
+ publicName: "appearance",
9115
+ isSignal: true,
9116
+ isRequired: false,
9117
+ transformFunction: null
9118
+ },
9119
+ disabled: {
9120
+ classPropertyName: "disabled",
9121
+ publicName: "disabled",
9122
+ isSignal: true,
9123
+ isRequired: false,
9124
+ transformFunction: null
9125
+ },
9126
+ actionLabel: {
9127
+ classPropertyName: "actionLabel",
9128
+ publicName: "actionLabel",
9129
+ isSignal: true,
9130
+ isRequired: false,
9131
+ transformFunction: null
9132
+ },
9133
+ ariaLabel: {
9134
+ classPropertyName: "ariaLabel",
9135
+ publicName: "ariaLabel",
9136
+ isSignal: true,
9137
+ isRequired: false,
9138
+ transformFunction: null
9139
+ }
9140
+ },
9141
+ outputs: { sourceSelect: "sourceSelect" },
9142
+ ngImport: i0,
9143
+ template: `
9144
+ <div class="ie-source-grid" [attr.role]="appearance() === 'card' ? 'group' : 'list'" [class.ie-source-grid--cards]="appearance() === 'card'" [attr.aria-label]="ariaLabel() || null">
9145
+ @for (src of sources(); track src.value) {
9146
+ @if (appearance() === 'card') {
9147
+ <ui-option-card [attr.data-testid]="'source-' + src.value" [title]="src.label" [description]="src.desc || ''" [letter]="src.letter || ''" [color]="src.color || '#64748b'"
9148
+ [actionLabel]="actionLabel()" [actionTestId]="'source-pick-' + src.value" [disabled]="disabled()" (action)="sourceSelect.emit(src.value)" />
9149
+ } @else {
9150
+ <button
9151
+ class="ie-source-card"
9152
+ role="listitem"
9153
+ type="button"
9154
+ [class.ie-source-card--active]="selected() === src.value"
9155
+ [attr.aria-pressed]="selected() === src.value"
9156
+ [attr.data-testid]="'source-' + src.value"
9157
+ (click)="sourceSelect.emit(src.value)">
9158
+ @if (src.letter) {
9159
+ <span class="ie-source-letter" [style.background]="src.color || '#64748b'" aria-hidden="true">{{ src.letter }}</span>
9160
+ }
9161
+ <span class="ie-source-label">{{ src.label }}</span>
9162
+ @if (src.desc) { <span class="ie-source-desc">{{ src.desc }}</span> }
9163
+ </button>
9164
+ }
9165
+ }
9166
+ </div>
9167
+ `,
9168
+ isInline: true,
9169
+ styles: ["ui-import-source-grid{display:block}.ie-source-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}@media(max-width:520px){.ie-source-grid{grid-template-columns:repeat(2,1fr)}}.ie-source-card{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:12px;border:1px solid #e2e8f0;border-radius:10px;background:#fff;cursor:pointer;font-family:inherit;text-align:left;transition:all .15s}.ie-source-card:hover{border-color:#94a3b8;background:#f8fafc}.ie-source-card.ie-source-card--active{border-color:#3b82f6;background:#eff6ff}.ie-source-card:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.ie-source-letter{width:36px;height:36px;border-radius:8px;color:#fff;font-size:1rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-source-label{font-size:.8125rem;font-weight:600;color:#1e293b;line-height:1.2}.ie-source-desc{font-size:.75rem;color:#64748b}.ie-source-grid--cards{grid-template-columns:repeat(2,1fr)}@media(max-width:520px){.ie-source-grid--cards{grid-template-columns:1fr}}\n"],
9170
+ dependencies: [{
9171
+ kind: "component",
9172
+ type: OptionCardComponent,
9173
+ selector: "ui-option-card",
9174
+ inputs: [
9175
+ "title",
9176
+ "description",
9177
+ "letter",
9178
+ "icon",
9179
+ "color",
9180
+ "actionLabel",
9181
+ "actionVariant",
9182
+ "actionAriaLabel",
9183
+ "actionTestId",
9184
+ "actionLoading",
9185
+ "disabled"
9186
+ ],
9187
+ outputs: ["action"]
9188
+ }],
9189
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
9190
+ encapsulation: i0.ViewEncapsulation.None
9191
+ });
9192
+ }
9193
+ };
8915
9194
  i0.ɵɵngDeclareClassMetadata({
8916
9195
  minVersion: "12.0.0",
8917
9196
  version: "22.2.2",
@@ -8924,23 +9203,13 @@ i0.ɵɵngDeclareClassMetadata({
8924
9203
  standalone: true,
8925
9204
  changeDetection: ChangeDetectionStrategy.OnPush,
8926
9205
  encapsulation: ViewEncapsulation.None,
8927
- imports: [ButtonComponent, DetailCardComponent],
9206
+ imports: [OptionCardComponent],
8928
9207
  template: `
8929
9208
  <div class="ie-source-grid" [attr.role]="appearance() === 'card' ? 'group' : 'list'" [class.ie-source-grid--cards]="appearance() === 'card'" [attr.aria-label]="ariaLabel() || null">
8930
9209
  @for (src of sources(); track src.value) {
8931
9210
  @if (appearance() === 'card') {
8932
- <ui-detail-card class="ie-source-detail" [showHeader]="false" [fill]="true" [ariaLabel]="src.label" [attr.data-testid]="'source-' + src.value">
8933
- <div class="ie-source-detail-row">
8934
- @if (src.letter) {
8935
- <span class="ie-source-letter" [style.background]="src.color || '#64748b'" aria-hidden="true">{{ src.letter }}</span>
8936
- }
8937
- <span class="ie-source-detail-text">
8938
- <span class="ie-source-label">{{ src.label }}</span>
8939
- @if (src.desc) { <span class="ie-source-desc">{{ src.desc }}</span> }
8940
- </span>
8941
- <ui-button variant="secondary" size="xs" [attr.data-testid]="'source-pick-' + src.value" [disabled]="disabled()" [ariaLabel]="actionLabel() + ' ' + src.label" (click)="sourceSelect.emit(src.value)">{{ actionLabel() }}</ui-button>
8942
- </div>
8943
- </ui-detail-card>
9211
+ <ui-option-card [attr.data-testid]="'source-' + src.value" [title]="src.label" [description]="src.desc || ''" [letter]="src.letter || ''" [color]="src.color || '#64748b'"
9212
+ [actionLabel]="actionLabel()" [actionTestId]="'source-pick-' + src.value" [disabled]="disabled()" (action)="sourceSelect.emit(src.value)" />
8944
9213
  } @else {
8945
9214
  <button
8946
9215
  class="ie-source-card"
@@ -8960,7 +9229,7 @@ i0.ɵɵngDeclareClassMetadata({
8960
9229
  }
8961
9230
  </div>
8962
9231
  `,
8963
- styles: ["ui-import-source-grid{display:block}.ie-source-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}@media(max-width:520px){.ie-source-grid{grid-template-columns:repeat(2,1fr)}}.ie-source-card{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:12px;border:1px solid #e2e8f0;border-radius:10px;background:#fff;cursor:pointer;font-family:inherit;text-align:left;transition:all .15s}.ie-source-card:hover{border-color:#94a3b8;background:#f8fafc}.ie-source-card.ie-source-card--active{border-color:#3b82f6;background:#eff6ff}.ie-source-card:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.ie-source-letter{width:36px;height:36px;border-radius:8px;color:#fff;font-size:1rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-source-label{font-size:.8125rem;font-weight:600;color:#1e293b;line-height:1.2}.ie-source-desc{font-size:.75rem;color:#64748b}.ie-source-grid--cards{grid-template-columns:repeat(2,1fr)}@media(max-width:520px){.ie-source-grid--cards{grid-template-columns:1fr}}ui-import-source-grid .ie-source-detail.ie-source-detail{margin-bottom:0}.ie-source-detail-row{display:flex;align-items:center;gap:12px}.ie-source-detail-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}\n"]
9232
+ styles: ["ui-import-source-grid{display:block}.ie-source-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}@media(max-width:520px){.ie-source-grid{grid-template-columns:repeat(2,1fr)}}.ie-source-card{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:12px;border:1px solid #e2e8f0;border-radius:10px;background:#fff;cursor:pointer;font-family:inherit;text-align:left;transition:all .15s}.ie-source-card:hover{border-color:#94a3b8;background:#f8fafc}.ie-source-card.ie-source-card--active{border-color:#3b82f6;background:#eff6ff}.ie-source-card:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.ie-source-letter{width:36px;height:36px;border-radius:8px;color:#fff;font-size:1rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-source-label{font-size:.8125rem;font-weight:600;color:#1e293b;line-height:1.2}.ie-source-desc{font-size:.75rem;color:#64748b}.ie-source-grid--cards{grid-template-columns:repeat(2,1fr)}@media(max-width:520px){.ie-source-grid--cards{grid-template-columns:1fr}}\n"]
8964
9233
  }]
8965
9234
  }],
8966
9235
  propDecorators: {
@@ -42614,6 +42883,10 @@ const DEFAULT_TEXTS = {
42614
42883
  selectSource: "Select",
42615
42884
  connected: "Connected",
42616
42885
  importMore: "Import more",
42886
+ importRequired: "Import your data to continue, or skip this step.",
42887
+ importErrorsTitle: (errors) => `${errors} row${errors === 1 ? "" : "s"} could not be imported`,
42888
+ importErrorsText: (imported, errors) => `${imported} imported. Fix the ${errors === 1 ? "row" : "rows"} listed in the import window in your file and import ${errors === 1 ? "it" : "them"} again (only the ${errors === 1 ? "row" : "rows"} that failed, so nothing is imported twice) to continue.`,
42889
+ importAgain: "Import again",
42617
42890
  whatGetsImported: "WHAT GETS IMPORTED:",
42618
42891
  doneTitle: "You're All Set!",
42619
42892
  doneDescription: "Your account is configured and ready to go. Here's a quick summary:",
@@ -42641,6 +42914,20 @@ var SetupWizardComponent = class SetupWizardComponent {
42641
42914
  this.http = inject(HttpClient);
42642
42915
  this.apiBase = inject(FORGEROUTE_CONFIG, { optional: true })?.baseUrl ?? "/api";
42643
42916
  this.destroyRef = inject(DestroyRef);
42917
+ this.narrow = signal(false, ...ngDevMode ? [{ debugName: "narrow" }] : /* istanbul ignore next */ []);
42918
+ this.importBlocked = computed(() => {
42919
+ const st = this.current();
42920
+ return st.kind === "import" && !!st.requireImport && !this.completed().has(st.key);
42921
+ }, ...ngDevMode ? [{ debugName: "importBlocked" }] : /* istanbul ignore next */ []);
42922
+ this.splitTab = signal("extra", ...ngDevMode ? [{ debugName: "splitTab" }] : /* istanbul ignore next */ []);
42923
+ this.splitTabs = computed(() => [{
42924
+ key: "extra",
42925
+ label: this.current().extraTab || this.current().extraTitle || ""
42926
+ }, {
42927
+ key: "main",
42928
+ label: this.current().mainTab || this.current().cardTitle || ""
42929
+ }], ...ngDevMode ? [{ debugName: "splitTabs" }] : /* istanbul ignore next */ []);
42930
+ this.split = computed(() => this.current().kind !== "custom" && !!this.current().splitLayout && !!this.templateFor(this.current().key), ...ngDevMode ? [{ debugName: "split" }] : /* istanbul ignore next */ []);
42644
42931
  this.steps = input.required(...ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []);
42645
42932
  this.texts = input({}, ...ngDevMode ? [{ debugName: "texts" }] : /* istanbul ignore next */ []);
42646
42933
  this.finished = output();
@@ -42648,6 +42935,8 @@ var SetupWizardComponent = class SetupWizardComponent {
42648
42935
  this.stepChange = output();
42649
42936
  this.stepTemplates = contentChildren(SetupWizardStepDirective, ...ngDevMode ? [{ debugName: "stepTemplates" }] : /* istanbul ignore next */ []);
42650
42937
  this.headerTemplates = contentChildren(SetupWizardStepHeaderDirective, ...ngDevMode ? [{ debugName: "headerTemplates" }] : /* istanbul ignore next */ []);
42938
+ this.injector = inject(Injector);
42939
+ this.stepTitle = viewChild("stepTitle", ...ngDevMode ? [{ debugName: "stepTitle" }] : /* istanbul ignore next */ []);
42651
42940
  this.importers = viewChildren("importer", ...ngDevMode ? [{ debugName: "importers" }] : /* istanbul ignore next */ []);
42652
42941
  this.t = computed(() => ({
42653
42942
  ...DEFAULT_TEXTS,
@@ -42657,6 +42946,7 @@ var SetupWizardComponent = class SetupWizardComponent {
42657
42946
  this.completed = signal(/* @__PURE__ */ new Set(), ...ngDevMode ? [{ debugName: "completed" }] : /* istanbul ignore next */ []);
42658
42947
  this.skipped = signal(/* @__PURE__ */ new Set(), ...ngDevMode ? [{ debugName: "skipped" }] : /* istanbul ignore next */ []);
42659
42948
  this.imports = signal({}, ...ngDevMode ? [{ debugName: "imports" }] : /* istanbul ignore next */ []);
42949
+ this.importErrors = signal({}, ...ngDevMode ? [{ debugName: "importErrors" }] : /* istanbul ignore next */ []);
42660
42950
  this.statuses = signal({}, ...ngDevMode ? [{ debugName: "statuses" }] : /* istanbul ignore next */ []);
42661
42951
  this.busy = signal(false, ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
42662
42952
  this.api = {
@@ -42701,6 +42991,13 @@ var SetupWizardComponent = class SetupWizardComponent {
42701
42991
  variant: "slate"
42702
42992
  }
42703
42993
  })) }], ...ngDevMode ? [{ debugName: "summarySections" }] : /* istanbul ignore next */ []);
42994
+ if (typeof matchMedia === "function") {
42995
+ const mq = matchMedia("(max-width: 768px)");
42996
+ this.narrow.set(mq.matches);
42997
+ const on = (e) => this.narrow.set(e.matches);
42998
+ mq.addEventListener("change", on);
42999
+ this.destroyRef.onDestroy(() => mq.removeEventListener("change", on));
43000
+ }
42704
43001
  effect(() => {
42705
43002
  const steps = this.allSteps();
42706
43003
  untracked(() => {
@@ -42721,11 +43018,13 @@ var SetupWizardComponent = class SetupWizardComponent {
42721
43018
  this.error.set("");
42722
43019
  this.areaCodeOpen.set("");
42723
43020
  this.areaCode.set("");
43021
+ this.splitTab.set("extra");
42724
43022
  this.currentKey.set(key);
42725
43023
  const step = this.allSteps().find((s) => s.key === key);
42726
43024
  if (step.kind === "integrations") this.loadStatuses(step.integrations ?? []);
42727
43025
  step.onEnter?.();
42728
43026
  this.stepChange.emit(key);
43027
+ afterNextRender(() => this.stepTitle()?.nativeElement.focus(), { injector: this.injector });
42729
43028
  }
42730
43029
  advanceFrom(key) {
42731
43030
  const steps = this.allSteps();
@@ -42791,23 +43090,37 @@ var SetupWizardComponent = class SetupWizardComponent {
42791
43090
  this.importers()[0]?.openImport();
42792
43091
  }
42793
43092
  onImported(key) {
42794
- const imported = this.importers()[0]?.importResult?.imported ?? 0;
43093
+ const result = this.importers()[0]?.importResult;
43094
+ const imported = result?.imported ?? 0;
43095
+ const errors = result?.errors?.length ?? 0;
42795
43096
  this.imports.update((m) => ({
42796
43097
  ...m,
42797
43098
  [key]: imported
42798
43099
  }));
42799
- this.markCompleted(key);
43100
+ this.importErrors.update((m) => ({
43101
+ ...m,
43102
+ [key]: errors
43103
+ }));
43104
+ if (imported > 0 && errors === 0) this.markCompleted(key);
42800
43105
  }
42801
43106
  importResult(key) {
42802
43107
  const n = this.imports()[key];
42803
43108
  return n === void 0 ? null : n;
42804
43109
  }
43110
+ importErrorCount(key) {
43111
+ return this.importErrors()[key] ?? 0;
43112
+ }
42805
43113
  clearImport(key) {
42806
43114
  this.imports.update((m) => {
42807
43115
  const n = { ...m };
42808
43116
  delete n[key];
42809
43117
  return n;
42810
43118
  });
43119
+ this.importErrors.update((m) => {
43120
+ const n = { ...m };
43121
+ delete n[key];
43122
+ return n;
43123
+ });
42811
43124
  }
42812
43125
  importTitle(key) {
42813
43126
  const imp = this.steps().find((s) => s.key === key)?.import;
@@ -42842,6 +43155,20 @@ var SetupWizardComponent = class SetupWizardComponent {
42842
43155
  this.error.set("");
42843
43156
  this.areaCodeOpen.set("");
42844
43157
  this.areaCode.set("");
43158
+ if (!i.beforeConnect) {
43159
+ this.startConnect(i);
43160
+ return;
43161
+ }
43162
+ this.busy.set(true);
43163
+ this.run(i.beforeConnect()).then(() => {
43164
+ this.busy.set(false);
43165
+ this.startConnect(i);
43166
+ }, (e) => {
43167
+ this.busy.set(false);
43168
+ this.error.set(this.messageOf(e, this.t().connectIntegrationFailed(i.title)));
43169
+ });
43170
+ }
43171
+ startConnect(i) {
42845
43172
  if (i.connect.type === "area-code") {
42846
43173
  this.areaCodeOpen.set(i.key);
42847
43174
  return;
@@ -42928,6 +43255,12 @@ var SetupWizardComponent = class SetupWizardComponent {
42928
43255
  isSignal: true
42929
43256
  }],
42930
43257
  viewQueries: [{
43258
+ propertyName: "stepTitle",
43259
+ first: true,
43260
+ predicate: ["stepTitle"],
43261
+ descendants: true,
43262
+ isSignal: true
43263
+ }, {
42931
43264
  propertyName: "importers",
42932
43265
  predicate: ["importer"],
42933
43266
  descendants: true,
@@ -42936,7 +43269,7 @@ var SetupWizardComponent = class SetupWizardComponent {
42936
43269
  ngImport: i0,
42937
43270
  template: `
42938
43271
  <div class="sw-page" data-testid="setup-wizard-page">
42939
- <aside class="sw-sidebar">
43272
+ <aside class="sw-sidebar" [attr.aria-label]="t().brand">
42940
43273
  <div class="sw-sidebar-top">
42941
43274
  <div class="sw-brand">
42942
43275
  <ng-content select="[setup-wizard-logo]" />
@@ -42953,7 +43286,7 @@ var SetupWizardComponent = class SetupWizardComponent {
42953
43286
 
42954
43287
  <main class="sw-content">
42955
43288
  <div class="sw-content-header">
42956
- <h1 class="sw-step-title" data-testid="wizard-step-title">{{ current().label }}</h1>
43289
+ <h1 #stepTitle class="sw-step-title" tabindex="-1" data-testid="wizard-step-title">{{ current().label }}</h1>
42957
43290
  <ui-button variant="ghost" size="sm" data-testid="wizard-exit" (click)="exited.emit()"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('close')" /></svg> {{ t().exit }}</ui-button>
42958
43291
  </div>
42959
43292
 
@@ -42965,15 +43298,47 @@ var SetupWizardComponent = class SetupWizardComponent {
42965
43298
  <ui-button variant="primary" size="sm" data-testid="wizard-finish" (click)="finished.emit()"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('check')" /></svg> {{ t().finish }}</ui-button>
42966
43299
  </div>
42967
43300
  } @else {
42968
- <div class="sw-step-content" [attr.data-step]="current().key">
43301
+ <div class="sw-step-content" [attr.aria-busy]="busy()" [attr.data-step]="current().key">
42969
43302
  @if (intro(); as i) { <ui-section-header class="sw-intro" data-testid="wizard-step-intro" size="lg" background="#eaf3ff" [title]="i.title" [description]="i.text"><span section-header-icon class="sw-step-number" data-testid="wizard-step-number">{{ index() + 1 }}</span></ui-section-header> }
42970
43303
 
43304
+ <ng-template #actions>
43305
+ @if (index() > 0) { <ui-button variant="secondary" size="sm" [fullWidth]="narrow()" data-testid="wizard-back" [disabled]="busy()" (click)="back()"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-left')" /></svg> {{ t().back }}</ui-button> } @else { <span></span> }
43306
+ <div class="sw-actions-right">
43307
+ @if (current().skippable !== false) {
43308
+ <ui-button variant="secondary" size="sm" [fullWidth]="narrow()" data-testid="wizard-skip" [disabled]="busy()" (click)="skip()">{{ t().skip }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('chevron-right')" /></svg></ui-button>
43309
+ }
43310
+ @if (current().kind === 'custom') {
43311
+ @if (!current().ownActions) {
43312
+ <ui-button variant="primary" size="sm" [fullWidth]="narrow()" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (click)="saveAndContinue()">
43313
+ {{ current().saveLabel ?? t().saveAndContinue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg>
43314
+ </ui-button>
43315
+ }
43316
+ } @else if (current().kind === 'integrations') {
43317
+ <ui-button variant="primary" size="sm" [fullWidth]="narrow()" data-testid="wizard-save" [loading]="busy()" (click)="saveAndContinue()">{{ t().saveAndContinue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg></ui-button>
43318
+ } @else if (current().kind === 'import') {
43319
+ <ui-button variant="primary" size="sm" [fullWidth]="narrow()" data-testid="wizard-continue" [disabled]="importBlocked()" [ariaDescribedBy]="importBlocked() ? 'sw-continue-hint' : ''" (click)="continueFromImport()">{{ t().continue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg></ui-button>
43320
+ }
43321
+ </div>
43322
+ </ng-template>
43323
+ @if (split()) {
43324
+ <ui-pill-tabs class="sw-split-tabs" [tabs]="splitTabs()" [activeKey]="splitTab()" [ariaLabel]="current().label" (tabChange)="splitTab.set($event === 'main' ? 'main' : 'extra')" data-testid="wizard-split-tabs" />
43325
+ }
43326
+ @if (split() && splitTab() === 'extra' && templateFor(current().key); as left) {
43327
+ <ui-detail-card class="sw-card sw-extra-card" [title]="current().extraTitle ?? ''" [showHeader]="!!current().extraTitle" [headingLevel]="3" [collapsible]="false"
43328
+ [ariaLabel]="current().extraTitle || current().label" headerBackground="rgb(248, 250, 252)" footerBackground="rgb(248, 250, 252)" data-testid="wizard-extra-card">
43329
+ <ng-container [ngTemplateOutlet]="left" [ngTemplateOutletContext]="{ $implicit: api }" />
43330
+ <p class="sw-extra-status" role="status" data-testid="wizard-extra-status">{{ current().extraFooter?.() }}</p>
43331
+ @if (importBlocked()) { <p class="sw-hint sw-continue-hint" id="sw-continue-hint" data-testid="wizard-continue-hint">{{ t().importRequired }}</p> }
43332
+ <div card-footer class="sw-step-actions"><ng-container [ngTemplateOutlet]="actions" /></div>
43333
+ </ui-detail-card>
43334
+ }
43335
+ @if (!split() || splitTab() === 'main') {
42971
43336
  <ui-detail-card class="sw-card" [showHeader]="!!current().cardTitle || !!headerTemplateFor(current().key)" [title]="current().cardTitle ?? ''" [headingLevel]="3" [collapsible]="false"
42972
43337
  [ariaLabel]="current().label" headerBackground="rgb(248, 250, 252)" footerBackground="rgb(248, 250, 252)" data-testid="wizard-step-card">
42973
43338
  @if (headerTemplateFor(current().key); as ht) {
42974
43339
  <div card-header-action class="sw-header-action" data-testid="wizard-card-header-action"><ng-container [ngTemplateOutlet]="ht" [ngTemplateOutletContext]="{ $implicit: api }" /></div>
42975
43340
  }
42976
- @if (current().kind !== 'custom' && templateFor(current().key); as extra) {
43341
+ @if (!split() && current().kind !== 'custom' && templateFor(current().key); as extra) {
42977
43342
  <ng-container [ngTemplateOutlet]="extra" [ngTemplateOutletContext]="{ $implicit: api }" />
42978
43343
  }
42979
43344
  @switch (current().kind) {
@@ -42988,7 +43353,12 @@ var SetupWizardComponent = class SetupWizardComponent {
42988
43353
  @for (tag of imp.tags; track tag) { <ui-badge [label]="tag" variant="slate" /> }
42989
43354
  </div>
42990
43355
  }
42991
- @if (importResult(current().key); as res) {
43356
+ @if (importErrorCount(current().key) > 0) {
43357
+ <ui-alert variant="warning" [title]="t().importErrorsTitle(importErrorCount(current().key))" [attr.data-testid]="'import-errors-' + current().key">
43358
+ {{ t().importErrorsText(importResult(current().key) ?? 0, importErrorCount(current().key)) }}
43359
+ <ui-button variant="link" size="sm" data-testid="import-again" (click)="clearImport(current().key)"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('upload')" /></svg> {{ t().importAgain }}</ui-button>
43360
+ </ui-alert>
43361
+ } @else if (importResult(current().key); as res) {
42992
43362
  <ui-alert variant="success" [title]="importTitle(current().key)" [attr.data-testid]="'import-result-' + current().key">
42993
43363
  {{ imp.resultText }}
42994
43364
  <ui-button variant="link" size="sm" data-testid="import-more" (click)="clearImport(current().key)"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('upload')" /></svg> {{ t().importMore }}</ui-button>
@@ -43007,56 +43377,35 @@ var SetupWizardComponent = class SetupWizardComponent {
43007
43377
  @case ('integrations') {
43008
43378
  <div class="sw-provider-grid">
43009
43379
  @for (it of current().integrations ?? []; track it.key) {
43010
- <ui-detail-card class="sw-integration" [attr.data-testid]="'integration-' + it.key" [showHeader]="false" [fill]="true" [ariaLabel]="it.title">
43011
- <div class="sw-int-row">
43012
- <span class="sw-int-tile" [style.background]="it.color || '#64748b'" aria-hidden="true">@if (it.letter) { {{ it.letter }} } @else { <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path [attr.d]="iconD(it.icon ?? 'link')" /></svg> }</span>
43013
- <span class="sw-int-text">
43014
- <span class="sw-int-title">{{ it.title }}</span>
43015
- <span class="sw-int-detail">{{ detailFor(it) }}</span>
43016
- </span>
43017
- <ui-button variant="secondary" size="xs" [attr.data-testid]="'integration-pick-' + it.key" [ariaLabel]="(isConnected(it) ? t().reconnect : t().connect) + ' ' + it.title" (click)="connect(it)">{{ isConnected(it) ? t().reconnect : t().connect }}</ui-button>
43018
- </div>
43380
+ <ui-option-card class="sw-integration" [attr.data-testid]="'integration-' + it.key" [title]="it.title" [description]="detailFor(it)" [letter]="it.letter || ''"
43381
+ [icon]="it.letter ? '' : (it.icon ?? 'link')" [color]="it.color || '#64748b'" [actionLabel]="isConnected(it) ? t().reconnect : t().connect"
43382
+ [actionTestId]="'integration-pick-' + it.key" (action)="connect(it)">
43019
43383
  @if (areaCodeOpen() === it.key) {
43020
43384
  <div class="sw-area-code" [attr.data-testid]="'area-code-' + it.key">
43021
43385
  <ui-text-input [label]="areaCodeLabelFor(it)" [maxlength]="3" inputmode="numeric" [ngModel]="areaCode()" (ngModelChange)="areaCode.set($event ?? '')" [inputTestId]="'area-code-input-' + it.key" />
43022
43386
  <ui-button variant="primary" size="sm" [loading]="busy()" [disabled]="!validAreaCode()" (click)="submitAreaCode(it)"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('link')" /></svg> {{ t().connect }}</ui-button>
43023
43387
  </div>
43024
43388
  }
43025
- </ui-detail-card>
43389
+ </ui-option-card>
43026
43390
  }
43027
43391
  </div>
43028
43392
  }
43029
43393
  }
43030
43394
 
43395
+ @if (importBlocked()) { <p class="sw-hint sw-continue-hint" id="sw-continue-hint" data-testid="wizard-continue-hint">{{ t().importRequired }}</p> }
43396
+
43031
43397
  @if (error()) { <ui-alert variant="danger" data-testid="wizard-save-error">{{ error() }}</ui-alert> }
43032
43398
 
43033
- <div card-footer class="sw-step-actions">
43034
- @if (index() > 0) { <ui-button variant="secondary" size="sm" data-testid="wizard-back" [disabled]="busy()" (click)="back()"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-left')" /></svg> {{ t().back }}</ui-button> } @else { <span></span> }
43035
- <div class="sw-actions-right">
43036
- @if (current().skippable !== false) {
43037
- <ui-button variant="secondary" size="sm" data-testid="wizard-skip" [disabled]="busy()" (click)="skip()">{{ t().skip }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('chevron-right')" /></svg></ui-button>
43038
- }
43039
- @if (current().kind === 'custom') {
43040
- @if (!current().ownActions) {
43041
- <ui-button variant="primary" size="sm" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (click)="saveAndContinue()">
43042
- {{ current().saveLabel ?? t().saveAndContinue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg>
43043
- </ui-button>
43044
- }
43045
- } @else if (current().kind === 'integrations') {
43046
- <ui-button variant="primary" size="sm" data-testid="wizard-save" [loading]="busy()" (click)="saveAndContinue()">{{ t().saveAndContinue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg></ui-button>
43047
- } @else if (current().kind === 'import') {
43048
- <ui-button variant="primary" size="sm" data-testid="wizard-continue" (click)="continueFromImport()">{{ t().continue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg></ui-button>
43049
- }
43050
- </div>
43051
- </div>
43399
+ <div card-footer class="sw-step-actions"><ng-container [ngTemplateOutlet]="actions" /></div>
43052
43400
  </ui-detail-card>
43401
+ }
43053
43402
  </div>
43054
43403
  }
43055
43404
  </main>
43056
43405
  </div>
43057
43406
  `,
43058
43407
  isInline: true,
43059
- styles: [".sw-page{display:flex;min-height:100vh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.sw-sidebar{width:260px;min-width:260px;background:#faf9f7;border-right:1px solid #e5e2dc;display:flex;flex-direction:column;justify-content:space-between;padding:28px 20px}.sw-brand{display:flex;align-items:center;gap:10px;margin-bottom:28px}.sw-brand-text{font-size:1.125rem;font-weight:700;color:#1e293b}.sw-step-nav{display:block}.sw-sidebar-bottom{margin-top:24px}.sw-progress-text{display:block;margin-top:8px;font-size:.75rem;color:#94a3b8}.sw-content{flex:1;min-width:0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.sw-content-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 32px;border-bottom:1px solid #f1f5f9}.sw-step-title{font-size:1.25rem;font-weight:700;color:#111827;margin:0}.sw-step-content{max-width:780px;padding:16px 48px 60px}.sw-intro{margin-bottom:24px}.sw-step-number{font-size:1.25rem;font-weight:800;line-height:1}.sw-step-desc{font-size:.9375rem;color:#6b7280;line-height:1.5;margin:0 0 32px}.sw-hint{font-size:.8125rem;color:#94a3b8;margin:0 0 16px}.sw-import-tags{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px}.sw-tag{font-size:.6875rem;font-weight:700;letter-spacing:1px;color:#6b7280}.sw-provider-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:8px}@media(max-width:768px){.sw-provider-grid{grid-template-columns:1fr}}.sw-provider-grid .sw-integration{margin-bottom:0}.sw-int-row{display:flex;align-items:center;gap:12px}.sw-int-tile{width:36px;height:36px;border-radius:8px;color:#fff;font-size:1rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.sw-int-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.sw-int-title{font-size:.8125rem;font-weight:600;color:#1e293b;line-height:1.2}.sw-int-detail{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.sw-area-code{display:flex;align-items:flex-end;gap:12px;margin-top:12px;max-width:320px}.sw-area-code ui-text-input{flex:1}.sw-content ui-alert{display:block;margin-bottom:16px}.sw-card{display:block}.sw-header-action{margin-left:auto;min-width:0;max-width:100%}.sw-step-actions{display:flex;justify-content:space-between;align-items:center}.sw-ico{flex-shrink:0;vertical-align:-2px}.sw-actions-right{display:flex;align-items:center;gap:16px}.sw-done{text-align:center;display:flex;flex-direction:column;align-items:center;max-width:none}.sw-done .sw-step-desc{max-width:480px}.sw-summary{display:block;width:100%;max-width:480px;margin-bottom:24px;text-align:left}.sw-done-hint{font-size:.8125rem;color:#9ca3af;margin-bottom:24px}@media(max-width:768px){.sw-page{flex-direction:column}.sw-sidebar{width:100%;min-width:unset;padding:16px}.sw-brand{margin-bottom:12px}.sw-sidebar-bottom{display:none}.sw-step-content{padding:12px 20px 40px}}\n"],
43408
+ styles: [".sw-page{display:flex;min-height:100vh;min-height:100dvh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.sw-sidebar{width:260px;min-width:260px;background:#faf9f7;border-right:1px solid #e5e2dc;display:flex;flex-direction:column;justify-content:space-between;padding:28px 20px}.sw-brand{display:flex;align-items:center;gap:10px;margin-bottom:28px}.sw-brand-text{font-size:1.125rem;font-weight:700;color:#1e293b}.sw-step-nav{display:block}.sw-sidebar-bottom{margin-top:24px}.sw-progress-text{display:block;margin-top:8px;font-size:.75rem;color:#94a3b8}.sw-content{flex:1;min-width:0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.sw-content-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 32px;border-bottom:1px solid #f1f5f9}.sw-step-title{font-size:1.25rem;font-weight:700;color:#111827;margin:0}.sw-step-content{max-width:780px;padding:16px 48px 60px}.sw-intro{margin-bottom:24px}.sw-step-number{font-size:1.25rem;font-weight:800;line-height:1}.sw-step-desc{font-size:.9375rem;color:#6b7280;line-height:1.5;margin:0 0 32px}.sw-split-tabs{display:block;margin-bottom:16px}.sw-hint.sw-continue-hint{margin:14px 0 0}.sw-extra-status{font-size:.8125rem;color:#64748b;margin:12px 0 0}.sw-extra-status:empty{display:none}.sw-hint{font-size:.8125rem;line-height:1.5;color:#64748b;margin:0 0 16px}.sw-import-tags{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px}.sw-tag{font-size:.6875rem;font-weight:700;letter-spacing:1px;color:#6b7280}.sw-provider-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:8px}@media(max-width:768px){.sw-provider-grid{grid-template-columns:1fr}}.sw-provider-grid .sw-integration{margin-bottom:0}.sw-area-code{display:flex;align-items:flex-end;gap:12px;margin-top:12px;max-width:320px}.sw-area-code ui-text-input{flex:1}.sw-content ui-alert{display:block;margin-bottom:16px}.sw-card{display:block}.sw-header-action{margin-left:auto;min-width:0;max-width:100%}.sw-step-actions{display:flex;justify-content:space-between;align-items:center}.sw-ico{flex-shrink:0;vertical-align:-2px}.sw-actions-right{display:flex;align-items:center;gap:16px;margin-left:auto}.sw-done{text-align:center;display:flex;flex-direction:column;align-items:center;max-width:none}.sw-done .sw-step-desc{max-width:480px}.sw-summary{display:block;width:100%;max-width:480px;margin-bottom:24px;text-align:left}.sw-done-hint{font-size:.8125rem;color:#9ca3af;margin-bottom:24px}@media(max-width:768px){.sw-step-actions{flex-direction:column-reverse;align-items:stretch;gap:10px}.sw-actions-right{flex-direction:column-reverse;align-items:stretch;gap:10px;margin-left:0}.sw-page{flex-direction:column}.sw-sidebar{width:100%;min-width:unset;padding:16px}.sw-brand{margin-bottom:12px}.sw-sidebar-bottom{display:none}.sw-step-content{padding:12px 20px 40px}}\n"],
43060
43409
  dependencies: [
43061
43410
  {
43062
43411
  kind: "directive",
@@ -43208,6 +43557,37 @@ var SetupWizardComponent = class SetupWizardComponent {
43208
43557
  ],
43209
43558
  outputs: ["sourceSelect"]
43210
43559
  },
43560
+ {
43561
+ kind: "component",
43562
+ type: OptionCardComponent,
43563
+ selector: "ui-option-card",
43564
+ inputs: [
43565
+ "title",
43566
+ "description",
43567
+ "letter",
43568
+ "icon",
43569
+ "color",
43570
+ "actionLabel",
43571
+ "actionVariant",
43572
+ "actionAriaLabel",
43573
+ "actionTestId",
43574
+ "actionLoading",
43575
+ "disabled"
43576
+ ],
43577
+ outputs: ["action"]
43578
+ },
43579
+ {
43580
+ kind: "component",
43581
+ type: PillTabsComponent,
43582
+ selector: "ui-pill-tabs",
43583
+ inputs: [
43584
+ "tabs",
43585
+ "activeKey",
43586
+ "ariaLabel",
43587
+ "name"
43588
+ ],
43589
+ outputs: ["tabChange"]
43590
+ },
43211
43591
  {
43212
43592
  kind: "component",
43213
43593
  type: PanelInfoListComponent,
@@ -43346,6 +43726,8 @@ i0.ɵɵngDeclareClassMetadata({
43346
43726
  ImportExportComponent,
43347
43727
  DetailCardComponent,
43348
43728
  ImportSourceGridComponent,
43729
+ OptionCardComponent,
43730
+ PillTabsComponent,
43349
43731
  PanelInfoListComponent,
43350
43732
  ProgressBarComponent,
43351
43733
  SectionHeaderComponent,
@@ -43354,7 +43736,7 @@ i0.ɵɵngDeclareClassMetadata({
43354
43736
  ],
43355
43737
  template: `
43356
43738
  <div class="sw-page" data-testid="setup-wizard-page">
43357
- <aside class="sw-sidebar">
43739
+ <aside class="sw-sidebar" [attr.aria-label]="t().brand">
43358
43740
  <div class="sw-sidebar-top">
43359
43741
  <div class="sw-brand">
43360
43742
  <ng-content select="[setup-wizard-logo]" />
@@ -43371,7 +43753,7 @@ i0.ɵɵngDeclareClassMetadata({
43371
43753
 
43372
43754
  <main class="sw-content">
43373
43755
  <div class="sw-content-header">
43374
- <h1 class="sw-step-title" data-testid="wizard-step-title">{{ current().label }}</h1>
43756
+ <h1 #stepTitle class="sw-step-title" tabindex="-1" data-testid="wizard-step-title">{{ current().label }}</h1>
43375
43757
  <ui-button variant="ghost" size="sm" data-testid="wizard-exit" (click)="exited.emit()"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('close')" /></svg> {{ t().exit }}</ui-button>
43376
43758
  </div>
43377
43759
 
@@ -43383,15 +43765,47 @@ i0.ɵɵngDeclareClassMetadata({
43383
43765
  <ui-button variant="primary" size="sm" data-testid="wizard-finish" (click)="finished.emit()"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('check')" /></svg> {{ t().finish }}</ui-button>
43384
43766
  </div>
43385
43767
  } @else {
43386
- <div class="sw-step-content" [attr.data-step]="current().key">
43768
+ <div class="sw-step-content" [attr.aria-busy]="busy()" [attr.data-step]="current().key">
43387
43769
  @if (intro(); as i) { <ui-section-header class="sw-intro" data-testid="wizard-step-intro" size="lg" background="#eaf3ff" [title]="i.title" [description]="i.text"><span section-header-icon class="sw-step-number" data-testid="wizard-step-number">{{ index() + 1 }}</span></ui-section-header> }
43388
43770
 
43771
+ <ng-template #actions>
43772
+ @if (index() > 0) { <ui-button variant="secondary" size="sm" [fullWidth]="narrow()" data-testid="wizard-back" [disabled]="busy()" (click)="back()"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-left')" /></svg> {{ t().back }}</ui-button> } @else { <span></span> }
43773
+ <div class="sw-actions-right">
43774
+ @if (current().skippable !== false) {
43775
+ <ui-button variant="secondary" size="sm" [fullWidth]="narrow()" data-testid="wizard-skip" [disabled]="busy()" (click)="skip()">{{ t().skip }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('chevron-right')" /></svg></ui-button>
43776
+ }
43777
+ @if (current().kind === 'custom') {
43778
+ @if (!current().ownActions) {
43779
+ <ui-button variant="primary" size="sm" [fullWidth]="narrow()" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (click)="saveAndContinue()">
43780
+ {{ current().saveLabel ?? t().saveAndContinue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg>
43781
+ </ui-button>
43782
+ }
43783
+ } @else if (current().kind === 'integrations') {
43784
+ <ui-button variant="primary" size="sm" [fullWidth]="narrow()" data-testid="wizard-save" [loading]="busy()" (click)="saveAndContinue()">{{ t().saveAndContinue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg></ui-button>
43785
+ } @else if (current().kind === 'import') {
43786
+ <ui-button variant="primary" size="sm" [fullWidth]="narrow()" data-testid="wizard-continue" [disabled]="importBlocked()" [ariaDescribedBy]="importBlocked() ? 'sw-continue-hint' : ''" (click)="continueFromImport()">{{ t().continue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg></ui-button>
43787
+ }
43788
+ </div>
43789
+ </ng-template>
43790
+ @if (split()) {
43791
+ <ui-pill-tabs class="sw-split-tabs" [tabs]="splitTabs()" [activeKey]="splitTab()" [ariaLabel]="current().label" (tabChange)="splitTab.set($event === 'main' ? 'main' : 'extra')" data-testid="wizard-split-tabs" />
43792
+ }
43793
+ @if (split() && splitTab() === 'extra' && templateFor(current().key); as left) {
43794
+ <ui-detail-card class="sw-card sw-extra-card" [title]="current().extraTitle ?? ''" [showHeader]="!!current().extraTitle" [headingLevel]="3" [collapsible]="false"
43795
+ [ariaLabel]="current().extraTitle || current().label" headerBackground="rgb(248, 250, 252)" footerBackground="rgb(248, 250, 252)" data-testid="wizard-extra-card">
43796
+ <ng-container [ngTemplateOutlet]="left" [ngTemplateOutletContext]="{ $implicit: api }" />
43797
+ <p class="sw-extra-status" role="status" data-testid="wizard-extra-status">{{ current().extraFooter?.() }}</p>
43798
+ @if (importBlocked()) { <p class="sw-hint sw-continue-hint" id="sw-continue-hint" data-testid="wizard-continue-hint">{{ t().importRequired }}</p> }
43799
+ <div card-footer class="sw-step-actions"><ng-container [ngTemplateOutlet]="actions" /></div>
43800
+ </ui-detail-card>
43801
+ }
43802
+ @if (!split() || splitTab() === 'main') {
43389
43803
  <ui-detail-card class="sw-card" [showHeader]="!!current().cardTitle || !!headerTemplateFor(current().key)" [title]="current().cardTitle ?? ''" [headingLevel]="3" [collapsible]="false"
43390
43804
  [ariaLabel]="current().label" headerBackground="rgb(248, 250, 252)" footerBackground="rgb(248, 250, 252)" data-testid="wizard-step-card">
43391
43805
  @if (headerTemplateFor(current().key); as ht) {
43392
43806
  <div card-header-action class="sw-header-action" data-testid="wizard-card-header-action"><ng-container [ngTemplateOutlet]="ht" [ngTemplateOutletContext]="{ $implicit: api }" /></div>
43393
43807
  }
43394
- @if (current().kind !== 'custom' && templateFor(current().key); as extra) {
43808
+ @if (!split() && current().kind !== 'custom' && templateFor(current().key); as extra) {
43395
43809
  <ng-container [ngTemplateOutlet]="extra" [ngTemplateOutletContext]="{ $implicit: api }" />
43396
43810
  }
43397
43811
  @switch (current().kind) {
@@ -43406,7 +43820,12 @@ i0.ɵɵngDeclareClassMetadata({
43406
43820
  @for (tag of imp.tags; track tag) { <ui-badge [label]="tag" variant="slate" /> }
43407
43821
  </div>
43408
43822
  }
43409
- @if (importResult(current().key); as res) {
43823
+ @if (importErrorCount(current().key) > 0) {
43824
+ <ui-alert variant="warning" [title]="t().importErrorsTitle(importErrorCount(current().key))" [attr.data-testid]="'import-errors-' + current().key">
43825
+ {{ t().importErrorsText(importResult(current().key) ?? 0, importErrorCount(current().key)) }}
43826
+ <ui-button variant="link" size="sm" data-testid="import-again" (click)="clearImport(current().key)"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('upload')" /></svg> {{ t().importAgain }}</ui-button>
43827
+ </ui-alert>
43828
+ } @else if (importResult(current().key); as res) {
43410
43829
  <ui-alert variant="success" [title]="importTitle(current().key)" [attr.data-testid]="'import-result-' + current().key">
43411
43830
  {{ imp.resultText }}
43412
43831
  <ui-button variant="link" size="sm" data-testid="import-more" (click)="clearImport(current().key)"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('upload')" /></svg> {{ t().importMore }}</ui-button>
@@ -43425,55 +43844,34 @@ i0.ɵɵngDeclareClassMetadata({
43425
43844
  @case ('integrations') {
43426
43845
  <div class="sw-provider-grid">
43427
43846
  @for (it of current().integrations ?? []; track it.key) {
43428
- <ui-detail-card class="sw-integration" [attr.data-testid]="'integration-' + it.key" [showHeader]="false" [fill]="true" [ariaLabel]="it.title">
43429
- <div class="sw-int-row">
43430
- <span class="sw-int-tile" [style.background]="it.color || '#64748b'" aria-hidden="true">@if (it.letter) { {{ it.letter }} } @else { <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" focusable="false"><path [attr.d]="iconD(it.icon ?? 'link')" /></svg> }</span>
43431
- <span class="sw-int-text">
43432
- <span class="sw-int-title">{{ it.title }}</span>
43433
- <span class="sw-int-detail">{{ detailFor(it) }}</span>
43434
- </span>
43435
- <ui-button variant="secondary" size="xs" [attr.data-testid]="'integration-pick-' + it.key" [ariaLabel]="(isConnected(it) ? t().reconnect : t().connect) + ' ' + it.title" (click)="connect(it)">{{ isConnected(it) ? t().reconnect : t().connect }}</ui-button>
43436
- </div>
43847
+ <ui-option-card class="sw-integration" [attr.data-testid]="'integration-' + it.key" [title]="it.title" [description]="detailFor(it)" [letter]="it.letter || ''"
43848
+ [icon]="it.letter ? '' : (it.icon ?? 'link')" [color]="it.color || '#64748b'" [actionLabel]="isConnected(it) ? t().reconnect : t().connect"
43849
+ [actionTestId]="'integration-pick-' + it.key" (action)="connect(it)">
43437
43850
  @if (areaCodeOpen() === it.key) {
43438
43851
  <div class="sw-area-code" [attr.data-testid]="'area-code-' + it.key">
43439
43852
  <ui-text-input [label]="areaCodeLabelFor(it)" [maxlength]="3" inputmode="numeric" [ngModel]="areaCode()" (ngModelChange)="areaCode.set($event ?? '')" [inputTestId]="'area-code-input-' + it.key" />
43440
43853
  <ui-button variant="primary" size="sm" [loading]="busy()" [disabled]="!validAreaCode()" (click)="submitAreaCode(it)"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('link')" /></svg> {{ t().connect }}</ui-button>
43441
43854
  </div>
43442
43855
  }
43443
- </ui-detail-card>
43856
+ </ui-option-card>
43444
43857
  }
43445
43858
  </div>
43446
43859
  }
43447
43860
  }
43448
43861
 
43862
+ @if (importBlocked()) { <p class="sw-hint sw-continue-hint" id="sw-continue-hint" data-testid="wizard-continue-hint">{{ t().importRequired }}</p> }
43863
+
43449
43864
  @if (error()) { <ui-alert variant="danger" data-testid="wizard-save-error">{{ error() }}</ui-alert> }
43450
43865
 
43451
- <div card-footer class="sw-step-actions">
43452
- @if (index() > 0) { <ui-button variant="secondary" size="sm" data-testid="wizard-back" [disabled]="busy()" (click)="back()"><svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-left')" /></svg> {{ t().back }}</ui-button> } @else { <span></span> }
43453
- <div class="sw-actions-right">
43454
- @if (current().skippable !== false) {
43455
- <ui-button variant="secondary" size="sm" data-testid="wizard-skip" [disabled]="busy()" (click)="skip()">{{ t().skip }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('chevron-right')" /></svg></ui-button>
43456
- }
43457
- @if (current().kind === 'custom') {
43458
- @if (!current().ownActions) {
43459
- <ui-button variant="primary" size="sm" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (click)="saveAndContinue()">
43460
- {{ current().saveLabel ?? t().saveAndContinue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg>
43461
- </ui-button>
43462
- }
43463
- } @else if (current().kind === 'integrations') {
43464
- <ui-button variant="primary" size="sm" data-testid="wizard-save" [loading]="busy()" (click)="saveAndContinue()">{{ t().saveAndContinue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg></ui-button>
43465
- } @else if (current().kind === 'import') {
43466
- <ui-button variant="primary" size="sm" data-testid="wizard-continue" (click)="continueFromImport()">{{ t().continue }} <svg class="sw-ico" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="iconD('arrow-right')" /></svg></ui-button>
43467
- }
43468
- </div>
43469
- </div>
43866
+ <div card-footer class="sw-step-actions"><ng-container [ngTemplateOutlet]="actions" /></div>
43470
43867
  </ui-detail-card>
43868
+ }
43471
43869
  </div>
43472
43870
  }
43473
43871
  </main>
43474
43872
  </div>
43475
43873
  `,
43476
- styles: [".sw-page{display:flex;min-height:100vh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.sw-sidebar{width:260px;min-width:260px;background:#faf9f7;border-right:1px solid #e5e2dc;display:flex;flex-direction:column;justify-content:space-between;padding:28px 20px}.sw-brand{display:flex;align-items:center;gap:10px;margin-bottom:28px}.sw-brand-text{font-size:1.125rem;font-weight:700;color:#1e293b}.sw-step-nav{display:block}.sw-sidebar-bottom{margin-top:24px}.sw-progress-text{display:block;margin-top:8px;font-size:.75rem;color:#94a3b8}.sw-content{flex:1;min-width:0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.sw-content-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 32px;border-bottom:1px solid #f1f5f9}.sw-step-title{font-size:1.25rem;font-weight:700;color:#111827;margin:0}.sw-step-content{max-width:780px;padding:16px 48px 60px}.sw-intro{margin-bottom:24px}.sw-step-number{font-size:1.25rem;font-weight:800;line-height:1}.sw-step-desc{font-size:.9375rem;color:#6b7280;line-height:1.5;margin:0 0 32px}.sw-hint{font-size:.8125rem;color:#94a3b8;margin:0 0 16px}.sw-import-tags{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px}.sw-tag{font-size:.6875rem;font-weight:700;letter-spacing:1px;color:#6b7280}.sw-provider-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:8px}@media(max-width:768px){.sw-provider-grid{grid-template-columns:1fr}}.sw-provider-grid .sw-integration{margin-bottom:0}.sw-int-row{display:flex;align-items:center;gap:12px}.sw-int-tile{width:36px;height:36px;border-radius:8px;color:#fff;font-size:1rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.sw-int-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.sw-int-title{font-size:.8125rem;font-weight:600;color:#1e293b;line-height:1.2}.sw-int-detail{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.sw-area-code{display:flex;align-items:flex-end;gap:12px;margin-top:12px;max-width:320px}.sw-area-code ui-text-input{flex:1}.sw-content ui-alert{display:block;margin-bottom:16px}.sw-card{display:block}.sw-header-action{margin-left:auto;min-width:0;max-width:100%}.sw-step-actions{display:flex;justify-content:space-between;align-items:center}.sw-ico{flex-shrink:0;vertical-align:-2px}.sw-actions-right{display:flex;align-items:center;gap:16px}.sw-done{text-align:center;display:flex;flex-direction:column;align-items:center;max-width:none}.sw-done .sw-step-desc{max-width:480px}.sw-summary{display:block;width:100%;max-width:480px;margin-bottom:24px;text-align:left}.sw-done-hint{font-size:.8125rem;color:#9ca3af;margin-bottom:24px}@media(max-width:768px){.sw-page{flex-direction:column}.sw-sidebar{width:100%;min-width:unset;padding:16px}.sw-brand{margin-bottom:12px}.sw-sidebar-bottom{display:none}.sw-step-content{padding:12px 20px 40px}}\n"]
43874
+ styles: [".sw-page{display:flex;min-height:100vh;min-height:100dvh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.sw-sidebar{width:260px;min-width:260px;background:#faf9f7;border-right:1px solid #e5e2dc;display:flex;flex-direction:column;justify-content:space-between;padding:28px 20px}.sw-brand{display:flex;align-items:center;gap:10px;margin-bottom:28px}.sw-brand-text{font-size:1.125rem;font-weight:700;color:#1e293b}.sw-step-nav{display:block}.sw-sidebar-bottom{margin-top:24px}.sw-progress-text{display:block;margin-top:8px;font-size:.75rem;color:#94a3b8}.sw-content{flex:1;min-width:0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.sw-content-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 32px;border-bottom:1px solid #f1f5f9}.sw-step-title{font-size:1.25rem;font-weight:700;color:#111827;margin:0}.sw-step-content{max-width:780px;padding:16px 48px 60px}.sw-intro{margin-bottom:24px}.sw-step-number{font-size:1.25rem;font-weight:800;line-height:1}.sw-step-desc{font-size:.9375rem;color:#6b7280;line-height:1.5;margin:0 0 32px}.sw-split-tabs{display:block;margin-bottom:16px}.sw-hint.sw-continue-hint{margin:14px 0 0}.sw-extra-status{font-size:.8125rem;color:#64748b;margin:12px 0 0}.sw-extra-status:empty{display:none}.sw-hint{font-size:.8125rem;line-height:1.5;color:#64748b;margin:0 0 16px}.sw-import-tags{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px}.sw-tag{font-size:.6875rem;font-weight:700;letter-spacing:1px;color:#6b7280}.sw-provider-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:8px}@media(max-width:768px){.sw-provider-grid{grid-template-columns:1fr}}.sw-provider-grid .sw-integration{margin-bottom:0}.sw-area-code{display:flex;align-items:flex-end;gap:12px;margin-top:12px;max-width:320px}.sw-area-code ui-text-input{flex:1}.sw-content ui-alert{display:block;margin-bottom:16px}.sw-card{display:block}.sw-header-action{margin-left:auto;min-width:0;max-width:100%}.sw-step-actions{display:flex;justify-content:space-between;align-items:center}.sw-ico{flex-shrink:0;vertical-align:-2px}.sw-actions-right{display:flex;align-items:center;gap:16px;margin-left:auto}.sw-done{text-align:center;display:flex;flex-direction:column;align-items:center;max-width:none}.sw-done .sw-step-desc{max-width:480px}.sw-summary{display:block;width:100%;max-width:480px;margin-bottom:24px;text-align:left}.sw-done-hint{font-size:.8125rem;color:#9ca3af;margin-bottom:24px}@media(max-width:768px){.sw-step-actions{flex-direction:column-reverse;align-items:stretch;gap:10px}.sw-actions-right{flex-direction:column-reverse;align-items:stretch;gap:10px;margin-left:0}.sw-page{flex-direction:column}.sw-sidebar{width:100%;min-width:unset;padding:16px}.sw-brand{margin-bottom:12px}.sw-sidebar-bottom{display:none}.sw-step-content{padding:12px 20px 40px}}\n"]
43477
43875
  }]
43478
43876
  }],
43479
43877
  ctorParameters: () => [],
@@ -43514,6 +43912,10 @@ i0.ɵɵngDeclareClassMetadata({
43514
43912
  type: i0.ContentChildren,
43515
43913
  args: [i0.forwardRef(() => SetupWizardStepHeaderDirective), { isSignal: true }]
43516
43914
  }],
43915
+ stepTitle: [{
43916
+ type: i0.ViewChild,
43917
+ args: ["stepTitle", { isSignal: true }]
43918
+ }],
43517
43919
  importers: [{
43518
43920
  type: i0.ViewChildren,
43519
43921
  args: ["importer", { isSignal: true }]
@@ -44158,17 +44560,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44158
44560
  if (!this.canWrite()) return;
44159
44561
  const list = this.blocks();
44160
44562
  if (index < 0 || index >= list.length) return;
44161
- if (list.length === 1) {
44162
- const ref = this.editorFor(list[0].id);
44163
- const alreadyEmpty = list[0].html === "<p></p>" && (!ref || ref.nativeElement.innerHTML === "<p></p>");
44164
- this.blocks.set([{
44165
- ...list[0],
44166
- html: "<p></p>"
44167
- }]);
44168
- if (ref) ref.nativeElement.innerHTML = "<p></p>";
44169
- if (!alreadyEmpty) this.bodyEdited.set(true);
44170
- return;
44171
- }
44563
+ if (list.length === 1) return;
44172
44564
  this.bodyEdited.set(true);
44173
44565
  this.initializedBlockIds.delete(list[index].id);
44174
44566
  const next = list.filter((_, i) => i !== index);
@@ -44996,9 +45388,11 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44996
45388
  <ui-button variant="ghost" size="xs" ariaLabel="Duplicate block" uiTooltip="Duplicate" (mousedown)="preventFocusLoss($event)" (click)="duplicateBlock(i)">
44997
45389
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
44998
45390
  </ui-button>
44999
- <ui-button variant="ghost" size="xs" ariaLabel="Delete block" uiTooltip="Delete block" (mousedown)="preventFocusLoss($event)" (click)="deleteBlock(i)">
45000
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>
45001
- </ui-button>
45391
+ @if (blocks().length > 1) {
45392
+ <ui-button variant="ghost" size="xs" ariaLabel="Delete block" uiTooltip="Delete block" (mousedown)="preventFocusLoss($event)" (click)="deleteBlock(i)">
45393
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>
45394
+ </ui-button>
45395
+ }
45002
45396
  </div>
45003
45397
  }
45004
45398
  </div>
@@ -45109,10 +45503,9 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
45109
45503
  @for (v of group.variables; track v.key) {
45110
45504
  <button type="button" class="variable-item" (mousedown)="saveSelection()" (click)="insertVariable(v)">
45111
45505
  <span class="var-tag">{{ '{{' + v.key + '}}' }}</span>
45112
- <span class="var-meta">
45113
- <span class="var-label">{{ v.label }}</span>
45114
- <span class="var-example">{{ v.example }}</span>
45115
- </span>
45506
+ <span class="var-example">Example: {{ v.example }}</span>
45507
+ <!-- A very short explanation of what the variable is: the host's description, else its label. -->
45508
+ <span class="var-description">{{ v.description || v.label }}</span>
45116
45509
  </button>
45117
45510
  }
45118
45511
  </div>
@@ -45206,7 +45599,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
45206
45599
 
45207
45600
  `,
45208
45601
  isInline: true,
45209
- styles: [":host{display:flex;flex-direction:column;flex:1;min-height:0}.required{color:#ef4444;font-weight:400}.editor-page{display:flex;flex-direction:column;flex:1;min-height:0;background:#f8fafc;overflow:hidden}.editor-actions{display:flex;justify-content:space-between;align-items:center;gap:8px 16px;flex-wrap:wrap;padding:0 0 12px;flex-shrink:0}.editor-heading{margin:0;font-size:1.25rem;font-weight:700;color:#1e293b;line-height:1.3;min-width:0}.save-wrap{display:inline-flex}.editor-actions-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;margin-left:auto}.readonly-note{margin:0;padding:8px 16px;font-size:.8125rem;color:#92400e;background:#fffbeb;border-bottom:1px solid #fde68a}.readonly-note.system-note{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.editor-body{display:grid;grid-template-columns:340px minmax(0,1fr) 300px;grid-template-rows:minmax(0,1fr);flex:1;min-height:0;overflow:hidden}.panel-left{background:#fff;border-right:1px solid #e2e8f0;padding:24px;overflow-y:auto}.panel-title{font-size:1.0625rem;font-weight:700;color:#1e293b;margin:0 0 20px}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-row-dates{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.assignments-section{border-top:1px solid #e2e8f0;padding-top:20px;margin-top:16px}.section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 6px}.section-desc{font-size:.8125rem;color:#64748b;line-height:1.5;margin:0 0 12px}.assignment-list{max-height:340px;overflow-y:auto;margin-top:12px;border:1px solid #e2e8f0;border-radius:8px}.assignment-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;border-bottom:1px solid #f1f5f9;transition:background .1s}.assignment-item:last-child{border-bottom:none}.assignment-item:hover{background:#f8fafc}.assignment-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.assignment-item.assignment-readonly{cursor:default}.assignment-item.assignment-readonly:hover{background:transparent}.assignment-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.assignment-text strong{font-size:.8125rem;color:#1e293b}.assignment-text span{font-size:.75rem;color:#64748b}.assignment-channels{display:flex;gap:4px;flex-shrink:0}.channel-badge{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;background:#f1f5f9;color:#94a3b8;transition:all .15s}.channel-badge.active{background:#3b82f6;color:#fff}.channel-badge.disabled{opacity:.4;cursor:not-allowed}.config-desc{font-size:.875rem;color:#64748b;line-height:1.5;margin:0}.config-divider{border:none;border-top:1px solid #e2e8f0;margin:20px 0}.config-section{display:flex;flex-direction:column;gap:12px}.config-section-label{font-size:.6875rem;font-weight:700;color:#3b82f6;text-transform:uppercase;letter-spacing:.04em}.config-field{display:flex;flex-direction:column;gap:6px}.config-field-mt{margin-top:16px}.config-label{font-size:.8125rem;font-weight:600;color:#1e293b}.config-readonly{padding:9px 12px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:.875rem;color:#1e293b}.config-hint{font-size:.75rem;color:#64748b}.test-save-note{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fef3c7;border:1px solid #fcd34d;border-radius:8px;font-size:.8125rem;color:#92400e;margin-top:12px}.test-save-note svg{flex-shrink:0}.panel-center{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.editor-tabs{display:flex;gap:2px;padding:12px 20px 0;background:#fff;border-bottom:1px solid #e2e8f0;overflow-x:auto;-webkit-overflow-scrolling:touch}.editor-tab{display:flex;align-items:center;gap:6px;padding:10px 16px;border:1px solid #e2e8f0;border-bottom:none;border-radius:8px 8px 0 0;background:#f8fafc;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;white-space:nowrap}.editor-tab:hover{background:#fff;color:#1e293b}.editor-tab.active{background:#eff6ff;color:#3b82f6;border-color:#93c5fd}.editor-tab:focus-visible,.right-tab:focus-visible,.block-group-header:focus-visible,.variable-item:focus-visible,.add-block-btn:focus-visible,.block-item:focus-visible,.video-lib-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.editor-toolbar{display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.toolbar-row-2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 20px;background:#fff;border-bottom:1px solid #e2e8f0}.toolbar-group{display:flex;align-items:center;gap:2px;padding-right:8px;border-right:1px solid #e2e8f0}.toolbar-group:last-child{border-right:none;padding-right:0}.toolbar-select{display:block;min-width:96px}.toolbar-label{font-size:.75rem;font-weight:600;color:#64748b;white-space:nowrap;margin-right:6px}.hidden-color-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none;border:none;padding:0}.color-indicator{display:flex;flex-direction:column;align-items:center;gap:2px;color:#475569}.color-bar{display:block;width:16px;height:3px;border-radius:2px;border:1px solid rgba(0,0,0,.1)}.link-dialog{background:#fff;border-bottom:1px solid #e2e8f0;padding:12px 20px}.link-dialog-inner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.link-dialog-title{font-size:.8125rem;font-weight:700;color:#1e293b;white-space:nowrap;padding-top:10px}.link-dialog-input{display:block;width:240px;max-width:100%}.link-dialog-actions{display:flex;gap:6px}.preview-frame{flex:1;display:flex;justify-content:center;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{max-width:600px;width:100%;box-sizing:border-box;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:32px;min-height:400px;font-size:.9375rem;line-height:1.6;color:#1e293b;overflow-wrap:anywhere}.preview-content p{margin:0 0 8px}.mobile-shell{width:375px;max-width:100%;box-sizing:border-box;min-height:600px;border:2px solid #1e293b;border-radius:24px;padding:40px 12px 24px;background:#fff;box-shadow:0 8px 32px #0000001f}.mobile-shell .preview-content{border:none;border-radius:0;padding:16px;max-width:100%}.blocks-canvas{flex:1 1 0;min-height:0;padding:16px 20px 24px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;background:#f1f5f9;display:flex;flex-direction:column}.block-wrapper{flex-shrink:0;position:relative;display:flex;align-items:flex-start;background:#fff;border:2px solid transparent;border-radius:8px;transition:border-color .15s,box-shadow .15s}.block-wrapper:hover,.block-wrapper.selected,.block-wrapper:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.block-wrapper:hover .block-drag-handle,.block-wrapper.selected .block-drag-handle,.block-wrapper:focus-within .block-drag-handle{opacity:1}.block-wrapper:hover .block-controls,.block-wrapper.selected .block-controls,.block-wrapper:focus-within .block-controls{opacity:1;pointer-events:all}.block-wrapper.dragging{opacity:.4}.block-drag-handle{flex-shrink:0;width:28px;display:flex;align-items:flex-start;justify-content:center;padding-top:14px;opacity:0;transition:opacity .15s;cursor:grab;color:#94a3b8}.block-drag-handle:active{cursor:grabbing}.block-content{flex:1;min-width:0;padding:12px 16px;outline:none;font-size:.9375rem;color:#1e293b;line-height:1.6;min-height:48px;overflow-wrap:anywhere}.block-content:empty:before{content:\"Click to edit...\";color:#94a3b8;font-style:italic;pointer-events:none}.block-content p{margin:0 0 8px}.block-content p:last-child{margin:0}.block-content h1,.block-content h2,.block-content h3{margin:8px 0 6px;color:#1e293b}.block-content a{color:#3b82f6}.block-content img{max-width:100%;border-radius:6px}.block-content ul,.block-content ol{padding-left:20px;margin:0 0 8px}.block-controls{position:absolute;top:6px;right:6px;display:flex;gap:2px;opacity:0;pointer-events:none;transition:opacity .15s;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:3px;box-shadow:0 2px 6px #00000014}@media(hover:none){.block-wrapper.selected .block-controls{opacity:1;pointer-events:all}}.drop-zone{flex-shrink:0;height:8px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:height .15s,background .15s;position:relative}.drop-zone-label{font-size:.75rem;font-weight:600;color:#3b82f6;opacity:0;transition:opacity .1s}.drop-zone.active{height:40px;background:#3b82f614;border:2px dashed #3b82f6}.drop-zone.active .drop-zone-label{opacity:1}.add-block-btn{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:44px;padding:12px;margin-top:8px;border:2px dashed #e2e8f0;border-radius:8px;background:none;font-size:.875rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;transition:border-color .15s,color .15s,background .15s}.add-block-btn:hover{border-color:#3b82f6;color:#3b82f6;background:#3b82f60a}.panel-right{background:#fff;border-left:1px solid #e2e8f0;display:flex;flex-direction:column;min-height:0;min-width:0}.right-tabs{display:flex;border-bottom:1px solid #e2e8f0}.right-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;min-height:44px;border:none;background:none;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;border-bottom:2px solid transparent}.right-tab:hover{color:#1e293b}.right-tab.active{color:#3b82f6;background:#eff6ff;border-bottom-color:#3b82f6}.right-panel-body{flex:1;padding:20px;overflow-y:auto}.right-section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 12px}.right-section-desc{font-size:.8125rem;color:#64748b;margin:0 0 16px;line-height:1.5}.right-section-hint{font-size:.8125rem;color:#64748b;margin:0 0 12px;line-height:1.5}.block-group{border-bottom:1px solid #f1f5f9}.block-group-header{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:12px 0;border:none;background:none;font-size:.875rem;font-weight:600;color:#1e293b;cursor:pointer;font-family:inherit;text-align:left}.block-group-header .chevron{transition:transform .2s;color:#94a3b8}.block-group-header .chevron.expanded{transform:rotate(90deg)}.block-group-header span:nth-of-type(1){flex:1}.block-count{font-size:.75rem;font-weight:600;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:10px;margin-left:auto}.block-list,.variable-list{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.block-item{display:flex;align-items:center;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:8px 12px 8px 28px;font-size:.8125rem;color:#64748b;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit;-webkit-user-select:none;user-select:none}.block-item:hover{background:#f8fafc;color:#1e293b}.block-item-drag{color:#cbd5e1;flex-shrink:0;cursor:grab}.variable-item{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-height:44px;padding:8px 12px 8px 28px;min-width:0;border:none;background:none;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit}.variable-item:hover{background:#f8fafc}.var-tag{max-width:100%;overflow-wrap:anywhere;font-size:.75rem;font-weight:600;color:#3b82f6;background:#3b82f614;padding:2px 6px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.var-meta{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px;min-width:0;max-width:100%}.var-label{font-size:.8125rem;color:#1e293b}.var-example{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.video-library-panel{padding:0}.video-library-panel .right-section-title,.video-library-panel .right-section-hint{padding:0 16px}.video-library-panel .right-section-title{padding-top:16px}.video-config-section{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9}.video-config-section:last-of-type{border-bottom:none}.video-lib-list{display:flex;flex-direction:column;gap:2px;padding:8px 8px 16px}.video-lib-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:8px;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;text-align:left;font-family:inherit;transition:background .15s,border-color .15s}.video-lib-item:hover{background:#f8fafc;border-color:#e2e8f0}.video-lib-item.selected{background:#eff6ff;border-color:#93c5fd}.vli-thumb{position:relative;flex-shrink:0;width:56px;height:40px;border-radius:6px;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);display:flex;align-items:center;justify-content:center}.vli-dur{position:absolute;bottom:2px;right:3px;font-size:.625rem;font-weight:600;color:#fff;background:#000000a6;padding:1px 4px;border-radius:3px}.vli-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.vli-title{font-size:.8125rem;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vli-cat{font-size:.75rem;color:#64748b}.vli-check{flex-shrink:0}.video-lib-loading{padding:8px}.video-lib-skeleton{display:flex;align-items:center;gap:10px;padding:8px;margin-bottom:4px}.vls-info{flex:1;display:flex;flex-direction:column;gap:6px}@media(max-width:1200px){.editor-body{grid-template-columns:280px minmax(0,1fr) 260px}}@media(max-width:900px){:host{flex:none}.editor-page{flex:none;min-height:100vh;min-height:100dvh;overflow:visible}.editor-body{display:flex;flex-direction:column;flex:none;overflow:visible}.panel-left{border-right:none;border-bottom:1px solid #e2e8f0;overflow:visible;padding:16px}.panel-center{overflow:visible;min-height:480px}.blocks-canvas{overflow:visible;min-height:320px}.panel-right{border-left:none;border-top:1px solid #e2e8f0}.right-panel-body{overflow:visible}.editor-toolbar,.toolbar-row-2,.link-dialog,.editor-tabs{padding-left:12px;padding-right:12px}.preview-frame{padding:12px}.preview-content{padding:16px}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"],
45602
+ styles: [":host{display:flex;flex-direction:column;flex:1;min-height:0}.required{color:#ef4444;font-weight:400}.editor-page{display:flex;flex-direction:column;flex:1;min-height:0;background:#f8fafc;overflow:hidden}.editor-actions{display:flex;justify-content:space-between;align-items:center;gap:8px 16px;flex-wrap:wrap;padding:0 0 12px;flex-shrink:0}.editor-heading{margin:0;font-size:1.25rem;font-weight:700;color:#1e293b;line-height:1.3;min-width:0}.save-wrap{display:inline-flex}.editor-actions-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;margin-left:auto}.readonly-note{margin:0;padding:8px 16px;font-size:.8125rem;color:#92400e;background:#fffbeb;border-bottom:1px solid #fde68a}.readonly-note.system-note{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.editor-body{display:grid;grid-template-columns:340px minmax(0,1fr) 300px;grid-template-rows:minmax(0,1fr);flex:1;min-height:0;overflow:hidden}.panel-left{background:#fff;border-right:1px solid #e2e8f0;padding:24px;overflow-y:auto}.panel-title{font-size:1.0625rem;font-weight:700;color:#1e293b;margin:0 0 20px}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-row-dates{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.assignments-section{border-top:1px solid #e2e8f0;padding-top:20px;margin-top:16px}.section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 6px}.section-desc{font-size:.8125rem;color:#64748b;line-height:1.5;margin:0 0 12px}.assignment-list{max-height:340px;overflow-y:auto;margin-top:12px;border:1px solid #e2e8f0;border-radius:8px}.assignment-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;border-bottom:1px solid #f1f5f9;transition:background .1s}.assignment-item:last-child{border-bottom:none}.assignment-item:hover{background:#f8fafc}.assignment-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.assignment-item.assignment-readonly{cursor:default}.assignment-item.assignment-readonly:hover{background:transparent}.assignment-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.assignment-text strong{font-size:.8125rem;color:#1e293b}.assignment-text span{font-size:.75rem;color:#64748b}.assignment-channels{display:flex;gap:4px;flex-shrink:0}.channel-badge{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;background:#f1f5f9;color:#94a3b8;transition:all .15s}.channel-badge.active{background:#3b82f6;color:#fff}.channel-badge.disabled{opacity:.4;cursor:not-allowed}.config-desc{font-size:.875rem;color:#64748b;line-height:1.5;margin:0}.config-divider{border:none;border-top:1px solid #e2e8f0;margin:20px 0}.config-section{display:flex;flex-direction:column;gap:12px}.config-section-label{font-size:.6875rem;font-weight:700;color:#3b82f6;text-transform:uppercase;letter-spacing:.04em}.config-field{display:flex;flex-direction:column;gap:6px}.config-field-mt{margin-top:16px}.config-label{font-size:.8125rem;font-weight:600;color:#1e293b}.config-readonly{padding:9px 12px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:.875rem;color:#1e293b}.config-hint{font-size:.75rem;color:#64748b}.test-save-note{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fef3c7;border:1px solid #fcd34d;border-radius:8px;font-size:.8125rem;color:#92400e;margin-top:12px}.test-save-note svg{flex-shrink:0}.panel-center{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.editor-tabs{display:flex;gap:2px;padding:12px 20px 0;background:#fff;border-bottom:1px solid #e2e8f0;overflow-x:auto;-webkit-overflow-scrolling:touch}.editor-tab{display:flex;align-items:center;gap:6px;padding:10px 16px;border:1px solid #e2e8f0;border-bottom:none;border-radius:8px 8px 0 0;background:#f8fafc;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;white-space:nowrap}.editor-tab:hover{background:#fff;color:#1e293b}.editor-tab.active{background:#eff6ff;color:#3b82f6;border-color:#93c5fd}.editor-tab:focus-visible,.right-tab:focus-visible,.block-group-header:focus-visible,.variable-item:focus-visible,.add-block-btn:focus-visible,.block-item:focus-visible,.video-lib-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.editor-toolbar{display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.toolbar-row-2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 20px;background:#fff;border-bottom:1px solid #e2e8f0}.toolbar-group{display:flex;align-items:center;gap:2px;padding-right:8px;border-right:1px solid #e2e8f0}.toolbar-group:last-child{border-right:none;padding-right:0}.toolbar-select{display:block;min-width:96px}.toolbar-label{font-size:.75rem;font-weight:600;color:#64748b;white-space:nowrap;margin-right:6px}.hidden-color-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none;border:none;padding:0}.color-indicator{display:flex;flex-direction:column;align-items:center;gap:2px;color:#475569}.color-bar{display:block;width:16px;height:3px;border-radius:2px;border:1px solid rgba(0,0,0,.1)}.link-dialog{background:#fff;border-bottom:1px solid #e2e8f0;padding:12px 20px}.link-dialog-inner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.link-dialog-title{font-size:.8125rem;font-weight:700;color:#1e293b;white-space:nowrap;padding-top:10px}.link-dialog-input{display:block;width:240px;max-width:100%}.link-dialog-actions{display:flex;gap:6px}.preview-frame{flex:1;display:flex;justify-content:center;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{max-width:600px;width:100%;box-sizing:border-box;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:32px;min-height:400px;font-size:.9375rem;line-height:1.6;color:#1e293b;overflow-wrap:anywhere}.preview-content p{margin:0 0 8px}.mobile-shell{width:375px;max-width:100%;box-sizing:border-box;min-height:600px;border:2px solid #1e293b;border-radius:24px;padding:40px 12px 24px;background:#fff;box-shadow:0 8px 32px #0000001f}.mobile-shell .preview-content{border:none;border-radius:0;padding:16px;max-width:100%}.blocks-canvas{flex:1 1 0;min-height:0;padding:16px 20px 24px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;background:#f1f5f9;display:flex;flex-direction:column}.block-wrapper{flex-shrink:0;position:relative;display:flex;align-items:flex-start;background:#fff;border:2px solid transparent;border-radius:8px;transition:border-color .15s,box-shadow .15s}.block-wrapper:hover,.block-wrapper.selected,.block-wrapper:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.block-wrapper:hover .block-drag-handle,.block-wrapper.selected .block-drag-handle,.block-wrapper:focus-within .block-drag-handle{opacity:1}.block-wrapper:hover .block-controls,.block-wrapper.selected .block-controls,.block-wrapper:focus-within .block-controls{opacity:1;pointer-events:all}.block-wrapper.dragging{opacity:.4}.block-drag-handle{flex-shrink:0;width:28px;display:flex;align-items:flex-start;justify-content:center;padding-top:14px;opacity:0;transition:opacity .15s;cursor:grab;color:#94a3b8}.block-drag-handle:active{cursor:grabbing}.block-content{flex:1;min-width:0;padding:12px 16px;outline:none;font-size:.9375rem;color:#1e293b;line-height:1.6;min-height:48px;overflow-wrap:anywhere}.block-content:empty:before{content:\"Click to edit...\";color:#94a3b8;font-style:italic;pointer-events:none}.block-content p{margin:0 0 8px}.block-content p:last-child{margin:0}.block-content h1,.block-content h2,.block-content h3{margin:8px 0 6px;color:#1e293b}.block-content a{color:#3b82f6}.block-content img{max-width:100%;border-radius:6px}.block-content ul,.block-content ol{padding-left:20px;margin:0 0 8px}.block-controls{position:absolute;top:6px;right:6px;display:flex;gap:2px;opacity:0;pointer-events:none;transition:opacity .15s;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:3px;box-shadow:0 2px 6px #00000014}@media(hover:none){.block-wrapper.selected .block-controls{opacity:1;pointer-events:all}}.drop-zone{flex-shrink:0;height:8px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:height .15s,background .15s;position:relative}.drop-zone-label{font-size:.75rem;font-weight:600;color:#3b82f6;opacity:0;transition:opacity .1s}.drop-zone.active{height:40px;background:#3b82f614;border:2px dashed #3b82f6}.drop-zone.active .drop-zone-label{opacity:1}.add-block-btn{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:44px;padding:12px;margin-top:8px;border:2px dashed #e2e8f0;border-radius:8px;background:none;font-size:.875rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;transition:border-color .15s,color .15s,background .15s}.add-block-btn:hover{border-color:#3b82f6;color:#3b82f6;background:#3b82f60a}.panel-right{background:#fff;border-left:1px solid #e2e8f0;display:flex;flex-direction:column;min-height:0;min-width:0}.right-tabs{display:flex;border-bottom:1px solid #e2e8f0}.right-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;min-height:44px;border:none;background:none;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;border-bottom:2px solid transparent}.right-tab:hover{color:#1e293b}.right-tab.active{color:#3b82f6;background:#eff6ff;border-bottom-color:#3b82f6}.right-panel-body{flex:1;padding:20px;overflow-y:auto}.right-section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 12px}.right-section-desc{font-size:.8125rem;color:#64748b;margin:0 0 16px;line-height:1.5}.right-section-hint{font-size:.8125rem;color:#64748b;margin:0 0 12px;line-height:1.5}.block-group{border-bottom:1px solid #f1f5f9}.block-group-header{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:12px 0;border:none;background:none;font-size:.875rem;font-weight:600;color:#1e293b;cursor:pointer;font-family:inherit;text-align:left}.block-group-header .chevron{transition:transform .2s;color:#94a3b8}.block-group-header .chevron.expanded{transform:rotate(90deg)}.block-group-header span:nth-of-type(1){flex:1}.block-count{font-size:.75rem;font-weight:600;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:10px;margin-left:auto}.block-list{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.variable-list{display:flex;flex-direction:column;padding-bottom:8px}.variable-item+.variable-item{border-top:1px solid #f1f5f9;border-radius:0}.block-item{display:flex;align-items:center;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:8px 12px 8px 28px;font-size:.8125rem;color:#64748b;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit;-webkit-user-select:none;user-select:none}.block-item:hover{background:#f8fafc;color:#1e293b}.block-item-drag{color:#cbd5e1;flex-shrink:0;cursor:grab}.variable-item{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-height:44px;padding:8px 0;min-width:0;width:100%;box-sizing:border-box;border:none;background:none;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit}.variable-item:hover{background:#f8fafc}.var-tag{max-width:100%;overflow-wrap:anywhere;font-size:.75rem;font-weight:600;color:#3b82f6;background:#3b82f614;padding:2px 6px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.var-example{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.var-description{font-size:.75rem;color:#64748b;line-height:1.4;overflow-wrap:anywhere}.video-library-panel{padding:0}.video-library-panel .right-section-title,.video-library-panel .right-section-hint{padding:0 16px}.video-library-panel .right-section-title{padding-top:16px}.video-config-section{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9}.video-config-section:last-of-type{border-bottom:none}.video-lib-list{display:flex;flex-direction:column;gap:2px;padding:8px 8px 16px}.video-lib-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:8px;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;text-align:left;font-family:inherit;transition:background .15s,border-color .15s}.video-lib-item:hover{background:#f8fafc;border-color:#e2e8f0}.video-lib-item.selected{background:#eff6ff;border-color:#93c5fd}.vli-thumb{position:relative;flex-shrink:0;width:56px;height:40px;border-radius:6px;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);display:flex;align-items:center;justify-content:center}.vli-dur{position:absolute;bottom:2px;right:3px;font-size:.625rem;font-weight:600;color:#fff;background:#000000a6;padding:1px 4px;border-radius:3px}.vli-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.vli-title{font-size:.8125rem;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vli-cat{font-size:.75rem;color:#64748b}.vli-check{flex-shrink:0}.video-lib-loading{padding:8px}.video-lib-skeleton{display:flex;align-items:center;gap:10px;padding:8px;margin-bottom:4px}.vls-info{flex:1;display:flex;flex-direction:column;gap:6px}@media(max-width:1200px){.editor-body{grid-template-columns:280px minmax(0,1fr) 260px}}@media(max-width:900px){:host{flex:none}.editor-page{flex:none;min-height:100vh;min-height:100dvh;overflow:visible}.editor-body{display:flex;flex-direction:column;flex:none;overflow:visible}.panel-left{border-right:none;border-bottom:1px solid #e2e8f0;overflow:visible;padding:16px}.panel-center{overflow:visible;min-height:480px}.blocks-canvas{overflow:visible;min-height:320px}.panel-right{border-left:none;border-top:1px solid #e2e8f0}.right-panel-body{overflow:visible}.editor-toolbar,.toolbar-row-2,.link-dialog,.editor-tabs{padding-left:12px;padding-right:12px}.preview-frame{padding:12px}.preview-content{padding:16px}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"],
45210
45603
  dependencies: [
45211
45604
  {
45212
45605
  kind: "ngmodule",
@@ -45778,9 +46171,11 @@ i0.ɵɵngDeclareClassMetadata({
45778
46171
  <ui-button variant="ghost" size="xs" ariaLabel="Duplicate block" uiTooltip="Duplicate" (mousedown)="preventFocusLoss($event)" (click)="duplicateBlock(i)">
45779
46172
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
45780
46173
  </ui-button>
45781
- <ui-button variant="ghost" size="xs" ariaLabel="Delete block" uiTooltip="Delete block" (mousedown)="preventFocusLoss($event)" (click)="deleteBlock(i)">
45782
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>
45783
- </ui-button>
46174
+ @if (blocks().length > 1) {
46175
+ <ui-button variant="ghost" size="xs" ariaLabel="Delete block" uiTooltip="Delete block" (mousedown)="preventFocusLoss($event)" (click)="deleteBlock(i)">
46176
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>
46177
+ </ui-button>
46178
+ }
45784
46179
  </div>
45785
46180
  }
45786
46181
  </div>
@@ -45891,10 +46286,9 @@ i0.ɵɵngDeclareClassMetadata({
45891
46286
  @for (v of group.variables; track v.key) {
45892
46287
  <button type="button" class="variable-item" (mousedown)="saveSelection()" (click)="insertVariable(v)">
45893
46288
  <span class="var-tag">{{ '{{' + v.key + '}}' }}</span>
45894
- <span class="var-meta">
45895
- <span class="var-label">{{ v.label }}</span>
45896
- <span class="var-example">{{ v.example }}</span>
45897
- </span>
46289
+ <span class="var-example">Example: {{ v.example }}</span>
46290
+ <!-- A very short explanation of what the variable is: the host's description, else its label. -->
46291
+ <span class="var-description">{{ v.description || v.label }}</span>
45898
46292
  </button>
45899
46293
  }
45900
46294
  </div>
@@ -45987,7 +46381,7 @@ i0.ɵɵngDeclareClassMetadata({
45987
46381
 
45988
46382
 
45989
46383
  `,
45990
- styles: [":host{display:flex;flex-direction:column;flex:1;min-height:0}.required{color:#ef4444;font-weight:400}.editor-page{display:flex;flex-direction:column;flex:1;min-height:0;background:#f8fafc;overflow:hidden}.editor-actions{display:flex;justify-content:space-between;align-items:center;gap:8px 16px;flex-wrap:wrap;padding:0 0 12px;flex-shrink:0}.editor-heading{margin:0;font-size:1.25rem;font-weight:700;color:#1e293b;line-height:1.3;min-width:0}.save-wrap{display:inline-flex}.editor-actions-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;margin-left:auto}.readonly-note{margin:0;padding:8px 16px;font-size:.8125rem;color:#92400e;background:#fffbeb;border-bottom:1px solid #fde68a}.readonly-note.system-note{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.editor-body{display:grid;grid-template-columns:340px minmax(0,1fr) 300px;grid-template-rows:minmax(0,1fr);flex:1;min-height:0;overflow:hidden}.panel-left{background:#fff;border-right:1px solid #e2e8f0;padding:24px;overflow-y:auto}.panel-title{font-size:1.0625rem;font-weight:700;color:#1e293b;margin:0 0 20px}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-row-dates{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.assignments-section{border-top:1px solid #e2e8f0;padding-top:20px;margin-top:16px}.section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 6px}.section-desc{font-size:.8125rem;color:#64748b;line-height:1.5;margin:0 0 12px}.assignment-list{max-height:340px;overflow-y:auto;margin-top:12px;border:1px solid #e2e8f0;border-radius:8px}.assignment-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;border-bottom:1px solid #f1f5f9;transition:background .1s}.assignment-item:last-child{border-bottom:none}.assignment-item:hover{background:#f8fafc}.assignment-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.assignment-item.assignment-readonly{cursor:default}.assignment-item.assignment-readonly:hover{background:transparent}.assignment-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.assignment-text strong{font-size:.8125rem;color:#1e293b}.assignment-text span{font-size:.75rem;color:#64748b}.assignment-channels{display:flex;gap:4px;flex-shrink:0}.channel-badge{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;background:#f1f5f9;color:#94a3b8;transition:all .15s}.channel-badge.active{background:#3b82f6;color:#fff}.channel-badge.disabled{opacity:.4;cursor:not-allowed}.config-desc{font-size:.875rem;color:#64748b;line-height:1.5;margin:0}.config-divider{border:none;border-top:1px solid #e2e8f0;margin:20px 0}.config-section{display:flex;flex-direction:column;gap:12px}.config-section-label{font-size:.6875rem;font-weight:700;color:#3b82f6;text-transform:uppercase;letter-spacing:.04em}.config-field{display:flex;flex-direction:column;gap:6px}.config-field-mt{margin-top:16px}.config-label{font-size:.8125rem;font-weight:600;color:#1e293b}.config-readonly{padding:9px 12px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:.875rem;color:#1e293b}.config-hint{font-size:.75rem;color:#64748b}.test-save-note{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fef3c7;border:1px solid #fcd34d;border-radius:8px;font-size:.8125rem;color:#92400e;margin-top:12px}.test-save-note svg{flex-shrink:0}.panel-center{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.editor-tabs{display:flex;gap:2px;padding:12px 20px 0;background:#fff;border-bottom:1px solid #e2e8f0;overflow-x:auto;-webkit-overflow-scrolling:touch}.editor-tab{display:flex;align-items:center;gap:6px;padding:10px 16px;border:1px solid #e2e8f0;border-bottom:none;border-radius:8px 8px 0 0;background:#f8fafc;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;white-space:nowrap}.editor-tab:hover{background:#fff;color:#1e293b}.editor-tab.active{background:#eff6ff;color:#3b82f6;border-color:#93c5fd}.editor-tab:focus-visible,.right-tab:focus-visible,.block-group-header:focus-visible,.variable-item:focus-visible,.add-block-btn:focus-visible,.block-item:focus-visible,.video-lib-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.editor-toolbar{display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.toolbar-row-2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 20px;background:#fff;border-bottom:1px solid #e2e8f0}.toolbar-group{display:flex;align-items:center;gap:2px;padding-right:8px;border-right:1px solid #e2e8f0}.toolbar-group:last-child{border-right:none;padding-right:0}.toolbar-select{display:block;min-width:96px}.toolbar-label{font-size:.75rem;font-weight:600;color:#64748b;white-space:nowrap;margin-right:6px}.hidden-color-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none;border:none;padding:0}.color-indicator{display:flex;flex-direction:column;align-items:center;gap:2px;color:#475569}.color-bar{display:block;width:16px;height:3px;border-radius:2px;border:1px solid rgba(0,0,0,.1)}.link-dialog{background:#fff;border-bottom:1px solid #e2e8f0;padding:12px 20px}.link-dialog-inner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.link-dialog-title{font-size:.8125rem;font-weight:700;color:#1e293b;white-space:nowrap;padding-top:10px}.link-dialog-input{display:block;width:240px;max-width:100%}.link-dialog-actions{display:flex;gap:6px}.preview-frame{flex:1;display:flex;justify-content:center;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{max-width:600px;width:100%;box-sizing:border-box;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:32px;min-height:400px;font-size:.9375rem;line-height:1.6;color:#1e293b;overflow-wrap:anywhere}.preview-content p{margin:0 0 8px}.mobile-shell{width:375px;max-width:100%;box-sizing:border-box;min-height:600px;border:2px solid #1e293b;border-radius:24px;padding:40px 12px 24px;background:#fff;box-shadow:0 8px 32px #0000001f}.mobile-shell .preview-content{border:none;border-radius:0;padding:16px;max-width:100%}.blocks-canvas{flex:1 1 0;min-height:0;padding:16px 20px 24px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;background:#f1f5f9;display:flex;flex-direction:column}.block-wrapper{flex-shrink:0;position:relative;display:flex;align-items:flex-start;background:#fff;border:2px solid transparent;border-radius:8px;transition:border-color .15s,box-shadow .15s}.block-wrapper:hover,.block-wrapper.selected,.block-wrapper:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.block-wrapper:hover .block-drag-handle,.block-wrapper.selected .block-drag-handle,.block-wrapper:focus-within .block-drag-handle{opacity:1}.block-wrapper:hover .block-controls,.block-wrapper.selected .block-controls,.block-wrapper:focus-within .block-controls{opacity:1;pointer-events:all}.block-wrapper.dragging{opacity:.4}.block-drag-handle{flex-shrink:0;width:28px;display:flex;align-items:flex-start;justify-content:center;padding-top:14px;opacity:0;transition:opacity .15s;cursor:grab;color:#94a3b8}.block-drag-handle:active{cursor:grabbing}.block-content{flex:1;min-width:0;padding:12px 16px;outline:none;font-size:.9375rem;color:#1e293b;line-height:1.6;min-height:48px;overflow-wrap:anywhere}.block-content:empty:before{content:\"Click to edit...\";color:#94a3b8;font-style:italic;pointer-events:none}.block-content p{margin:0 0 8px}.block-content p:last-child{margin:0}.block-content h1,.block-content h2,.block-content h3{margin:8px 0 6px;color:#1e293b}.block-content a{color:#3b82f6}.block-content img{max-width:100%;border-radius:6px}.block-content ul,.block-content ol{padding-left:20px;margin:0 0 8px}.block-controls{position:absolute;top:6px;right:6px;display:flex;gap:2px;opacity:0;pointer-events:none;transition:opacity .15s;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:3px;box-shadow:0 2px 6px #00000014}@media(hover:none){.block-wrapper.selected .block-controls{opacity:1;pointer-events:all}}.drop-zone{flex-shrink:0;height:8px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:height .15s,background .15s;position:relative}.drop-zone-label{font-size:.75rem;font-weight:600;color:#3b82f6;opacity:0;transition:opacity .1s}.drop-zone.active{height:40px;background:#3b82f614;border:2px dashed #3b82f6}.drop-zone.active .drop-zone-label{opacity:1}.add-block-btn{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:44px;padding:12px;margin-top:8px;border:2px dashed #e2e8f0;border-radius:8px;background:none;font-size:.875rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;transition:border-color .15s,color .15s,background .15s}.add-block-btn:hover{border-color:#3b82f6;color:#3b82f6;background:#3b82f60a}.panel-right{background:#fff;border-left:1px solid #e2e8f0;display:flex;flex-direction:column;min-height:0;min-width:0}.right-tabs{display:flex;border-bottom:1px solid #e2e8f0}.right-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;min-height:44px;border:none;background:none;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;border-bottom:2px solid transparent}.right-tab:hover{color:#1e293b}.right-tab.active{color:#3b82f6;background:#eff6ff;border-bottom-color:#3b82f6}.right-panel-body{flex:1;padding:20px;overflow-y:auto}.right-section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 12px}.right-section-desc{font-size:.8125rem;color:#64748b;margin:0 0 16px;line-height:1.5}.right-section-hint{font-size:.8125rem;color:#64748b;margin:0 0 12px;line-height:1.5}.block-group{border-bottom:1px solid #f1f5f9}.block-group-header{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:12px 0;border:none;background:none;font-size:.875rem;font-weight:600;color:#1e293b;cursor:pointer;font-family:inherit;text-align:left}.block-group-header .chevron{transition:transform .2s;color:#94a3b8}.block-group-header .chevron.expanded{transform:rotate(90deg)}.block-group-header span:nth-of-type(1){flex:1}.block-count{font-size:.75rem;font-weight:600;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:10px;margin-left:auto}.block-list,.variable-list{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.block-item{display:flex;align-items:center;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:8px 12px 8px 28px;font-size:.8125rem;color:#64748b;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit;-webkit-user-select:none;user-select:none}.block-item:hover{background:#f8fafc;color:#1e293b}.block-item-drag{color:#cbd5e1;flex-shrink:0;cursor:grab}.variable-item{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-height:44px;padding:8px 12px 8px 28px;min-width:0;border:none;background:none;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit}.variable-item:hover{background:#f8fafc}.var-tag{max-width:100%;overflow-wrap:anywhere;font-size:.75rem;font-weight:600;color:#3b82f6;background:#3b82f614;padding:2px 6px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.var-meta{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 8px;min-width:0;max-width:100%}.var-label{font-size:.8125rem;color:#1e293b}.var-example{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.video-library-panel{padding:0}.video-library-panel .right-section-title,.video-library-panel .right-section-hint{padding:0 16px}.video-library-panel .right-section-title{padding-top:16px}.video-config-section{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9}.video-config-section:last-of-type{border-bottom:none}.video-lib-list{display:flex;flex-direction:column;gap:2px;padding:8px 8px 16px}.video-lib-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:8px;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;text-align:left;font-family:inherit;transition:background .15s,border-color .15s}.video-lib-item:hover{background:#f8fafc;border-color:#e2e8f0}.video-lib-item.selected{background:#eff6ff;border-color:#93c5fd}.vli-thumb{position:relative;flex-shrink:0;width:56px;height:40px;border-radius:6px;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);display:flex;align-items:center;justify-content:center}.vli-dur{position:absolute;bottom:2px;right:3px;font-size:.625rem;font-weight:600;color:#fff;background:#000000a6;padding:1px 4px;border-radius:3px}.vli-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.vli-title{font-size:.8125rem;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vli-cat{font-size:.75rem;color:#64748b}.vli-check{flex-shrink:0}.video-lib-loading{padding:8px}.video-lib-skeleton{display:flex;align-items:center;gap:10px;padding:8px;margin-bottom:4px}.vls-info{flex:1;display:flex;flex-direction:column;gap:6px}@media(max-width:1200px){.editor-body{grid-template-columns:280px minmax(0,1fr) 260px}}@media(max-width:900px){:host{flex:none}.editor-page{flex:none;min-height:100vh;min-height:100dvh;overflow:visible}.editor-body{display:flex;flex-direction:column;flex:none;overflow:visible}.panel-left{border-right:none;border-bottom:1px solid #e2e8f0;overflow:visible;padding:16px}.panel-center{overflow:visible;min-height:480px}.blocks-canvas{overflow:visible;min-height:320px}.panel-right{border-left:none;border-top:1px solid #e2e8f0}.right-panel-body{overflow:visible}.editor-toolbar,.toolbar-row-2,.link-dialog,.editor-tabs{padding-left:12px;padding-right:12px}.preview-frame{padding:12px}.preview-content{padding:16px}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"]
46384
+ styles: [":host{display:flex;flex-direction:column;flex:1;min-height:0}.required{color:#ef4444;font-weight:400}.editor-page{display:flex;flex-direction:column;flex:1;min-height:0;background:#f8fafc;overflow:hidden}.editor-actions{display:flex;justify-content:space-between;align-items:center;gap:8px 16px;flex-wrap:wrap;padding:0 0 12px;flex-shrink:0}.editor-heading{margin:0;font-size:1.25rem;font-weight:700;color:#1e293b;line-height:1.3;min-width:0}.save-wrap{display:inline-flex}.editor-actions-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;margin-left:auto}.readonly-note{margin:0;padding:8px 16px;font-size:.8125rem;color:#92400e;background:#fffbeb;border-bottom:1px solid #fde68a}.readonly-note.system-note{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.editor-body{display:grid;grid-template-columns:340px minmax(0,1fr) 300px;grid-template-rows:minmax(0,1fr);flex:1;min-height:0;overflow:hidden}.panel-left{background:#fff;border-right:1px solid #e2e8f0;padding:24px;overflow-y:auto}.panel-title{font-size:1.0625rem;font-weight:700;color:#1e293b;margin:0 0 20px}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-row-dates{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.assignments-section{border-top:1px solid #e2e8f0;padding-top:20px;margin-top:16px}.section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 6px}.section-desc{font-size:.8125rem;color:#64748b;line-height:1.5;margin:0 0 12px}.assignment-list{max-height:340px;overflow-y:auto;margin-top:12px;border:1px solid #e2e8f0;border-radius:8px}.assignment-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;border-bottom:1px solid #f1f5f9;transition:background .1s}.assignment-item:last-child{border-bottom:none}.assignment-item:hover{background:#f8fafc}.assignment-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.assignment-item.assignment-readonly{cursor:default}.assignment-item.assignment-readonly:hover{background:transparent}.assignment-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.assignment-text strong{font-size:.8125rem;color:#1e293b}.assignment-text span{font-size:.75rem;color:#64748b}.assignment-channels{display:flex;gap:4px;flex-shrink:0}.channel-badge{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;background:#f1f5f9;color:#94a3b8;transition:all .15s}.channel-badge.active{background:#3b82f6;color:#fff}.channel-badge.disabled{opacity:.4;cursor:not-allowed}.config-desc{font-size:.875rem;color:#64748b;line-height:1.5;margin:0}.config-divider{border:none;border-top:1px solid #e2e8f0;margin:20px 0}.config-section{display:flex;flex-direction:column;gap:12px}.config-section-label{font-size:.6875rem;font-weight:700;color:#3b82f6;text-transform:uppercase;letter-spacing:.04em}.config-field{display:flex;flex-direction:column;gap:6px}.config-field-mt{margin-top:16px}.config-label{font-size:.8125rem;font-weight:600;color:#1e293b}.config-readonly{padding:9px 12px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:.875rem;color:#1e293b}.config-hint{font-size:.75rem;color:#64748b}.test-save-note{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fef3c7;border:1px solid #fcd34d;border-radius:8px;font-size:.8125rem;color:#92400e;margin-top:12px}.test-save-note svg{flex-shrink:0}.panel-center{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.editor-tabs{display:flex;gap:2px;padding:12px 20px 0;background:#fff;border-bottom:1px solid #e2e8f0;overflow-x:auto;-webkit-overflow-scrolling:touch}.editor-tab{display:flex;align-items:center;gap:6px;padding:10px 16px;border:1px solid #e2e8f0;border-bottom:none;border-radius:8px 8px 0 0;background:#f8fafc;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;white-space:nowrap}.editor-tab:hover{background:#fff;color:#1e293b}.editor-tab.active{background:#eff6ff;color:#3b82f6;border-color:#93c5fd}.editor-tab:focus-visible,.right-tab:focus-visible,.block-group-header:focus-visible,.variable-item:focus-visible,.add-block-btn:focus-visible,.block-item:focus-visible,.video-lib-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.editor-toolbar{display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.toolbar-row-2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 20px;background:#fff;border-bottom:1px solid #e2e8f0}.toolbar-group{display:flex;align-items:center;gap:2px;padding-right:8px;border-right:1px solid #e2e8f0}.toolbar-group:last-child{border-right:none;padding-right:0}.toolbar-select{display:block;min-width:96px}.toolbar-label{font-size:.75rem;font-weight:600;color:#64748b;white-space:nowrap;margin-right:6px}.hidden-color-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none;border:none;padding:0}.color-indicator{display:flex;flex-direction:column;align-items:center;gap:2px;color:#475569}.color-bar{display:block;width:16px;height:3px;border-radius:2px;border:1px solid rgba(0,0,0,.1)}.link-dialog{background:#fff;border-bottom:1px solid #e2e8f0;padding:12px 20px}.link-dialog-inner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.link-dialog-title{font-size:.8125rem;font-weight:700;color:#1e293b;white-space:nowrap;padding-top:10px}.link-dialog-input{display:block;width:240px;max-width:100%}.link-dialog-actions{display:flex;gap:6px}.preview-frame{flex:1;display:flex;justify-content:center;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{max-width:600px;width:100%;box-sizing:border-box;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:32px;min-height:400px;font-size:.9375rem;line-height:1.6;color:#1e293b;overflow-wrap:anywhere}.preview-content p{margin:0 0 8px}.mobile-shell{width:375px;max-width:100%;box-sizing:border-box;min-height:600px;border:2px solid #1e293b;border-radius:24px;padding:40px 12px 24px;background:#fff;box-shadow:0 8px 32px #0000001f}.mobile-shell .preview-content{border:none;border-radius:0;padding:16px;max-width:100%}.blocks-canvas{flex:1 1 0;min-height:0;padding:16px 20px 24px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;background:#f1f5f9;display:flex;flex-direction:column}.block-wrapper{flex-shrink:0;position:relative;display:flex;align-items:flex-start;background:#fff;border:2px solid transparent;border-radius:8px;transition:border-color .15s,box-shadow .15s}.block-wrapper:hover,.block-wrapper.selected,.block-wrapper:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.block-wrapper:hover .block-drag-handle,.block-wrapper.selected .block-drag-handle,.block-wrapper:focus-within .block-drag-handle{opacity:1}.block-wrapper:hover .block-controls,.block-wrapper.selected .block-controls,.block-wrapper:focus-within .block-controls{opacity:1;pointer-events:all}.block-wrapper.dragging{opacity:.4}.block-drag-handle{flex-shrink:0;width:28px;display:flex;align-items:flex-start;justify-content:center;padding-top:14px;opacity:0;transition:opacity .15s;cursor:grab;color:#94a3b8}.block-drag-handle:active{cursor:grabbing}.block-content{flex:1;min-width:0;padding:12px 16px;outline:none;font-size:.9375rem;color:#1e293b;line-height:1.6;min-height:48px;overflow-wrap:anywhere}.block-content:empty:before{content:\"Click to edit...\";color:#94a3b8;font-style:italic;pointer-events:none}.block-content p{margin:0 0 8px}.block-content p:last-child{margin:0}.block-content h1,.block-content h2,.block-content h3{margin:8px 0 6px;color:#1e293b}.block-content a{color:#3b82f6}.block-content img{max-width:100%;border-radius:6px}.block-content ul,.block-content ol{padding-left:20px;margin:0 0 8px}.block-controls{position:absolute;top:6px;right:6px;display:flex;gap:2px;opacity:0;pointer-events:none;transition:opacity .15s;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:3px;box-shadow:0 2px 6px #00000014}@media(hover:none){.block-wrapper.selected .block-controls{opacity:1;pointer-events:all}}.drop-zone{flex-shrink:0;height:8px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:height .15s,background .15s;position:relative}.drop-zone-label{font-size:.75rem;font-weight:600;color:#3b82f6;opacity:0;transition:opacity .1s}.drop-zone.active{height:40px;background:#3b82f614;border:2px dashed #3b82f6}.drop-zone.active .drop-zone-label{opacity:1}.add-block-btn{flex-shrink:0;display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:44px;padding:12px;margin-top:8px;border:2px dashed #e2e8f0;border-radius:8px;background:none;font-size:.875rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;transition:border-color .15s,color .15s,background .15s}.add-block-btn:hover{border-color:#3b82f6;color:#3b82f6;background:#3b82f60a}.panel-right{background:#fff;border-left:1px solid #e2e8f0;display:flex;flex-direction:column;min-height:0;min-width:0}.right-tabs{display:flex;border-bottom:1px solid #e2e8f0}.right-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;min-height:44px;border:none;background:none;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;border-bottom:2px solid transparent}.right-tab:hover{color:#1e293b}.right-tab.active{color:#3b82f6;background:#eff6ff;border-bottom-color:#3b82f6}.right-panel-body{flex:1;padding:20px;overflow-y:auto}.right-section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 12px}.right-section-desc{font-size:.8125rem;color:#64748b;margin:0 0 16px;line-height:1.5}.right-section-hint{font-size:.8125rem;color:#64748b;margin:0 0 12px;line-height:1.5}.block-group{border-bottom:1px solid #f1f5f9}.block-group-header{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:12px 0;border:none;background:none;font-size:.875rem;font-weight:600;color:#1e293b;cursor:pointer;font-family:inherit;text-align:left}.block-group-header .chevron{transition:transform .2s;color:#94a3b8}.block-group-header .chevron.expanded{transform:rotate(90deg)}.block-group-header span:nth-of-type(1){flex:1}.block-count{font-size:.75rem;font-weight:600;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:10px;margin-left:auto}.block-list{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.variable-list{display:flex;flex-direction:column;padding-bottom:8px}.variable-item+.variable-item{border-top:1px solid #f1f5f9;border-radius:0}.block-item{display:flex;align-items:center;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:8px 12px 8px 28px;font-size:.8125rem;color:#64748b;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit;-webkit-user-select:none;user-select:none}.block-item:hover{background:#f8fafc;color:#1e293b}.block-item-drag{color:#cbd5e1;flex-shrink:0;cursor:grab}.variable-item{display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-height:44px;padding:8px 0;min-width:0;width:100%;box-sizing:border-box;border:none;background:none;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit}.variable-item:hover{background:#f8fafc}.var-tag{max-width:100%;overflow-wrap:anywhere;font-size:.75rem;font-weight:600;color:#3b82f6;background:#3b82f614;padding:2px 6px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.var-example{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.var-description{font-size:.75rem;color:#64748b;line-height:1.4;overflow-wrap:anywhere}.video-library-panel{padding:0}.video-library-panel .right-section-title,.video-library-panel .right-section-hint{padding:0 16px}.video-library-panel .right-section-title{padding-top:16px}.video-config-section{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9}.video-config-section:last-of-type{border-bottom:none}.video-lib-list{display:flex;flex-direction:column;gap:2px;padding:8px 8px 16px}.video-lib-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:8px;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;text-align:left;font-family:inherit;transition:background .15s,border-color .15s}.video-lib-item:hover{background:#f8fafc;border-color:#e2e8f0}.video-lib-item.selected{background:#eff6ff;border-color:#93c5fd}.vli-thumb{position:relative;flex-shrink:0;width:56px;height:40px;border-radius:6px;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);display:flex;align-items:center;justify-content:center}.vli-dur{position:absolute;bottom:2px;right:3px;font-size:.625rem;font-weight:600;color:#fff;background:#000000a6;padding:1px 4px;border-radius:3px}.vli-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.vli-title{font-size:.8125rem;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vli-cat{font-size:.75rem;color:#64748b}.vli-check{flex-shrink:0}.video-lib-loading{padding:8px}.video-lib-skeleton{display:flex;align-items:center;gap:10px;padding:8px;margin-bottom:4px}.vls-info{flex:1;display:flex;flex-direction:column;gap:6px}@media(max-width:1200px){.editor-body{grid-template-columns:280px minmax(0,1fr) 260px}}@media(max-width:900px){:host{flex:none}.editor-page{flex:none;min-height:100vh;min-height:100dvh;overflow:visible}.editor-body{display:flex;flex-direction:column;flex:none;overflow:visible}.panel-left{border-right:none;border-bottom:1px solid #e2e8f0;overflow:visible;padding:16px}.panel-center{overflow:visible;min-height:480px}.blocks-canvas{overflow:visible;min-height:320px}.panel-right{border-left:none;border-top:1px solid #e2e8f0}.right-panel-body{overflow:visible}.editor-toolbar,.toolbar-row-2,.link-dialog,.editor-tabs{padding-left:12px;padding-right:12px}.preview-frame{padding:12px}.preview-content{padding:16px}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"]
45991
46385
  }]
45992
46386
  }],
45993
46387
  ctorParameters: () => [],
@@ -46234,6 +46628,6 @@ i0.ɵɵngDeclareClassMetadata({
46234
46628
  }]
46235
46629
  }
46236
46630
  });
46237
- export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, DEFAULT_PASSWORD_RULES, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EMAIL_BLOCK_DRAG_TYPE, EMAIL_TEMPLATE_MAX_BODY, EMAIL_TEMPLATE_MAX_TEXT, EMAIL_TEMPLATE_START_TEXT, EmailTemplateEditorComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IDX_BEHAVIOR_SIGNALS, INTEGRATION_CATALOG, INTEGRATION_FIELD_DEFS, INTEGRATION_GROUP_ORDER, INTEGRATION_OPTION_DEFS, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, ImportSourceGridComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, LiveRegionComponent, MAX_EMAIL_ADDRESS_LENGTH, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, SetupWizardStepHeaderDirective, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, blockHasContent, buildDefaultSchedule, buildVideoBlockHtml, builtInActionIcon, businessTimeOptions, createFieldReveal, decodeFilterValues, digitsOnly, downloadBlob, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, fileMatchesAccept, formatAddress, formatCategoryLabel, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isValidEmailAddress, isWebUrl, isoKey, issueToErrors, maxLengthIssue, normalizeHexColor, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, setupIntegrations, splitIntro };
46631
+ export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, DEFAULT_PASSWORD_RULES, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EMAIL_BLOCK_DRAG_TYPE, EMAIL_TEMPLATE_MAX_BODY, EMAIL_TEMPLATE_MAX_TEXT, EMAIL_TEMPLATE_START_TEXT, EmailTemplateEditorComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IDX_BEHAVIOR_SIGNALS, INTEGRATION_CATALOG, INTEGRATION_FIELD_DEFS, INTEGRATION_GROUP_ORDER, INTEGRATION_OPTION_DEFS, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, ImportSourceGridComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, LiveRegionComponent, MAX_EMAIL_ADDRESS_LENGTH, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, OptionCardComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, SetupWizardStepHeaderDirective, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, blockHasContent, buildDefaultSchedule, buildVideoBlockHtml, builtInActionIcon, businessTimeOptions, createFieldReveal, decodeFilterValues, digitsOnly, downloadBlob, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, fileMatchesAccept, formatAddress, formatCategoryLabel, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isValidEmailAddress, isWebUrl, isoKey, issueToErrors, maxLengthIssue, normalizeHexColor, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, setupIntegrations, splitIntro };
46238
46632
 
46239
46633
  //# sourceMappingURL=forgeroute-ui.mjs.map