@forgeroute/ui 0.4.38 → 0.4.39

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.
@@ -9287,43 +9287,58 @@ i0.ɵɵngDeclareClassMetadata({
9287
9287
  }]
9288
9288
  }
9289
9289
  });
9290
- function parseCsvLine(line) {
9291
- const cells = [];
9292
- let i = 0;
9293
- while (i <= line.length) {
9294
- if (i === line.length) {
9295
- cells.push("");
9296
- break;
9297
- }
9298
- if (line[i] === "\"") {
9299
- let cell = "";
9300
- i++;
9301
- while (i < line.length) if (line[i] === "\"") {
9302
- if (line[i + 1] === "\"") {
9303
- cell += "\"";
9304
- i += 2;
9305
- } else {
9306
- i++;
9307
- break;
9308
- }
9309
- } else cell += line[i++];
9310
- if (line[i] === ",") i++;
9311
- cells.push(cell);
9312
- if (i >= line.length) break;
9313
- } else {
9314
- const end = line.indexOf(",", i);
9315
- if (end === -1) {
9316
- cells.push(line.slice(i));
9317
- break;
9318
- }
9319
- cells.push(line.slice(i, end));
9320
- i = end + 1;
9321
- }
9290
+ function detectCsvDelimiter(text) {
9291
+ const counts = {
9292
+ ",": 0,
9293
+ ";": 0,
9294
+ " ": 0
9295
+ };
9296
+ let quoted = false;
9297
+ for (const ch of text) if (ch === "\"") quoted = !quoted;
9298
+ else if (!quoted) {
9299
+ if (ch === "\n" || ch === "\r") break;
9300
+ if (ch in counts) counts[ch]++;
9322
9301
  }
9323
- return cells;
9302
+ return [
9303
+ ",",
9304
+ ";",
9305
+ " "
9306
+ ].reduce((best, d) => counts[d] > counts[best] ? d : best, ",");
9324
9307
  }
9325
9308
  function parseCsv(text) {
9326
- return text.split(/\r?\n/).filter((l) => l.trim()).map(parseCsvLine);
9309
+ const delimiter = detectCsvDelimiter(text);
9310
+ const rows = [];
9311
+ let row = [];
9312
+ let cell = "";
9313
+ let quoted = false;
9314
+ const endCell = () => {
9315
+ row.push(cell);
9316
+ cell = "";
9317
+ };
9318
+ const endRow = () => {
9319
+ endCell();
9320
+ if (row.some((c) => c.trim() !== "")) rows.push(row);
9321
+ row = [];
9322
+ };
9323
+ const src = text.replace(/^\uFEFF/, "");
9324
+ for (let i = 0; i < src.length; i++) {
9325
+ const ch = src[i];
9326
+ if (quoted) {
9327
+ if (ch !== "\"") cell += ch;
9328
+ else if (src[i + 1] === "\"") {
9329
+ cell += "\"";
9330
+ i++;
9331
+ } else quoted = false;
9332
+ } else if (ch === "\"" && cell === "") quoted = true;
9333
+ else if (ch === delimiter) endCell();
9334
+ else if (ch === "\r") {
9335
+ if (src[i + 1] === "\n") i++;
9336
+ endRow();
9337
+ } else if (ch === "\n") endRow();
9338
+ else cell += ch;
9339
+ }
9340
+ if (cell !== "" || row.length) endRow();
9341
+ return rows;
9327
9342
  }
9328
9343
  function csvCell(cell) {
9329
9344
  if (typeof cell === "number") return String(cell);
@@ -9354,6 +9369,9 @@ var ImportExportComponent = class ImportExportComponent {
9354
9369
  this.apiBase = inject(FORGEROUTE_CONFIG, { optional: true })?.baseUrl ?? "/api";
9355
9370
  this.toast = inject(ToastService);
9356
9371
  this.cdr = inject(ChangeDetectorRef);
9372
+ this.destroyRef = inject(DestroyRef);
9373
+ this.importElapsed = 0;
9374
+ this.importTimer = null;
9357
9375
  this.exporting = false;
9358
9376
  this.importOpen = false;
9359
9377
  this.step = "upload";
@@ -9365,6 +9383,7 @@ var ImportExportComponent = class ImportExportComponent {
9365
9383
  this.mappingError = null;
9366
9384
  this.importing = false;
9367
9385
  this.importResult = null;
9386
+ this.destroyRef.onDestroy(() => this.stopImportTimer());
9368
9387
  effect(() => {
9369
9388
  const v = this._configInput();
9370
9389
  if (v !== null) this.config = v;
@@ -9461,10 +9480,18 @@ var ImportExportComponent = class ImportExportComponent {
9461
9480
  onFileChange(event) {
9462
9481
  const file = event.target.files?.[0];
9463
9482
  if (!file) return;
9483
+ this.readCsvFile(file);
9484
+ }
9485
+ readCsvFile(file, encoding) {
9464
9486
  const reader = new FileReader();
9465
9487
  reader.onload = (e) => {
9488
+ const raw = e.target.result;
9489
+ if (!encoding && raw.includes("�")) {
9490
+ this.readCsvFile(file, "windows-1252");
9491
+ return;
9492
+ }
9466
9493
  try {
9467
- const parsed = parseCsv(e.target.result.trim());
9494
+ const parsed = parseCsv(raw.trim());
9468
9495
  if (parsed.length < 1) {
9469
9496
  this.fileError = "The CSV file appears to be empty.";
9470
9497
  this.cdr.detectChanges();
@@ -9486,7 +9513,8 @@ var ImportExportComponent = class ImportExportComponent {
9486
9513
  this.cdr.detectChanges();
9487
9514
  }
9488
9515
  };
9489
- reader.readAsText(file);
9516
+ if (encoding) reader.readAsText(file, encoding);
9517
+ else reader.readAsText(file);
9490
9518
  }
9491
9519
  autoMap() {
9492
9520
  this.columnMapping = {};
@@ -9505,6 +9533,19 @@ var ImportExportComponent = class ImportExportComponent {
9505
9533
  }
9506
9534
  this.columnMapping[field.key] = match ?? "";
9507
9535
  }
9536
+ const tokens = (t) => t.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
9537
+ const containsRun = (haystack, needle) => needle.length > 0 && haystack.some((_, i) => needle.every((w, j) => haystack[i + j] === w));
9538
+ for (const field of this.config.importFields ?? []) {
9539
+ if (this.columnMapping[field.key] || !field.required) continue;
9540
+ const used = new Set(Object.values(this.columnMapping).filter(Boolean));
9541
+ const terms = [
9542
+ field.label,
9543
+ field.key.replace(/([a-z])([A-Z])/g, "$1 $2"),
9544
+ ...this.config.columnAliases?.[field.key] ?? []
9545
+ ].map(tokens).filter((t) => t.join("").length >= 3);
9546
+ const candidates = this.csvHeaders.filter((h) => !used.has(h) && terms.some((t) => containsRun(tokens(h), t)));
9547
+ if (new Set(candidates).size === 1) this.columnMapping[field.key] = candidates[0];
9548
+ }
9508
9549
  }
9509
9550
  get canSubmit() {
9510
9551
  return (this.config.importFields ?? []).filter((f) => f.required).every((f) => !!this.columnMapping[f.key]);
@@ -9558,8 +9599,20 @@ var ImportExportComponent = class ImportExportComponent {
9558
9599
  return record;
9559
9600
  });
9560
9601
  }
9602
+ stopImportTimer() {
9603
+ if (this.importTimer !== null) {
9604
+ clearInterval(this.importTimer);
9605
+ this.importTimer = null;
9606
+ }
9607
+ }
9561
9608
  submitImport() {
9562
9609
  this.importing = true;
9610
+ this.importElapsed = 0;
9611
+ this.stopImportTimer();
9612
+ this.importTimer = setInterval(() => {
9613
+ this.importElapsed++;
9614
+ this.cdr.detectChanges();
9615
+ }, 1e3);
9563
9616
  this.cdr.detectChanges();
9564
9617
  const records = this.csvRows.map((row) => {
9565
9618
  const record = {};
@@ -9573,6 +9626,7 @@ var ImportExportComponent = class ImportExportComponent {
9573
9626
  });
9574
9627
  this.http.post(`${this.apiBase}${this.config.importEndpoint ?? ""}`, { records }).subscribe({
9575
9628
  next: (result) => {
9629
+ this.stopImportTimer();
9576
9630
  this.importing = false;
9577
9631
  this.importResult = {
9578
9632
  imported: result.imported,
@@ -9584,6 +9638,7 @@ var ImportExportComponent = class ImportExportComponent {
9584
9638
  this.cdr.detectChanges();
9585
9639
  },
9586
9640
  error: () => {
9641
+ this.stopImportTimer();
9587
9642
  this.importing = false;
9588
9643
  this.toast.error("Import failed. Please check your data and try again.");
9589
9644
  this.cdr.detectChanges();
@@ -9771,6 +9826,12 @@ var ImportExportComponent = class ImportExportComponent {
9771
9826
  </tbody>
9772
9827
  </table>
9773
9828
  </div>
9829
+ @if (importing) {
9830
+ <div class="ie-progress" role="status" aria-live="polite" data-testid="import-progress">
9831
+ <div class="ie-progress-track" aria-hidden="true"><span class="ie-progress-bar"></span></div>
9832
+ <p class="ie-progress-text" data-testid="import-progress-text">Importing {{ csvRows.length.toLocaleString('en-US') }} record(s)… {{ importElapsed }}s. Keep this window open until it finishes.</p>
9833
+ </div>
9834
+ }
9774
9835
  </div>
9775
9836
  }
9776
9837
 
@@ -9799,7 +9860,7 @@ var ImportExportComponent = class ImportExportComponent {
9799
9860
  @if (importResult.errors.length > 0) {
9800
9861
  <div class="ie-errors-list">
9801
9862
  <p class="ie-errors-title">Errors:</p>
9802
- @for (err of importResult.errors; track err.row) {
9863
+ @for (err of importResult.errors; track $index) {
9803
9864
  <div class="ie-error-row">
9804
9865
  <span class="ie-error-row-num">Row {{ err.row }}</span>
9805
9866
  <span>{{ err.message }}</span>
@@ -9855,7 +9916,7 @@ var ImportExportComponent = class ImportExportComponent {
9855
9916
  }
9856
9917
  @if (step === 'preview') {
9857
9918
  <div modal-footer-right class="ie-footer-right">
9858
- <ui-button variant="secondary" size="sm" (click)="closeImport()">Cancel</ui-button>
9919
+ <ui-button variant="secondary" size="sm" [disabled]="importing" (click)="closeImport()">Cancel</ui-button>
9859
9920
  <ui-button variant="primary" size="sm" [loading]="importing" (click)="submitImport()">Import {{ csvRows.length }} Record(s)</ui-button>
9860
9921
  </div>
9861
9922
  }
@@ -9869,7 +9930,7 @@ var ImportExportComponent = class ImportExportComponent {
9869
9930
  </ui-modal>
9870
9931
  `,
9871
9932
  isInline: true,
9872
- styles: [".ie-actions{display:flex;gap:8px}.ie-steps{display:flex;align-items:center;margin-bottom:24px;gap:0;list-style:none;padding:0}.ie-step{display:flex;align-items:center;gap:6px;flex-shrink:0}.ie-step-num{width:24px;height:24px;border-radius:50%;background:#e2e8f0;color:#64748b;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-step-label{font-size:.8125rem;color:#94a3b8;font-weight:500}.ie-step.active .ie-step-num{background:#3b82f6;color:#fff}.ie-step.active .ie-step-label{color:#1e293b;font-weight:600}.ie-step.done .ie-step-num{background:#22c55e;color:#fff}.ie-step.done .ie-step-label{color:#64748b}.ie-step-divider{flex:1;height:1px;background:#e2e8f0;margin:0 8px;min-width:16px}.ie-source-step{display:flex;flex-direction:column;gap:16px}.ie-upload-area{display:flex;flex-direction:column;gap:12px}.ie-template-hint{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.875rem;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px}.ie-file-hidden{display:none}.ie-dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:40px 24px;border:2px dashed #cbd5e1;border-radius:10px;cursor:pointer;transition:border-color .18s ease,background .18s ease}.ie-dropzone:hover,.ie-dropzone:focus-within{border-color:#3b82f6;background:#f0f7ff}.ie-dropzone.has-error{border-color:#ef4444}.ie-dropzone-text{font-size:.9375rem;font-weight:600;color:#1e293b}.ie-dropzone-sub{font-size:.8125rem;color:#94a3b8}.ie-mapping{display:flex;flex-direction:column;gap:12px}.ie-mapping-hint{font-size:.875rem;color:#64748b;margin:0}.ie-mapping-success{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:.875rem;color:#15803d}.ie-mapping-success svg{flex-shrink:0;margin-top:1px;color:#16a34a}.ie-mapping-unmatched{display:flex;align-items:flex-start;gap:6px;font-size:.8125rem;color:#64748b;margin:0;padding-top:4px}.ie-mapping-unmatched svg{flex-shrink:0;margin-top:1px}.ie-mapping-unmatched em{font-style:normal;color:#475569}.ie-mapping-table{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.ie-mapping-header{display:grid;grid-template-columns:1fr 1fr 1fr;padding:8px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase}.ie-mapping-row{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:start;padding:8px 12px;border-bottom:1px solid #f1f5f9;gap:8px}.ie-mapping-row:last-child{border-bottom:none}.ie-mapping-row.ie-mapping-row--required-missing{background:#fff7ed}.ie-mapping-row.ie-mapping-row--required-missing .ie-field-label{color:#c2410c}.ie-match-icon{color:#16a34a;margin-right:4px;vertical-align:-1px}.ie-field-label{display:flex;align-items:center;font-size:.875rem;color:#1e293b;font-weight:500}.ie-required{color:#dc2626;margin-left:2px}.ie-sample{font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview{display:flex;flex-direction:column;gap:12px}.ie-preview-scroll{overflow-x:auto;border:1px solid #e2e8f0;border-radius:8px}.ie-preview-table{width:100%;border-collapse:collapse;font-size:.8125rem}.ie-preview-table th{background:#f8fafc;padding:8px 12px;text-align:left;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0;white-space:nowrap}.ie-preview-table td{padding:7px 12px;color:#1e293b;border-bottom:1px solid #f1f5f9;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview-table tr:last-child td{border-bottom:none}.ie-result{display:flex;flex-direction:column;gap:16px}.ie-result-summary{display:flex;flex-direction:column;gap:8px}.ie-result-stat{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:8px;font-size:.9375rem}.ie-result-stat.success{background:#f0fdf4;color:#15803d}.ie-result-stat.success svg{stroke:#22c55e}.ie-result-stat.error{background:#fef2f2;color:#b91c1c}.ie-result-stat.error svg{stroke:#ef4444}.ie-result-stat.warning{background:#fffbeb;color:#b45309}.ie-result-stat.warning svg{stroke:#f59e0b}.ie-errors-list{border:1px solid #fecaca;border-radius:8px;overflow:hidden}.ie-errors-title{font-size:.8125rem;font-weight:600;color:#b91c1c;padding:8px 12px;background:#fef2f2;margin:0;border-bottom:1px solid #fecaca}.ie-error-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fff1f2;font-size:.8125rem;color:#374151}.ie-error-row:last-child{border-bottom:none}.ie-error-row-num{font-weight:600;color:#b91c1c;flex-shrink:0}.ie-warnings-list{border:1px solid #fde68a;border-radius:8px;overflow:hidden}.ie-warnings-title{font-size:.8125rem;font-weight:600;color:#b45309;padding:8px 12px;background:#fffbeb;margin:0;border-bottom:1px solid #fde68a}.ie-warning-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fef3c7;font-size:.8125rem;color:#374151}.ie-warning-row:last-child{border-bottom:none}.ie-warning-row-num{font-weight:600;color:#b45309;flex-shrink:0}.ie-error{font-size:.875rem;color:#dc2626;margin:0}.ie-footer-right{display:flex;gap:8px;align-items:center}@media(max-width:600px){.ie-step-label{display:none}.ie-dropzone{padding:24px 16px}.ie-mapping-header{grid-template-columns:1fr 1fr}.ie-mapping-header span:last-child{display:none}.ie-mapping-row{grid-template-columns:1fr 1fr}.ie-mapping-row .ie-sample{display:none}}\n"],
9933
+ styles: [".ie-actions{display:flex;gap:8px}.ie-steps{display:flex;align-items:center;margin-bottom:24px;gap:0;list-style:none;padding:0}.ie-step{display:flex;align-items:center;gap:6px;flex-shrink:0}.ie-step-num{width:24px;height:24px;border-radius:50%;background:#e2e8f0;color:#64748b;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-step-label{font-size:.8125rem;color:#64748b;font-weight:500}.ie-step.active .ie-step-num{background:#3b82f6;color:#fff}.ie-step.active .ie-step-label{color:#1e293b;font-weight:600}.ie-step.done .ie-step-num{background:#22c55e;color:#fff}.ie-step.done .ie-step-label{color:#64748b}.ie-step-divider{flex:1;height:1px;background:#e2e8f0;margin:0 8px;min-width:16px}.ie-source-step{display:flex;flex-direction:column;gap:16px}.ie-upload-area{display:flex;flex-direction:column;gap:12px}.ie-template-hint{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.875rem;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px}.ie-file-hidden{display:none}.ie-dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:40px 24px;border:2px dashed #cbd5e1;border-radius:10px;cursor:pointer;transition:border-color .18s ease,background .18s ease}.ie-dropzone:hover,.ie-dropzone:focus-within{border-color:#3b82f6;background:#f0f7ff}.ie-dropzone.has-error{border-color:#ef4444}.ie-dropzone-text{font-size:.9375rem;font-weight:600;color:#1e293b}.ie-dropzone-sub{font-size:.8125rem;color:#64748b}.ie-mapping{display:flex;flex-direction:column;gap:12px}.ie-mapping-hint{font-size:.875rem;color:#64748b;margin:0}.ie-mapping-success{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:.875rem;color:#15803d}.ie-mapping-success svg{flex-shrink:0;margin-top:1px;color:#16a34a}.ie-mapping-unmatched{display:flex;align-items:flex-start;gap:6px;font-size:.8125rem;color:#64748b;margin:0;padding-top:4px}.ie-mapping-unmatched svg{flex-shrink:0;margin-top:1px}.ie-mapping-unmatched em{font-style:normal;color:#475569}.ie-mapping-table{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.ie-mapping-header{display:grid;grid-template-columns:1fr 1fr 1fr;padding:8px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase}.ie-mapping-row{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:start;padding:8px 12px;border-bottom:1px solid #f1f5f9;gap:8px}.ie-mapping-row:last-child{border-bottom:none}.ie-mapping-row.ie-mapping-row--required-missing{background:#fff7ed}.ie-mapping-row.ie-mapping-row--required-missing .ie-field-label{color:#c2410c}.ie-match-icon{color:#16a34a;margin-right:4px;vertical-align:-1px}.ie-field-label{display:flex;align-items:center;font-size:.875rem;color:#1e293b;font-weight:500}.ie-required{color:#dc2626;margin-left:2px}.ie-sample{font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview{display:flex;flex-direction:column;gap:12px}.ie-preview-scroll{overflow-x:auto;border:1px solid #e2e8f0;border-radius:8px}.ie-preview-table{width:100%;border-collapse:collapse;font-size:.8125rem}.ie-preview-table th{background:#f8fafc;padding:8px 12px;text-align:left;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0;white-space:nowrap}.ie-preview-table td{padding:7px 12px;color:#1e293b;border-bottom:1px solid #f1f5f9;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview-table tr:last-child td{border-bottom:none}.ie-result{display:flex;flex-direction:column;gap:16px}.ie-result-summary{display:flex;flex-direction:column;gap:8px}.ie-result-stat{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:8px;font-size:.9375rem}.ie-result-stat.success{background:#f0fdf4;color:#15803d}.ie-result-stat.success svg{stroke:#22c55e}.ie-result-stat.error{background:#fef2f2;color:#b91c1c}.ie-result-stat.error svg{stroke:#ef4444}.ie-result-stat.warning{background:#fffbeb;color:#b45309}.ie-result-stat.warning svg{stroke:#f59e0b}.ie-progress{margin-top:14px}.ie-progress-track{height:6px;border-radius:999px;background:#e2e8f0;overflow:hidden;position:relative}.ie-progress-bar{position:absolute;inset:0 auto 0 0;width:35%;border-radius:999px;background:#2563eb;animation:ie-progress-slide 1.2s ease-in-out infinite}.ie-progress-text{margin:8px 0 0;font-size:.8125rem;color:#475569}@keyframes ie-progress-slide{0%{left:-35%}to{left:100%}}@media(prefers-reduced-motion:reduce){.ie-progress-bar{animation:none;width:100%;opacity:.5}}.ie-errors-list{border:1px solid #fecaca;border-radius:8px;overflow:hidden}.ie-errors-title{font-size:.8125rem;font-weight:600;color:#b91c1c;padding:8px 12px;background:#fef2f2;margin:0;border-bottom:1px solid #fecaca}.ie-error-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fff1f2;font-size:.8125rem;color:#374151}.ie-error-row:last-child{border-bottom:none}.ie-error-row-num{font-weight:600;color:#b91c1c;flex-shrink:0}.ie-warnings-list{border:1px solid #fde68a;border-radius:8px;overflow:hidden}.ie-warnings-title{font-size:.8125rem;font-weight:600;color:#b45309;padding:8px 12px;background:#fffbeb;margin:0;border-bottom:1px solid #fde68a}.ie-warning-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fef3c7;font-size:.8125rem;color:#374151}.ie-warning-row:last-child{border-bottom:none}.ie-warning-row-num{font-weight:600;color:#b45309;flex-shrink:0}.ie-error{font-size:.875rem;color:#dc2626;margin:0}.ie-footer-right{display:flex;gap:8px;align-items:center}@media(max-width:600px){.ie-step-label{display:none}.ie-dropzone{padding:24px 16px}.ie-mapping-header{grid-template-columns:1fr 1fr}.ie-mapping-header span:last-child{display:none}.ie-mapping-row{grid-template-columns:1fr 1fr}.ie-mapping-row .ie-sample{display:none}}\n"],
9873
9934
  dependencies: [
9874
9935
  {
9875
9936
  kind: "ngmodule",
@@ -10128,6 +10189,12 @@ i0.ɵɵngDeclareClassMetadata({
10128
10189
  </tbody>
10129
10190
  </table>
10130
10191
  </div>
10192
+ @if (importing) {
10193
+ <div class="ie-progress" role="status" aria-live="polite" data-testid="import-progress">
10194
+ <div class="ie-progress-track" aria-hidden="true"><span class="ie-progress-bar"></span></div>
10195
+ <p class="ie-progress-text" data-testid="import-progress-text">Importing {{ csvRows.length.toLocaleString('en-US') }} record(s)… {{ importElapsed }}s. Keep this window open until it finishes.</p>
10196
+ </div>
10197
+ }
10131
10198
  </div>
10132
10199
  }
10133
10200
 
@@ -10156,7 +10223,7 @@ i0.ɵɵngDeclareClassMetadata({
10156
10223
  @if (importResult.errors.length > 0) {
10157
10224
  <div class="ie-errors-list">
10158
10225
  <p class="ie-errors-title">Errors:</p>
10159
- @for (err of importResult.errors; track err.row) {
10226
+ @for (err of importResult.errors; track $index) {
10160
10227
  <div class="ie-error-row">
10161
10228
  <span class="ie-error-row-num">Row {{ err.row }}</span>
10162
10229
  <span>{{ err.message }}</span>
@@ -10212,7 +10279,7 @@ i0.ɵɵngDeclareClassMetadata({
10212
10279
  }
10213
10280
  @if (step === 'preview') {
10214
10281
  <div modal-footer-right class="ie-footer-right">
10215
- <ui-button variant="secondary" size="sm" (click)="closeImport()">Cancel</ui-button>
10282
+ <ui-button variant="secondary" size="sm" [disabled]="importing" (click)="closeImport()">Cancel</ui-button>
10216
10283
  <ui-button variant="primary" size="sm" [loading]="importing" (click)="submitImport()">Import {{ csvRows.length }} Record(s)</ui-button>
10217
10284
  </div>
10218
10285
  }
@@ -10225,7 +10292,7 @@ i0.ɵɵngDeclareClassMetadata({
10225
10292
 
10226
10293
  </ui-modal>
10227
10294
  `,
10228
- styles: [".ie-actions{display:flex;gap:8px}.ie-steps{display:flex;align-items:center;margin-bottom:24px;gap:0;list-style:none;padding:0}.ie-step{display:flex;align-items:center;gap:6px;flex-shrink:0}.ie-step-num{width:24px;height:24px;border-radius:50%;background:#e2e8f0;color:#64748b;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-step-label{font-size:.8125rem;color:#94a3b8;font-weight:500}.ie-step.active .ie-step-num{background:#3b82f6;color:#fff}.ie-step.active .ie-step-label{color:#1e293b;font-weight:600}.ie-step.done .ie-step-num{background:#22c55e;color:#fff}.ie-step.done .ie-step-label{color:#64748b}.ie-step-divider{flex:1;height:1px;background:#e2e8f0;margin:0 8px;min-width:16px}.ie-source-step{display:flex;flex-direction:column;gap:16px}.ie-upload-area{display:flex;flex-direction:column;gap:12px}.ie-template-hint{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.875rem;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px}.ie-file-hidden{display:none}.ie-dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:40px 24px;border:2px dashed #cbd5e1;border-radius:10px;cursor:pointer;transition:border-color .18s ease,background .18s ease}.ie-dropzone:hover,.ie-dropzone:focus-within{border-color:#3b82f6;background:#f0f7ff}.ie-dropzone.has-error{border-color:#ef4444}.ie-dropzone-text{font-size:.9375rem;font-weight:600;color:#1e293b}.ie-dropzone-sub{font-size:.8125rem;color:#94a3b8}.ie-mapping{display:flex;flex-direction:column;gap:12px}.ie-mapping-hint{font-size:.875rem;color:#64748b;margin:0}.ie-mapping-success{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:.875rem;color:#15803d}.ie-mapping-success svg{flex-shrink:0;margin-top:1px;color:#16a34a}.ie-mapping-unmatched{display:flex;align-items:flex-start;gap:6px;font-size:.8125rem;color:#64748b;margin:0;padding-top:4px}.ie-mapping-unmatched svg{flex-shrink:0;margin-top:1px}.ie-mapping-unmatched em{font-style:normal;color:#475569}.ie-mapping-table{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.ie-mapping-header{display:grid;grid-template-columns:1fr 1fr 1fr;padding:8px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase}.ie-mapping-row{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:start;padding:8px 12px;border-bottom:1px solid #f1f5f9;gap:8px}.ie-mapping-row:last-child{border-bottom:none}.ie-mapping-row.ie-mapping-row--required-missing{background:#fff7ed}.ie-mapping-row.ie-mapping-row--required-missing .ie-field-label{color:#c2410c}.ie-match-icon{color:#16a34a;margin-right:4px;vertical-align:-1px}.ie-field-label{display:flex;align-items:center;font-size:.875rem;color:#1e293b;font-weight:500}.ie-required{color:#dc2626;margin-left:2px}.ie-sample{font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview{display:flex;flex-direction:column;gap:12px}.ie-preview-scroll{overflow-x:auto;border:1px solid #e2e8f0;border-radius:8px}.ie-preview-table{width:100%;border-collapse:collapse;font-size:.8125rem}.ie-preview-table th{background:#f8fafc;padding:8px 12px;text-align:left;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0;white-space:nowrap}.ie-preview-table td{padding:7px 12px;color:#1e293b;border-bottom:1px solid #f1f5f9;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview-table tr:last-child td{border-bottom:none}.ie-result{display:flex;flex-direction:column;gap:16px}.ie-result-summary{display:flex;flex-direction:column;gap:8px}.ie-result-stat{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:8px;font-size:.9375rem}.ie-result-stat.success{background:#f0fdf4;color:#15803d}.ie-result-stat.success svg{stroke:#22c55e}.ie-result-stat.error{background:#fef2f2;color:#b91c1c}.ie-result-stat.error svg{stroke:#ef4444}.ie-result-stat.warning{background:#fffbeb;color:#b45309}.ie-result-stat.warning svg{stroke:#f59e0b}.ie-errors-list{border:1px solid #fecaca;border-radius:8px;overflow:hidden}.ie-errors-title{font-size:.8125rem;font-weight:600;color:#b91c1c;padding:8px 12px;background:#fef2f2;margin:0;border-bottom:1px solid #fecaca}.ie-error-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fff1f2;font-size:.8125rem;color:#374151}.ie-error-row:last-child{border-bottom:none}.ie-error-row-num{font-weight:600;color:#b91c1c;flex-shrink:0}.ie-warnings-list{border:1px solid #fde68a;border-radius:8px;overflow:hidden}.ie-warnings-title{font-size:.8125rem;font-weight:600;color:#b45309;padding:8px 12px;background:#fffbeb;margin:0;border-bottom:1px solid #fde68a}.ie-warning-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fef3c7;font-size:.8125rem;color:#374151}.ie-warning-row:last-child{border-bottom:none}.ie-warning-row-num{font-weight:600;color:#b45309;flex-shrink:0}.ie-error{font-size:.875rem;color:#dc2626;margin:0}.ie-footer-right{display:flex;gap:8px;align-items:center}@media(max-width:600px){.ie-step-label{display:none}.ie-dropzone{padding:24px 16px}.ie-mapping-header{grid-template-columns:1fr 1fr}.ie-mapping-header span:last-child{display:none}.ie-mapping-row{grid-template-columns:1fr 1fr}.ie-mapping-row .ie-sample{display:none}}\n"]
10295
+ styles: [".ie-actions{display:flex;gap:8px}.ie-steps{display:flex;align-items:center;margin-bottom:24px;gap:0;list-style:none;padding:0}.ie-step{display:flex;align-items:center;gap:6px;flex-shrink:0}.ie-step-num{width:24px;height:24px;border-radius:50%;background:#e2e8f0;color:#64748b;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.ie-step-label{font-size:.8125rem;color:#64748b;font-weight:500}.ie-step.active .ie-step-num{background:#3b82f6;color:#fff}.ie-step.active .ie-step-label{color:#1e293b;font-weight:600}.ie-step.done .ie-step-num{background:#22c55e;color:#fff}.ie-step.done .ie-step-label{color:#64748b}.ie-step-divider{flex:1;height:1px;background:#e2e8f0;margin:0 8px;min-width:16px}.ie-source-step{display:flex;flex-direction:column;gap:16px}.ie-upload-area{display:flex;flex-direction:column;gap:12px}.ie-template-hint{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.875rem;color:#64748b;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px}.ie-file-hidden{display:none}.ie-dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:40px 24px;border:2px dashed #cbd5e1;border-radius:10px;cursor:pointer;transition:border-color .18s ease,background .18s ease}.ie-dropzone:hover,.ie-dropzone:focus-within{border-color:#3b82f6;background:#f0f7ff}.ie-dropzone.has-error{border-color:#ef4444}.ie-dropzone-text{font-size:.9375rem;font-weight:600;color:#1e293b}.ie-dropzone-sub{font-size:.8125rem;color:#64748b}.ie-mapping{display:flex;flex-direction:column;gap:12px}.ie-mapping-hint{font-size:.875rem;color:#64748b;margin:0}.ie-mapping-success{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;font-size:.875rem;color:#15803d}.ie-mapping-success svg{flex-shrink:0;margin-top:1px;color:#16a34a}.ie-mapping-unmatched{display:flex;align-items:flex-start;gap:6px;font-size:.8125rem;color:#64748b;margin:0;padding-top:4px}.ie-mapping-unmatched svg{flex-shrink:0;margin-top:1px}.ie-mapping-unmatched em{font-style:normal;color:#475569}.ie-mapping-table{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden}.ie-mapping-header{display:grid;grid-template-columns:1fr 1fr 1fr;padding:8px 12px;background:#f8fafc;border-bottom:1px solid #e2e8f0;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase}.ie-mapping-row{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:start;padding:8px 12px;border-bottom:1px solid #f1f5f9;gap:8px}.ie-mapping-row:last-child{border-bottom:none}.ie-mapping-row.ie-mapping-row--required-missing{background:#fff7ed}.ie-mapping-row.ie-mapping-row--required-missing .ie-field-label{color:#c2410c}.ie-match-icon{color:#16a34a;margin-right:4px;vertical-align:-1px}.ie-field-label{display:flex;align-items:center;font-size:.875rem;color:#1e293b;font-weight:500}.ie-required{color:#dc2626;margin-left:2px}.ie-sample{font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview{display:flex;flex-direction:column;gap:12px}.ie-preview-scroll{overflow-x:auto;border:1px solid #e2e8f0;border-radius:8px}.ie-preview-table{width:100%;border-collapse:collapse;font-size:.8125rem}.ie-preview-table th{background:#f8fafc;padding:8px 12px;text-align:left;font-size:.75rem;font-weight:600;color:#64748b;text-transform:uppercase;border-bottom:1px solid #e2e8f0;white-space:nowrap}.ie-preview-table td{padding:7px 12px;color:#1e293b;border-bottom:1px solid #f1f5f9;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ie-preview-table tr:last-child td{border-bottom:none}.ie-result{display:flex;flex-direction:column;gap:16px}.ie-result-summary{display:flex;flex-direction:column;gap:8px}.ie-result-stat{display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:8px;font-size:.9375rem}.ie-result-stat.success{background:#f0fdf4;color:#15803d}.ie-result-stat.success svg{stroke:#22c55e}.ie-result-stat.error{background:#fef2f2;color:#b91c1c}.ie-result-stat.error svg{stroke:#ef4444}.ie-result-stat.warning{background:#fffbeb;color:#b45309}.ie-result-stat.warning svg{stroke:#f59e0b}.ie-progress{margin-top:14px}.ie-progress-track{height:6px;border-radius:999px;background:#e2e8f0;overflow:hidden;position:relative}.ie-progress-bar{position:absolute;inset:0 auto 0 0;width:35%;border-radius:999px;background:#2563eb;animation:ie-progress-slide 1.2s ease-in-out infinite}.ie-progress-text{margin:8px 0 0;font-size:.8125rem;color:#475569}@keyframes ie-progress-slide{0%{left:-35%}to{left:100%}}@media(prefers-reduced-motion:reduce){.ie-progress-bar{animation:none;width:100%;opacity:.5}}.ie-errors-list{border:1px solid #fecaca;border-radius:8px;overflow:hidden}.ie-errors-title{font-size:.8125rem;font-weight:600;color:#b91c1c;padding:8px 12px;background:#fef2f2;margin:0;border-bottom:1px solid #fecaca}.ie-error-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fff1f2;font-size:.8125rem;color:#374151}.ie-error-row:last-child{border-bottom:none}.ie-error-row-num{font-weight:600;color:#b91c1c;flex-shrink:0}.ie-warnings-list{border:1px solid #fde68a;border-radius:8px;overflow:hidden}.ie-warnings-title{font-size:.8125rem;font-weight:600;color:#b45309;padding:8px 12px;background:#fffbeb;margin:0;border-bottom:1px solid #fde68a}.ie-warning-row{display:flex;gap:12px;padding:7px 12px;border-bottom:1px solid #fef3c7;font-size:.8125rem;color:#374151}.ie-warning-row:last-child{border-bottom:none}.ie-warning-row-num{font-weight:600;color:#b45309;flex-shrink:0}.ie-error{font-size:.875rem;color:#dc2626;margin:0}.ie-footer-right{display:flex;gap:8px;align-items:center}@media(max-width:600px){.ie-step-label{display:none}.ie-dropzone{padding:24px 16px}.ie-mapping-header{grid-template-columns:1fr 1fr}.ie-mapping-header span:last-child{display:none}.ie-mapping-row{grid-template-columns:1fr 1fr}.ie-mapping-row .ie-sample{display:none}}\n"]
10229
10296
  }]
10230
10297
  }],
10231
10298
  ctorParameters: () => [],
@@ -19071,7 +19138,7 @@ var ToggleBadgeComponent = class ToggleBadgeComponent {
19071
19138
  </span>
19072
19139
  `,
19073
19140
  isInline: true,
19074
- styles: [":host{display:inline-flex}.tb{display:inline-flex;align-items:center;border-radius:999px;border:1px solid #e2e8f0;background:#fff;color:#64748b;transition:all .15s ease}.tb:hover{background:#f8fafc;border-color:#94a3b8}.tb.active{background:#1e293b;color:#fff;border-color:#1e293b}.toggle-badge{display:inline-flex;align-items:center;gap:5px;padding:var(--ui-toggle-badge-pad-y, 3px) var(--ui-toggle-badge-pad-x, 10px);border-radius:999px;border:none;background:transparent;font-size:.75rem;font-weight:500;color:inherit;cursor:pointer;font-family:inherit;line-height:1}.toggle-badge:focus-visible,.tb-action:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.tb-has-actions .toggle-badge{padding-right:6px}.tb-actions{display:inline-flex;align-items:center;gap:1px;padding-right:4px}.tb-divider{width:1px;height:12px;background:currentColor;opacity:.25;margin-right:3px}.tb-action{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;border-radius:50%;background:transparent;color:inherit;cursor:pointer;opacity:.75;font-family:inherit;transition:background .15s ease,opacity .15s ease}.tb-action:hover:not(:disabled){opacity:1;background:#64748b2e}.tb.active .tb-action:hover:not(:disabled){background:#fff3}.tb-action:disabled{opacity:.35;cursor:not-allowed}@media(pointer:coarse){.tb-action{position:relative}.tb-action:after{content:\"\";position:absolute;inset:-12px}}\n"],
19141
+ styles: [":host{display:inline-flex}.tb{display:inline-flex;align-items:center;border-radius:999px;border:1px solid #e2e8f0;background:#fff;color:#64748b;transition:all .15s ease}.tb:hover{background:#f8fafc;border-color:#94a3b8}.tb.active{background:#1e293b;color:#fff;border-color:#1e293b}.toggle-badge{display:inline-flex;align-items:center;gap:5px;padding:var(--ui-toggle-badge-pad-y, 3px) var(--ui-toggle-badge-pad-x, 10px);border-radius:999px;border:none;background:transparent;font-size:.75rem;font-weight:500;color:inherit;cursor:pointer;font-family:inherit;line-height:1}.toggle-badge:focus-visible,.tb-action:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.tb-has-actions .toggle-badge{padding-right:6px}@media(pointer:coarse){.toggle-badge{position:relative}.toggle-badge:after{content:\"\";position:absolute;inset:-12px -4px}}.tb-actions{display:inline-flex;align-items:center;gap:1px;padding-right:4px}.tb-divider{width:1px;height:12px;background:currentColor;opacity:.25;margin-right:3px}.tb-action{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;border-radius:50%;background:transparent;color:inherit;cursor:pointer;opacity:.75;font-family:inherit;transition:background .15s ease,opacity .15s ease}.tb-action:hover:not(:disabled){opacity:1;background:#64748b2e}.tb.active .tb-action:hover:not(:disabled){background:#fff3}.tb-action:disabled{opacity:.35;cursor:not-allowed}@media(pointer:coarse){.tb-action{position:relative}.tb-action:after{content:\"\";position:absolute;inset:-12px}}\n"],
19075
19142
  dependencies: [{
19076
19143
  kind: "directive",
19077
19144
  type: TooltipDirective,
@@ -19113,7 +19180,7 @@ i0.ɵɵngDeclareClassMetadata({
19113
19180
  }
19114
19181
  </span>
19115
19182
  `,
19116
- styles: [":host{display:inline-flex}.tb{display:inline-flex;align-items:center;border-radius:999px;border:1px solid #e2e8f0;background:#fff;color:#64748b;transition:all .15s ease}.tb:hover{background:#f8fafc;border-color:#94a3b8}.tb.active{background:#1e293b;color:#fff;border-color:#1e293b}.toggle-badge{display:inline-flex;align-items:center;gap:5px;padding:var(--ui-toggle-badge-pad-y, 3px) var(--ui-toggle-badge-pad-x, 10px);border-radius:999px;border:none;background:transparent;font-size:.75rem;font-weight:500;color:inherit;cursor:pointer;font-family:inherit;line-height:1}.toggle-badge:focus-visible,.tb-action:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.tb-has-actions .toggle-badge{padding-right:6px}.tb-actions{display:inline-flex;align-items:center;gap:1px;padding-right:4px}.tb-divider{width:1px;height:12px;background:currentColor;opacity:.25;margin-right:3px}.tb-action{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;border-radius:50%;background:transparent;color:inherit;cursor:pointer;opacity:.75;font-family:inherit;transition:background .15s ease,opacity .15s ease}.tb-action:hover:not(:disabled){opacity:1;background:#64748b2e}.tb.active .tb-action:hover:not(:disabled){background:#fff3}.tb-action:disabled{opacity:.35;cursor:not-allowed}@media(pointer:coarse){.tb-action{position:relative}.tb-action:after{content:\"\";position:absolute;inset:-12px}}\n"]
19183
+ styles: [":host{display:inline-flex}.tb{display:inline-flex;align-items:center;border-radius:999px;border:1px solid #e2e8f0;background:#fff;color:#64748b;transition:all .15s ease}.tb:hover{background:#f8fafc;border-color:#94a3b8}.tb.active{background:#1e293b;color:#fff;border-color:#1e293b}.toggle-badge{display:inline-flex;align-items:center;gap:5px;padding:var(--ui-toggle-badge-pad-y, 3px) var(--ui-toggle-badge-pad-x, 10px);border-radius:999px;border:none;background:transparent;font-size:.75rem;font-weight:500;color:inherit;cursor:pointer;font-family:inherit;line-height:1}.toggle-badge:focus-visible,.tb-action:focus-visible{outline:2px solid #60a5fa;outline-offset:2px}.tb-has-actions .toggle-badge{padding-right:6px}@media(pointer:coarse){.toggle-badge{position:relative}.toggle-badge:after{content:\"\";position:absolute;inset:-12px -4px}}.tb-actions{display:inline-flex;align-items:center;gap:1px;padding-right:4px}.tb-divider{width:1px;height:12px;background:currentColor;opacity:.25;margin-right:3px}.tb-action{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;border-radius:50%;background:transparent;color:inherit;cursor:pointer;opacity:.75;font-family:inherit;transition:background .15s ease,opacity .15s ease}.tb-action:hover:not(:disabled){opacity:1;background:#64748b2e}.tb.active .tb-action:hover:not(:disabled){background:#fff3}.tb-action:disabled{opacity:.35;cursor:not-allowed}@media(pointer:coarse){.tb-action{position:relative}.tb-action:after{content:\"\";position:absolute;inset:-12px}}\n"]
19117
19184
  }]
19118
19185
  }],
19119
19186
  propDecorators: {
@@ -24305,41 +24372,41 @@ var ChipComponent = class ChipComponent {
24305
24372
  }],
24306
24373
  ngImport: i0,
24307
24374
  template: `
24308
- <button
24309
- type="button"
24310
- class="chip"
24311
- [class.chip--active]="_resolvedActive()"
24312
- [class.chip--sm]="size() === 'sm'"
24313
- [class.chip--lg]="size() === 'lg'"
24314
- [class.chip--dismissible]="dismissible()"
24315
- [attr.aria-pressed]="dismissible() ? null : (_resolvedActive() ? 'true' : 'false')"
24316
- [disabled]="_disabled()"
24317
- (click)="onClick()"
24318
- (keydown.delete)="onDismissKey($event)"
24319
- (keydown.backspace)="onDismissKey($event)"
24320
- (blur)="_onTouched()">
24321
- {{ label() }}
24322
- @if (dismissible()) {
24323
- <span
24324
- class="chip-dismiss"
24325
- role="button"
24326
- [attr.aria-label]="'Remove ' + label()"
24327
- [attr.tabindex]="_disabled() ? null : 0"
24328
- (click)="onDismiss($event)"
24329
- (keydown.enter)="onDismissKey($event)"
24330
- (keydown.space)="onDismissKey($event)"
24331
- (keyup.space)="$event.preventDefault(); $event.stopPropagation()">
24375
+ @if (dismissible()) {
24376
+ <span
24377
+ class="chip chip--dismissible"
24378
+ [class.chip--active]="_resolvedActive()"
24379
+ [class.chip--sm]="size() === 'sm'"
24380
+ [class.chip--lg]="size() === 'lg'"
24381
+ [class.chip--disabled]="_disabled()"
24382
+ (keydown.delete)="onDismissKey($event)"
24383
+ (keydown.backspace)="onDismissKey($event)">
24384
+ <button type="button" class="chip-body" [disabled]="_disabled()" (click)="onClick()" (blur)="_onTouched()">{{ label() }}</button>
24385
+ <button type="button" class="chip-dismiss" [disabled]="_disabled()" [attr.aria-label]="'Remove ' + label()" (click)="onDismiss($event)">
24332
24386
  <svg width="10" height="10" viewBox="0 0 24 24" fill="none"
24333
- stroke="currentColor" stroke-width="2.5" aria-hidden="true">
24387
+ stroke="currentColor" stroke-width="2.5" aria-hidden="true" focusable="false">
24334
24388
  <line x1="18" y1="6" x2="6" y2="18"/>
24335
24389
  <line x1="6" y1="6" x2="18" y2="18"/>
24336
24390
  </svg>
24337
- </span>
24338
- }
24339
- </button>
24391
+ </button>
24392
+ </span>
24393
+ } @else {
24394
+ <button
24395
+ type="button"
24396
+ class="chip"
24397
+ [class.chip--active]="_resolvedActive()"
24398
+ [class.chip--sm]="size() === 'sm'"
24399
+ [class.chip--lg]="size() === 'lg'"
24400
+ [attr.aria-pressed]="_resolvedActive() ? 'true' : 'false'"
24401
+ [disabled]="_disabled()"
24402
+ (click)="onClick()"
24403
+ (blur)="_onTouched()">
24404
+ {{ label() }}
24405
+ </button>
24406
+ }
24340
24407
  `,
24341
24408
  isInline: true,
24342
- styles: [":host{display:contents}.chip{display:inline-flex;align-items:center;gap:5px;border-radius:999px;border:1.5px solid #d1d5db;background:#f9fafb;color:#374151;font-weight:500;font-family:inherit;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;transition:background .15s,border-color .15s,color .15s}.chip:hover:not(:disabled){border-color:#3b82f6;color:#3b82f6;background:#eff6ff}.chip:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.chip:disabled{opacity:.5;cursor:default}.chip--sm{padding:2px 10px;font-size:.75rem}.chip--lg{padding:6px 16px;font-size:.875rem}.chip--sm.chip--dismissible{padding-right:6px}.chip--lg.chip--dismissible{padding-right:10px}.chip--active{background:#3b82f6;border-color:#3b82f6;color:#fff}.chip--active:hover:not(:disabled){background:#2563eb;border-color:#2563eb;color:#fff}.chip-dismiss{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;background:#0000001f;flex-shrink:0;transition:background .15s}.chip-dismiss:hover{background:#00000040}.chip-dismiss:focus-visible{outline:2px solid currentColor;outline-offset:1px}.chip--active .chip-dismiss{background:#ffffff4d}.chip--active .chip-dismiss:hover{background:#ffffff80}@media(pointer:coarse){.chip{min-height:44px}.chip--sm{min-height:40px;padding:6px 14px}.chip--lg{padding-left:18px;padding-right:18px}.chip--sm.chip--dismissible{padding-right:8px}.chip--lg.chip--dismissible{padding-right:12px}.chip-dismiss{width:24px;height:24px;position:relative}.chip-dismiss:after{content:\"\";position:absolute;inset:-10px}}@media(max-width:480px)and (pointer:fine){.chip-dismiss{position:relative}.chip-dismiss:after{content:\"\";position:absolute;inset:-15px}}\n"],
24409
+ styles: [":host{display:contents}.chip{display:inline-flex;align-items:center;gap:5px;border-radius:999px;border:1.5px solid #d1d5db;background:#f9fafb;color:#374151;font-weight:500;font-family:inherit;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;transition:background .15s,border-color .15s,color .15s}.chip:hover:not(:disabled):not(.chip--disabled){border-color:#3b82f6;color:#1d4ed8;background:#eff6ff}.chip:focus-visible,.chip:has(:focus-visible){outline:2px solid #3b82f6;outline-offset:2px}.chip:disabled,.chip.chip--disabled{opacity:.5;cursor:default}.chip--sm{padding:2px 10px;font-size:.75rem}.chip--lg{padding:6px 16px;font-size:.875rem}.chip--dismissible{padding:0;gap:0}.chip-body{display:inline-flex;align-items:center;align-self:stretch;background:none;border:0;margin:0;color:inherit;font:inherit;cursor:pointer;border-radius:999px 0 0 999px}.chip-body:focus-visible{outline:2px solid currentColor;outline-offset:-2px}.chip-body:disabled{cursor:default}.chip--sm .chip-body{padding:2px 4px 2px 10px}.chip--lg .chip-body{padding:6px 6px 6px 16px}.chip--sm.chip--dismissible .chip-dismiss{margin-right:6px}.chip--lg.chip--dismissible .chip-dismiss{margin-right:10px}.chip--active{background:#2563eb;border-color:#2563eb;color:#fff}.chip--active:hover:not(:disabled){background:#1d4ed8;border-color:#1d4ed8;color:#fff}.chip-dismiss{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;border:0;padding:0;color:inherit;cursor:pointer;background:#0000001f;flex-shrink:0;transition:background .15s}.chip-dismiss:hover{background:#00000040}.chip-dismiss:focus-visible{outline:2px solid currentColor;outline-offset:1px}.chip--active .chip-dismiss{background:#ffffff4d}.chip--active .chip-dismiss:hover{background:#ffffff80}@media(pointer:coarse){.chip{min-height:44px}.chip--sm{min-height:40px;padding:6px 14px}.chip--lg{padding-left:18px;padding-right:18px}.chip--sm .chip-body{padding:6px 4px 6px 14px}.chip--lg .chip-body{padding-left:18px}.chip--sm.chip--dismissible .chip-dismiss{margin-right:8px}.chip--lg.chip--dismissible .chip-dismiss{margin-right:12px}.chip-dismiss{width:24px;height:24px;position:relative}.chip-dismiss:after{content:\"\";position:absolute;inset:-10px}}@media(max-width:480px)and (pointer:fine){.chip-dismiss{position:relative}.chip-dismiss:after{content:\"\";position:absolute;inset:-15px}}\n"],
24343
24410
  changeDetection: i0.ChangeDetectionStrategy.OnPush
24344
24411
  });
24345
24412
  }
@@ -24361,40 +24428,40 @@ i0.ɵɵngDeclareClassMetadata({
24361
24428
  multi: true
24362
24429
  }],
24363
24430
  template: `
24364
- <button
24365
- type="button"
24366
- class="chip"
24367
- [class.chip--active]="_resolvedActive()"
24368
- [class.chip--sm]="size() === 'sm'"
24369
- [class.chip--lg]="size() === 'lg'"
24370
- [class.chip--dismissible]="dismissible()"
24371
- [attr.aria-pressed]="dismissible() ? null : (_resolvedActive() ? 'true' : 'false')"
24372
- [disabled]="_disabled()"
24373
- (click)="onClick()"
24374
- (keydown.delete)="onDismissKey($event)"
24375
- (keydown.backspace)="onDismissKey($event)"
24376
- (blur)="_onTouched()">
24377
- {{ label() }}
24378
- @if (dismissible()) {
24379
- <span
24380
- class="chip-dismiss"
24381
- role="button"
24382
- [attr.aria-label]="'Remove ' + label()"
24383
- [attr.tabindex]="_disabled() ? null : 0"
24384
- (click)="onDismiss($event)"
24385
- (keydown.enter)="onDismissKey($event)"
24386
- (keydown.space)="onDismissKey($event)"
24387
- (keyup.space)="$event.preventDefault(); $event.stopPropagation()">
24431
+ @if (dismissible()) {
24432
+ <span
24433
+ class="chip chip--dismissible"
24434
+ [class.chip--active]="_resolvedActive()"
24435
+ [class.chip--sm]="size() === 'sm'"
24436
+ [class.chip--lg]="size() === 'lg'"
24437
+ [class.chip--disabled]="_disabled()"
24438
+ (keydown.delete)="onDismissKey($event)"
24439
+ (keydown.backspace)="onDismissKey($event)">
24440
+ <button type="button" class="chip-body" [disabled]="_disabled()" (click)="onClick()" (blur)="_onTouched()">{{ label() }}</button>
24441
+ <button type="button" class="chip-dismiss" [disabled]="_disabled()" [attr.aria-label]="'Remove ' + label()" (click)="onDismiss($event)">
24388
24442
  <svg width="10" height="10" viewBox="0 0 24 24" fill="none"
24389
- stroke="currentColor" stroke-width="2.5" aria-hidden="true">
24443
+ stroke="currentColor" stroke-width="2.5" aria-hidden="true" focusable="false">
24390
24444
  <line x1="18" y1="6" x2="6" y2="18"/>
24391
24445
  <line x1="6" y1="6" x2="18" y2="18"/>
24392
24446
  </svg>
24393
- </span>
24394
- }
24395
- </button>
24447
+ </button>
24448
+ </span>
24449
+ } @else {
24450
+ <button
24451
+ type="button"
24452
+ class="chip"
24453
+ [class.chip--active]="_resolvedActive()"
24454
+ [class.chip--sm]="size() === 'sm'"
24455
+ [class.chip--lg]="size() === 'lg'"
24456
+ [attr.aria-pressed]="_resolvedActive() ? 'true' : 'false'"
24457
+ [disabled]="_disabled()"
24458
+ (click)="onClick()"
24459
+ (blur)="_onTouched()">
24460
+ {{ label() }}
24461
+ </button>
24462
+ }
24396
24463
  `,
24397
- styles: [":host{display:contents}.chip{display:inline-flex;align-items:center;gap:5px;border-radius:999px;border:1.5px solid #d1d5db;background:#f9fafb;color:#374151;font-weight:500;font-family:inherit;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;transition:background .15s,border-color .15s,color .15s}.chip:hover:not(:disabled){border-color:#3b82f6;color:#3b82f6;background:#eff6ff}.chip:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}.chip:disabled{opacity:.5;cursor:default}.chip--sm{padding:2px 10px;font-size:.75rem}.chip--lg{padding:6px 16px;font-size:.875rem}.chip--sm.chip--dismissible{padding-right:6px}.chip--lg.chip--dismissible{padding-right:10px}.chip--active{background:#3b82f6;border-color:#3b82f6;color:#fff}.chip--active:hover:not(:disabled){background:#2563eb;border-color:#2563eb;color:#fff}.chip-dismiss{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;background:#0000001f;flex-shrink:0;transition:background .15s}.chip-dismiss:hover{background:#00000040}.chip-dismiss:focus-visible{outline:2px solid currentColor;outline-offset:1px}.chip--active .chip-dismiss{background:#ffffff4d}.chip--active .chip-dismiss:hover{background:#ffffff80}@media(pointer:coarse){.chip{min-height:44px}.chip--sm{min-height:40px;padding:6px 14px}.chip--lg{padding-left:18px;padding-right:18px}.chip--sm.chip--dismissible{padding-right:8px}.chip--lg.chip--dismissible{padding-right:12px}.chip-dismiss{width:24px;height:24px;position:relative}.chip-dismiss:after{content:\"\";position:absolute;inset:-10px}}@media(max-width:480px)and (pointer:fine){.chip-dismiss{position:relative}.chip-dismiss:after{content:\"\";position:absolute;inset:-15px}}\n"]
24464
+ styles: [":host{display:contents}.chip{display:inline-flex;align-items:center;gap:5px;border-radius:999px;border:1.5px solid #d1d5db;background:#f9fafb;color:#374151;font-weight:500;font-family:inherit;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;transition:background .15s,border-color .15s,color .15s}.chip:hover:not(:disabled):not(.chip--disabled){border-color:#3b82f6;color:#1d4ed8;background:#eff6ff}.chip:focus-visible,.chip:has(:focus-visible){outline:2px solid #3b82f6;outline-offset:2px}.chip:disabled,.chip.chip--disabled{opacity:.5;cursor:default}.chip--sm{padding:2px 10px;font-size:.75rem}.chip--lg{padding:6px 16px;font-size:.875rem}.chip--dismissible{padding:0;gap:0}.chip-body{display:inline-flex;align-items:center;align-self:stretch;background:none;border:0;margin:0;color:inherit;font:inherit;cursor:pointer;border-radius:999px 0 0 999px}.chip-body:focus-visible{outline:2px solid currentColor;outline-offset:-2px}.chip-body:disabled{cursor:default}.chip--sm .chip-body{padding:2px 4px 2px 10px}.chip--lg .chip-body{padding:6px 6px 6px 16px}.chip--sm.chip--dismissible .chip-dismiss{margin-right:6px}.chip--lg.chip--dismissible .chip-dismiss{margin-right:10px}.chip--active{background:#2563eb;border-color:#2563eb;color:#fff}.chip--active:hover:not(:disabled){background:#1d4ed8;border-color:#1d4ed8;color:#fff}.chip-dismiss{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;border:0;padding:0;color:inherit;cursor:pointer;background:#0000001f;flex-shrink:0;transition:background .15s}.chip-dismiss:hover{background:#00000040}.chip-dismiss:focus-visible{outline:2px solid currentColor;outline-offset:1px}.chip--active .chip-dismiss{background:#ffffff4d}.chip--active .chip-dismiss:hover{background:#ffffff80}@media(pointer:coarse){.chip{min-height:44px}.chip--sm{min-height:40px;padding:6px 14px}.chip--lg{padding-left:18px;padding-right:18px}.chip--sm .chip-body{padding:6px 4px 6px 14px}.chip--lg .chip-body{padding-left:18px}.chip--sm.chip--dismissible .chip-dismiss{margin-right:8px}.chip--lg.chip--dismissible .chip-dismiss{margin-right:12px}.chip-dismiss{width:24px;height:24px;position:relative}.chip-dismiss:after{content:\"\";position:absolute;inset:-10px}}@media(max-width:480px)and (pointer:fine){.chip-dismiss{position:relative}.chip-dismiss:after{content:\"\";position:absolute;inset:-15px}}\n"]
24398
24465
  }]
24399
24466
  }],
24400
24467
  propDecorators: {
@@ -25728,7 +25795,7 @@ var FormSectionComponent = class FormSectionComponent {
25728
25795
  <div class="fs-fields"><ng-content /></div>
25729
25796
  `,
25730
25797
  isInline: true,
25731
- styles: [":host{display:block}.fs-divider{height:1px;background:#f1f5f9;margin:8px -24px 16px}.fs-label{font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#94a3b8;margin:0 0 12px}.fs-fields{display:flex;flex-direction:column;gap:14px}\n"],
25798
+ styles: [":host{display:block}.fs-divider{height:1px;background:#f1f5f9;margin:8px -24px 16px}.fs-label{font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#64748b;margin:0 0 12px}.fs-fields{display:flex;flex-direction:column;gap:14px}\n"],
25732
25799
  changeDetection: i0.ChangeDetectionStrategy.OnPush
25733
25800
  });
25734
25801
  }
@@ -25749,7 +25816,7 @@ i0.ɵɵngDeclareClassMetadata({
25749
25816
  @if (label()) { <p class="fs-label">{{ label() }}</p> }
25750
25817
  <div class="fs-fields"><ng-content /></div>
25751
25818
  `,
25752
- styles: [":host{display:block}.fs-divider{height:1px;background:#f1f5f9;margin:8px -24px 16px}.fs-label{font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#94a3b8;margin:0 0 12px}.fs-fields{display:flex;flex-direction:column;gap:14px}\n"]
25819
+ styles: [":host{display:block}.fs-divider{height:1px;background:#f1f5f9;margin:8px -24px 16px}.fs-label{font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#64748b;margin:0 0 12px}.fs-fields{display:flex;flex-direction:column;gap:14px}\n"]
25753
25820
  }]
25754
25821
  }],
25755
25822
  propDecorators: {
@@ -42885,7 +42952,7 @@ const DEFAULT_TEXTS = {
42885
42952
  importMore: "Import more",
42886
42953
  importRequired: "Import your data to continue, or skip this step.",
42887
42954
  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.`,
42955
+ importErrorsText: (_imported, errors) => `Nothing was imported yet. Fix the ${errors === 1 ? "row" : "rows"} listed in the import window in your file, then import the whole file again to continue.`,
42889
42956
  importAgain: "Import again",
42890
42957
  whatGetsImported: "WHAT GETS IMPORTED:",
42891
42958
  summaryTitle: "Your setup",
@@ -43044,6 +43111,9 @@ var SetupWizardComponent = class SetupWizardComponent {
43044
43111
  this.skipped.update((s) => new Set(s).add(key));
43045
43112
  this.advanceFrom(key);
43046
43113
  }
43114
+ completeSteps(...keys) {
43115
+ this.markStepsCompleted(keys);
43116
+ }
43047
43117
  markStepsCompleted(keys) {
43048
43118
  const known = new Set(this.steps().map((s) => s.key));
43049
43119
  for (const key of keys) if (known.has(key)) this.markCompleted(key);
@@ -43059,6 +43129,7 @@ var SetupWizardComponent = class SetupWizardComponent {
43059
43129
  async saveAndContinue() {
43060
43130
  if (this.busy()) return;
43061
43131
  const step = this.current();
43132
+ if (step.canContinue && !step.canContinue()) return;
43062
43133
  this.busy.set(true);
43063
43134
  this.error.set("");
43064
43135
  try {
@@ -43323,7 +43394,7 @@ var SetupWizardComponent = class SetupWizardComponent {
43323
43394
  </ui-button>
43324
43395
  }
43325
43396
  } @else if (current().kind === 'integrations') {
43326
- <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>
43397
+ <ui-button variant="primary" size="sm" [fullWidth]="narrow()" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (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>
43327
43398
  } @else if (current().kind === 'import') {
43328
43399
  <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>
43329
43400
  }
@@ -43337,6 +43408,7 @@ var SetupWizardComponent = class SetupWizardComponent {
43337
43408
  [ariaLabel]="current().extraTitle || current().label" headerBackground="rgb(248, 250, 252)" footerBackground="rgb(248, 250, 252)" data-testid="wizard-extra-card">
43338
43409
  <ng-container [ngTemplateOutlet]="left" [ngTemplateOutletContext]="{ $implicit: api }" />
43339
43410
  <p class="sw-extra-status" role="status" data-testid="wizard-extra-status">{{ current().extraFooter?.() }}</p>
43411
+ @if (error()) { <ui-alert variant="danger" data-testid="wizard-save-error">{{ error() }}</ui-alert> }
43340
43412
  @if (importBlocked()) { <p class="sw-hint sw-continue-hint" id="sw-continue-hint" data-testid="wizard-continue-hint">{{ t().importRequired }}</p> }
43341
43413
  <div card-footer class="sw-step-actions"><ng-container [ngTemplateOutlet]="actions" /></div>
43342
43414
  </ui-detail-card>
@@ -43414,7 +43486,7 @@ var SetupWizardComponent = class SetupWizardComponent {
43414
43486
  </div>
43415
43487
  `,
43416
43488
  isInline: true,
43417
- 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-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-summary{display:block}.sw-done-hint{margin:16px 0 0}@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"],
43489
+ 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:#64748b}.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-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-summary{display:block}.sw-done-hint{margin:16px 0 0}@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"],
43418
43490
  dependencies: [
43419
43491
  {
43420
43492
  kind: "directive",
@@ -43797,7 +43869,7 @@ i0.ɵɵngDeclareClassMetadata({
43797
43869
  </ui-button>
43798
43870
  }
43799
43871
  } @else if (current().kind === 'integrations') {
43800
- <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>
43872
+ <ui-button variant="primary" size="sm" [fullWidth]="narrow()" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (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>
43801
43873
  } @else if (current().kind === 'import') {
43802
43874
  <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>
43803
43875
  }
@@ -43811,6 +43883,7 @@ i0.ɵɵngDeclareClassMetadata({
43811
43883
  [ariaLabel]="current().extraTitle || current().label" headerBackground="rgb(248, 250, 252)" footerBackground="rgb(248, 250, 252)" data-testid="wizard-extra-card">
43812
43884
  <ng-container [ngTemplateOutlet]="left" [ngTemplateOutletContext]="{ $implicit: api }" />
43813
43885
  <p class="sw-extra-status" role="status" data-testid="wizard-extra-status">{{ current().extraFooter?.() }}</p>
43886
+ @if (error()) { <ui-alert variant="danger" data-testid="wizard-save-error">{{ error() }}</ui-alert> }
43814
43887
  @if (importBlocked()) { <p class="sw-hint sw-continue-hint" id="sw-continue-hint" data-testid="wizard-continue-hint">{{ t().importRequired }}</p> }
43815
43888
  <div card-footer class="sw-step-actions"><ng-container [ngTemplateOutlet]="actions" /></div>
43816
43889
  </ui-detail-card>
@@ -43887,7 +43960,7 @@ i0.ɵɵngDeclareClassMetadata({
43887
43960
  </main>
43888
43961
  </div>
43889
43962
  `,
43890
- 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-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-summary{display:block}.sw-done-hint{margin:16px 0 0}@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"]
43963
+ 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:#64748b}.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-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-summary{display:block}.sw-done-hint{margin:16px 0 0}@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"]
43891
43964
  }]
43892
43965
  }],
43893
43966
  ctorParameters: () => [],
@@ -43953,6 +44026,14 @@ function isWebUrl(raw) {
43953
44026
  return false;
43954
44027
  }
43955
44028
  }
44029
+ function serializedTextLength(text) {
44030
+ let n = 0;
44031
+ for (let i = 0; i < text.length; i++) {
44032
+ const ch = text[i];
44033
+ n += ch === "&" ? 5 : ch === "<" || ch === ">" ? 4 : ch === "\xA0" ? 6 : 1;
44034
+ }
44035
+ return n;
44036
+ }
43956
44037
  function escapeHtml(value) {
43957
44038
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
43958
44039
  }
@@ -44367,7 +44448,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44367
44448
  if (this.subjectError()) missing.push(this.subject().trim() ? "a shorter subject" : "a subject");
44368
44449
  if (this.bodyError()) missing.push(this.bodyHasContent() ? "a shorter message" : "a message");
44369
44450
  if (this.assignmentError()) missing.push("at least one assignment");
44370
- return missing.length ? `Add ${missing.join(", ")} to save this template.` : this.datesError() || "Fix the highlighted fields to save this template.";
44451
+ return missing.length ? `Add ${missing.join(", ")} to save this template.` : this.datesError();
44371
44452
  }, ...ngDevMode ? [{ debugName: "saveHint" }] : /* istanbul ignore next */ []);
44372
44453
  this.normalizedLink = computed(() => {
44373
44454
  const url = this.linkUrl().trim();
@@ -44640,8 +44721,8 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44640
44721
  const incoming = event.data ?? event.dataTransfer?.getData("text/plain") ?? "";
44641
44722
  if (!incoming) return;
44642
44723
  const sel = window.getSelection();
44643
- const replaced = sel && !sel.isCollapsed && insideEditorBlock(sel.anchorNode) ? sel.toString().length : 0;
44644
- if (this.bodyLength() - replaced + escapeHtml(incoming).length > this.maxBodyLength()) event.preventDefault();
44724
+ const replaced = sel && !sel.isCollapsed && insideEditorBlock(sel.anchorNode) ? serializedTextLength(sel.toString()) : 0;
44725
+ if (this.bodyLength() - replaced + serializedTextLength(incoming) > this.maxBodyLength()) event.preventDefault();
44645
44726
  }
44646
44727
  onBlockFocus(block) {
44647
44728
  this.selectedBlockId.set(block.id);
@@ -44821,8 +44902,8 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44821
44902
  const sel = window.getSelection();
44822
44903
  if (sel && sel.rangeCount > 0 && !sel.isCollapsed) {
44823
44904
  document.execCommand("createLink", false, url);
44824
- const range = sel.getRangeAt(0);
44825
- (range.commonAncestorContainer instanceof Element ? range.commonAncestorContainer : range.commonAncestorContainer.parentElement)?.querySelectorAll("a").forEach((l) => {
44905
+ const node = sel.getRangeAt(0).commonAncestorContainer;
44906
+ (this.editorFor(this.selectedBlockId())?.nativeElement ?? (node instanceof Element ? node : node.parentElement)?.closest(".block-content") ?? null)?.querySelectorAll("a").forEach((l) => {
44826
44907
  if (l.getAttribute("href") === url) l.setAttribute("target", "_blank");
44827
44908
  });
44828
44909
  } else {
@@ -45159,7 +45240,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
45159
45240
  <!-- Actions (outside the white panels) -->
45160
45241
  <div class="editor-actions">
45161
45242
  @if (heading()) {
45162
- <h1 class="editor-heading" data-testid="editor-heading">{{ heading() }}</h1>
45243
+ <h2 class="editor-heading" data-testid="editor-heading">{{ heading() }}</h2>
45163
45244
  }
45164
45245
  <div class="editor-actions-buttons">
45165
45246
  @if (canWrite() && testSendEnabled()) {
@@ -45251,7 +45332,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
45251
45332
  </aside>
45252
45333
 
45253
45334
  <!-- CENTER: Editor -->
45254
- <main class="panel-center">
45335
+ <section class="panel-center" aria-label="Email design">
45255
45336
  <div class="editor-tabs" role="tablist" aria-label="Editor view">
45256
45337
  <button type="button" class="editor-tab" role="tab" [class.active]="activeEditorTab() === 'edit'" [attr.aria-selected]="activeEditorTab() === 'edit'" (click)="setEditorTab('edit')">
45257
45338
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/></svg>
@@ -45447,7 +45528,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
45447
45528
  </div>
45448
45529
  </div>
45449
45530
  }
45450
- </main>
45531
+ </section>
45451
45532
 
45452
45533
  <!-- RIGHT PANEL: Blocks, Variables, Video -->
45453
45534
  <aside class="panel-right" aria-label="Blocks, variables and video">
@@ -45621,7 +45702,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
45621
45702
 
45622
45703
  `,
45623
45704
  isInline: true,
45624
- 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;align-items:stretch;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{display:block;flex:1 1 auto;max-width:600px;width:100%;box-sizing:border-box;min-height:400px;background:#fff;border:1px solid #e2e8f0;border-radius: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;max-width:100%;height:520px;min-height:0}.blocks-canvas{flex:1 1 0;min-height:0;padding:16px 20px 24px 56px;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:attr(data-placeholder);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:0;left:-48px;flex-direction:column;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 0;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}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"],
45705
+ 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:#64748b;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:#1d4ed8;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;align-items:stretch;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{display:block;flex:1 1 auto;max-width:600px;width:100%;box-sizing:border-box;min-height:400px;background:#fff;border:1px solid #e2e8f0;border-radius: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;max-width:100%;height:520px;min-height:0}.blocks-canvas{flex:1 1 0;min-height:0;padding:16px 20px 24px 56px;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:attr(data-placeholder);color:#64748b;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:0;left:-48px;flex-direction:column;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(pointer:coarse){.editor-tab,.right-tab,.block-group-header{min-height:44px}}@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:#1d4ed8;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:#475569;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:#1d4ed8;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:#475569;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 0;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:#1d4ed8;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:#475569}.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}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"],
45625
45706
  dependencies: [
45626
45707
  {
45627
45708
  kind: "ngmodule",
@@ -45942,7 +46023,7 @@ i0.ɵɵngDeclareClassMetadata({
45942
46023
  <!-- Actions (outside the white panels) -->
45943
46024
  <div class="editor-actions">
45944
46025
  @if (heading()) {
45945
- <h1 class="editor-heading" data-testid="editor-heading">{{ heading() }}</h1>
46026
+ <h2 class="editor-heading" data-testid="editor-heading">{{ heading() }}</h2>
45946
46027
  }
45947
46028
  <div class="editor-actions-buttons">
45948
46029
  @if (canWrite() && testSendEnabled()) {
@@ -46034,7 +46115,7 @@ i0.ɵɵngDeclareClassMetadata({
46034
46115
  </aside>
46035
46116
 
46036
46117
  <!-- CENTER: Editor -->
46037
- <main class="panel-center">
46118
+ <section class="panel-center" aria-label="Email design">
46038
46119
  <div class="editor-tabs" role="tablist" aria-label="Editor view">
46039
46120
  <button type="button" class="editor-tab" role="tab" [class.active]="activeEditorTab() === 'edit'" [attr.aria-selected]="activeEditorTab() === 'edit'" (click)="setEditorTab('edit')">
46040
46121
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/></svg>
@@ -46230,7 +46311,7 @@ i0.ɵɵngDeclareClassMetadata({
46230
46311
  </div>
46231
46312
  </div>
46232
46313
  }
46233
- </main>
46314
+ </section>
46234
46315
 
46235
46316
  <!-- RIGHT PANEL: Blocks, Variables, Video -->
46236
46317
  <aside class="panel-right" aria-label="Blocks, variables and video">
@@ -46403,7 +46484,7 @@ i0.ɵɵngDeclareClassMetadata({
46403
46484
 
46404
46485
 
46405
46486
  `,
46406
- 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;align-items:stretch;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{display:block;flex:1 1 auto;max-width:600px;width:100%;box-sizing:border-box;min-height:400px;background:#fff;border:1px solid #e2e8f0;border-radius: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;max-width:100%;height:520px;min-height:0}.blocks-canvas{flex:1 1 0;min-height:0;padding:16px 20px 24px 56px;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:attr(data-placeholder);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:0;left:-48px;flex-direction:column;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 0;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}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"]
46487
+ 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:#64748b;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:#1d4ed8;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;align-items:stretch;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{display:block;flex:1 1 auto;max-width:600px;width:100%;box-sizing:border-box;min-height:400px;background:#fff;border:1px solid #e2e8f0;border-radius: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;max-width:100%;height:520px;min-height:0}.blocks-canvas{flex:1 1 0;min-height:0;padding:16px 20px 24px 56px;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:attr(data-placeholder);color:#64748b;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:0;left:-48px;flex-direction:column;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(pointer:coarse){.editor-tab,.right-tab,.block-group-header{min-height:44px}}@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:#1d4ed8;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:#475569;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:#1d4ed8;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:#475569;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 0;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:#1d4ed8;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:#475569}.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}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"]
46407
46488
  }]
46408
46489
  }],
46409
46490
  ctorParameters: () => [],
@@ -46650,6 +46731,6 @@ i0.ɵɵngDeclareClassMetadata({
46650
46731
  }]
46651
46732
  }
46652
46733
  });
46653
- 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, buildPreviewDocument, 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 };
46734
+ 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, buildPreviewDocument, 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, serializedTextLength, setupIntegrations, splitIntro };
46654
46735
 
46655
46736
  //# sourceMappingURL=forgeroute-ui.mjs.map