myio-js-library 0.1.546 → 0.1.548

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.
package/dist/index.cjs CHANGED
@@ -470,6 +470,9 @@ __export(src_exports, {
470
470
  createModalHeader: () => createModalHeader,
471
471
  createMoneyVarianceColumn: () => createMoneyVarianceColumn,
472
472
  createMyIOTheme: () => createMyIOTheme,
473
+ createMyioGcdrLoginSubmit: () => createMyioGcdrLoginSubmit,
474
+ createMyioGcdrLoginView: () => createMyioGcdrLoginView,
475
+ createMyioGcdrShell: () => createMyioGcdrShell,
473
476
  createNewTicketWizard: () => createNewTicketWizard,
474
477
  createOnOffDeviceModal: () => createOnOffDeviceModal,
475
478
  createOnOffTimelineChart: () => createOnOffTimelineChart,
@@ -710,6 +713,7 @@ __export(src_exports, {
710
713
  isInRange: () => isInRange,
711
714
  isLeapYear: () => isLeapYear,
712
715
  isMoneyColumnConfident: () => isMoneyColumnConfident,
716
+ isMyioGcdrLoginModalOpen: () => isMyioGcdrLoginModalOpen,
713
717
  isOnOffDeviceProfile: () => isOnOffDeviceProfile,
714
718
  isSolenoidDevice: () => isSolenoidDevice,
715
719
  isStoreDevice: () => isStoreDevice,
@@ -771,6 +775,7 @@ __export(src_exports, {
771
775
  openMeasurementSetupModal: () => openMeasurementSetupModal,
772
776
  openMessageDialog: () => openMessageDialog,
773
777
  openMetasGuide: () => openMetasGuide,
778
+ openMyioGcdrLoginModal: () => openMyioGcdrLoginModal,
774
779
  openOnOffDeviceModal: () => openOnOffDeviceModal,
775
780
  openOnboardModal: () => openOnboardModal,
776
781
  openOperationalComparisonModal: () => openOperationalComparisonModal,
@@ -894,7 +899,7 @@ module.exports = __toCommonJS(src_exports);
894
899
  // package.json
895
900
  var package_default = {
896
901
  name: "myio-js-library",
897
- version: "0.1.546",
902
+ version: "0.1.548",
898
903
  description: "A clean, standalone JS SDK for MYIO projects",
899
904
  license: "MIT",
900
905
  repository: "github:gh-myio/myio-js-library",
@@ -5423,22 +5428,22 @@ function generateExportHTML(modalId, exportFormats) {
5423
5428
  if (exportFormats.length === 0) return "";
5424
5429
  if (exportFormats.length === 1) {
5425
5430
  const format = exportFormats[0];
5426
- const icon = EXPORT_FORMAT_ICONS[format] || "\u{1F4E5}";
5431
+ const icon2 = EXPORT_FORMAT_ICONS[format] || "\u{1F4E5}";
5427
5432
  return `<button
5428
5433
  id="${modalId}-export"
5429
5434
  class="myio-modal-header__btn"
5430
5435
  title="Exportar ${EXPORT_FORMAT_LABELS[format]}"
5431
- >${icon}</button>`;
5436
+ >${icon2}</button>`;
5432
5437
  }
5433
5438
  const dropdownOptions = exportFormats.map((format) => {
5434
- const icon = EXPORT_FORMAT_ICONS[format] || "\u{1F4C4}";
5439
+ const icon2 = EXPORT_FORMAT_ICONS[format] || "\u{1F4C4}";
5435
5440
  const label = EXPORT_FORMAT_LABELS[format] || format.toUpperCase();
5436
5441
  return `<button
5437
5442
  id="${modalId}-export-${format}"
5438
5443
  class="myio-export-option"
5439
5444
  data-format="${format}"
5440
5445
  title="Exportar ${label}"
5441
- >${icon} ${label}</button>`;
5446
+ >${icon2} ${label}</button>`;
5442
5447
  }).join("");
5443
5448
  return `
5444
5449
  <div style="position: relative; display: inline-block;">
@@ -5493,7 +5498,7 @@ var ModalHeader = {
5493
5498
  generateHTML(options) {
5494
5499
  injectCSS();
5495
5500
  const {
5496
- icon,
5501
+ icon: icon2,
5497
5502
  title,
5498
5503
  modalId,
5499
5504
  theme = "dark",
@@ -5535,7 +5540,7 @@ var ModalHeader = {
5535
5540
  data-drag-handle
5536
5541
  >
5537
5542
  <div class="myio-modal-header__left">
5538
- <span class="myio-modal-header__icon">${icon}</span>
5543
+ <span class="myio-modal-header__icon">${icon2}</span>
5539
5544
  <h2 class="myio-modal-header__title">${title}</h2>
5540
5545
  </div>
5541
5546
  <div class="myio-modal-header__actions">
@@ -5553,7 +5558,7 @@ var ModalHeader = {
5553
5558
  */
5554
5559
  generateInlineHTML(options) {
5555
5560
  const {
5556
- icon,
5561
+ icon: icon2,
5557
5562
  title,
5558
5563
  modalId,
5559
5564
  theme = "dark",
@@ -5598,7 +5603,7 @@ var ModalHeader = {
5598
5603
  return `
5599
5604
  <div id="${modalId}-header" style="${headerStyle}" data-drag-handle>
5600
5605
  <div style="display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0;">
5601
- <span style="font-size: 18px;">${icon}</span>
5606
+ <span style="font-size: 18px;">${icon2}</span>
5602
5607
  <h2 style="margin: 0; font-size: 16px; font-weight: 600; color: ${textColor}; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
5603
5608
  ${title}
5604
5609
  </h2>
@@ -6370,10 +6375,10 @@ var state = {
6370
6375
  pinnedCounter: 0,
6371
6376
  isPinned: false
6372
6377
  };
6373
- function generateHeaderHTML(icon, title) {
6378
+ function generateHeaderHTML(icon2, title) {
6374
6379
  return `
6375
6380
  <div class="myio-info-tooltip__header" data-drag-handle>
6376
- <span class="myio-info-tooltip__icon">${icon}</span>
6381
+ <span class="myio-info-tooltip__icon">${icon2}</span>
6377
6382
  <span class="myio-info-tooltip__title">${title}</span>
6378
6383
  <div class="myio-info-tooltip__header-actions">
6379
6384
  <button class="myio-info-tooltip__header-btn" data-action="pin" title="Fixar na tela">
@@ -7002,7 +7007,7 @@ function openDeviceProfileModal(params) {
7002
7007
  });
7003
7008
  const body = handle.element;
7004
7009
  handle.on("close", () => {
7005
- cardHandles.forEach((h2) => h2.destroy());
7010
+ cardHandles.forEach((h3) => h3.destroy());
7006
7011
  cardHandles = [];
7007
7012
  onClose?.();
7008
7013
  });
@@ -7044,7 +7049,7 @@ function openDeviceProfileModal(params) {
7044
7049
  </div>`;
7045
7050
  }
7046
7051
  function mountCards() {
7047
- cardHandles.forEach((h2) => h2.destroy());
7052
+ cardHandles.forEach((h3) => h3.destroy());
7048
7053
  cardHandles = [];
7049
7054
  cardIds = [];
7050
7055
  const d = dom();
@@ -7074,10 +7079,10 @@ function openDeviceProfileModal(params) {
7074
7079
  cardIds.push(id);
7075
7080
  };
7076
7081
  const sep = (text2) => {
7077
- const h2 = document.createElement("h3");
7078
- h2.className = "mdp-sep-title";
7079
- h2.textContent = text2;
7080
- editor.appendChild(h2);
7082
+ const h3 = document.createElement("h3");
7083
+ h3.className = "mdp-sep-title";
7084
+ h3.textContent = text2;
7085
+ editor.appendChild(h3);
7081
7086
  };
7082
7087
  sep("Colunas (grupos)");
7083
7088
  addCard(
@@ -7466,7 +7471,7 @@ function openDeviceProfileModal(params) {
7466
7471
  function setAllCollapsed(collapsed) {
7467
7472
  if (collapsed) cardIds.forEach((id) => collapsedIds.add(id));
7468
7473
  else collapsedIds.clear();
7469
- cardHandles.forEach((h2) => h2.setCollapsed(collapsed));
7474
+ cardHandles.forEach((h3) => h3.setCollapsed(collapsed));
7470
7475
  }
7471
7476
  function refreshPreview() {
7472
7477
  const hasCats = !!dom()?.categories;
@@ -16110,13 +16115,13 @@ var MyIODraggableCard = class {
16110
16115
  this.container.appendChild(card);
16111
16116
  }
16112
16117
  _generateCardHTML() {
16113
- const { id, name, icon, group, lastValue, unit, status } = this.entity;
16118
+ const { id, name, icon: icon2, group, lastValue, unit, status } = this.entity;
16114
16119
  const checkboxHtml = this.options.showCheckbox ? `<input type="checkbox" class="card-checkbox" aria-label="Select ${name}">` : "";
16115
16120
  return `
16116
16121
  <div class="card-header">
16117
16122
  ${checkboxHtml}
16118
- <div class="card-icon card-icon-${icon}">
16119
- ${this._getIconSvg(icon)}
16123
+ <div class="card-icon card-icon-${icon2}">
16124
+ ${this._getIconSvg(icon2)}
16120
16125
  </div>
16121
16126
  <div class="card-status card-status-${status}"></div>
16122
16127
  </div>
@@ -18644,6 +18649,12 @@ function renderCardComponentV5({
18644
18649
  temperatureMax,
18645
18650
  temperatureStatus,
18646
18651
  // 'ok' | 'above' | 'below' | undefined
18652
+ // Temperatura atual vinda do Ingestion = média das últimas 2 h; true = nenhuma leitura na janela
18653
+ temperatureNoRecentReading = false,
18654
+ temperatureSource,
18655
+ // 'ingestion-avg-2h' | 'thingsboard' | undefined
18656
+ temperatureFetchedAt,
18657
+ // ms da consulta (rótulo "Atualizado às HH:MM")
18647
18658
  // Per-device exclude_groups_totals attribute (SERVER_SCOPE) — drives the orange marker
18648
18659
  excludeGroupsTotals
18649
18660
  } = entityObject;
@@ -18740,7 +18751,7 @@ function renderCardComponentV5({
18740
18751
  const connectionStatus = mapDeviceToConnectionStatus(deviceStatus);
18741
18752
  const isOffline = isDeviceOffline(deviceStatus);
18742
18753
  const shouldFlashIcon2 = shouldFlashIcon(deviceStatus);
18743
- const icon = getDeviceStatusIcon(deviceStatus, deviceType);
18754
+ const icon2 = getDeviceStatusIcon(deviceStatus, deviceType);
18744
18755
  const connectionIcon = getConnectionStatusIcon(connectionStatus);
18745
18756
  const debugDeviceName = "3F SCMAL3L4304ABC";
18746
18757
  const labelStr = String(labelOrName || "");
@@ -18803,7 +18814,14 @@ function renderCardComponentV5({
18803
18814
  const percentageForDisplay = isTankDevice2 ? (waterPercentage || 0) * 100 : perc;
18804
18815
  const tankLevelCm = isTankDevice2 ? Number(waterLevel ?? val) : null;
18805
18816
  const _pctDecimals = resolvePercentDecimals(percentDecimals);
18817
+ const showNoTempReading = !!temperatureNoRecentReading && isTemperatureDevice2(deviceType);
18818
+ const tempValueTitle = (() => {
18819
+ if (!isTemperatureDevice2(deviceType) || temperatureSource !== "ingestion-avg-2h") return "";
18820
+ const at = temperatureFetchedAt ? ` \xB7 Atualizado \xE0s ${new Date(temperatureFetchedAt).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })}` : "";
18821
+ return showNoTempReading ? `Nenhuma leitura nas \xFAltimas 2 h${at}` : `Temperatura (m\xE9dia das \xFAltimas 2 h)${at}`;
18822
+ })();
18806
18823
  const formatCardValue = (value, deviceType2) => {
18824
+ if (showNoTempReading) return "Sem leitura recente";
18807
18825
  if (isTankDevice2) {
18808
18826
  return `${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%`;
18809
18827
  }
@@ -19106,7 +19124,7 @@ function renderCardComponentV5({
19106
19124
  }
19107
19125
  return "ok";
19108
19126
  };
19109
- const tempStatus = isTermostatoDevice ? calculateTempStatus2() : null;
19127
+ const tempStatus = isTermostatoDevice && !showNoTempReading ? calculateTempStatus2() : null;
19110
19128
  const deviceImageUrl = getDeviceImageUrl(deviceType, percentageForDisplay, {
19111
19129
  tempStatus,
19112
19130
  isOffline
@@ -19126,7 +19144,7 @@ function renderCardComponentV5({
19126
19144
  }
19127
19145
  return null;
19128
19146
  };
19129
- const tempDeviationPercent = isTermostatoDevice ? calculateTempDeviationPercent() : null;
19147
+ const tempDeviationPercent = isTermostatoDevice && !showNoTempReading ? calculateTempDeviationPercent() : null;
19130
19148
  const cardHTML = `
19131
19149
  <div class="device-card-centered clickable ${cardEntity.status === "offline" ? "offline" : ""}"
19132
19150
  data-entity-id="${entityId}"
@@ -19169,9 +19187,9 @@ function renderCardComponentV5({
19169
19187
  <div class="device-data-row">
19170
19188
  <div class="consumption-main">
19171
19189
  <span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
19172
- ${icon}
19190
+ ${icon2}
19173
19191
  </span>
19174
- <span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType)}</span>
19192
+ <span class="consumption-value"${showNoTempReading ? ' style="color:#9ca3af;font-weight:500;font-size:0.85em;"' : ""}${tempValueTitle ? ` title="${tempValueTitle}"` : ""}>${formatCardValue(cardEntity.lastValue, deviceType)}</span>
19175
19193
  </div>
19176
19194
  </div>
19177
19195
  ${isTankDevice2 ? `<span class="device-percentage-badge device-tank-level-badge" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important;">${formatTankHeadFromCm(tankLevelCm)}</span>` : !isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
@@ -20579,7 +20597,7 @@ function renderCardComponentV6({
20579
20597
  const connectionStatus = mapDeviceToConnectionStatus(deviceStatus);
20580
20598
  const isOffline = isDeviceOffline(deviceStatus);
20581
20599
  const shouldFlashIcon2 = shouldFlashIcon(deviceStatus);
20582
- const icon = getDeviceStatusIcon(deviceStatus, effectiveDeviceType);
20600
+ const icon2 = getDeviceStatusIcon(deviceStatus, effectiveDeviceType);
20583
20601
  const connectionIcon = getConnectionStatusIcon(connectionStatus);
20584
20602
  const mapDeviceTypeToIcon = (deviceType2) => {
20585
20603
  const category = getDeviceCategory(deviceType2);
@@ -20961,7 +20979,7 @@ function renderCardComponentV6({
20961
20979
  <div class="device-data-row">
20962
20980
  <div class="consumption-main">
20963
20981
  <span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
20964
- ${icon}
20982
+ ${icon2}
20965
20983
  </span>
20966
20984
  <span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType, deviceProfile)}</span>
20967
20985
  </div>
@@ -22510,12 +22528,12 @@ function renderCardAmbienteV6({
22510
22528
  statusText = isOn2 ? "ON" : "OFF";
22511
22529
  stateClass = isOn2 ? "on" : "off";
22512
22530
  }
22513
- const icon = isLamp ? "\u{1F4A1}" : "\u{1F518}";
22531
+ const icon2 = isLamp ? "\u{1F4A1}" : "\u{1F518}";
22514
22532
  const deviceEl = document.createElement("div");
22515
22533
  deviceEl.className = `myio-ambiente-card__switch-device ${stateClass} ${isLamp ? "lamp" : "remote"}`;
22516
22534
  deviceEl.title = device.label || device.name || (isLamp ? "L\xE2mpada" : "Controle");
22517
22535
  deviceEl.innerHTML = `
22518
- <span class="myio-ambiente-card__switch-device-icon">${icon}</span>
22536
+ <span class="myio-ambiente-card__switch-device-icon">${icon2}</span>
22519
22537
  <span class="myio-ambiente-card__switch-device-value">${statusText}</span>
22520
22538
  `;
22521
22539
  scrollContainer.appendChild(deviceEl);
@@ -22936,10 +22954,10 @@ var HeaderPanelComponent = class {
22936
22954
  el2.style.display = quantity >= 0 ? "" : "none";
22937
22955
  }
22938
22956
  }
22939
- setIcon(icon) {
22940
- this.options.icon = icon;
22957
+ setIcon(icon2) {
22958
+ this.options.icon = icon2;
22941
22959
  const el2 = this.root.querySelector(".myio-hp__icon");
22942
- if (el2) el2.innerHTML = icon;
22960
+ if (el2) el2.innerHTML = icon2;
22943
22961
  }
22944
22962
  setSubtitle(subtitle) {
22945
22963
  this.options.subtitle = subtitle;
@@ -22998,7 +23016,7 @@ var HeaderPanelComponent = class {
22998
23016
  render() {
22999
23017
  const {
23000
23018
  title,
23001
- icon,
23019
+ icon: icon2,
23002
23020
  quantity,
23003
23021
  style,
23004
23022
  showSearch,
@@ -23015,10 +23033,10 @@ var HeaderPanelComponent = class {
23015
23033
  }
23016
23034
  const left = document.createElement("div");
23017
23035
  left.className = "myio-hp__left";
23018
- if (icon) {
23036
+ if (icon2) {
23019
23037
  const iconEl = document.createElement("span");
23020
23038
  iconEl.className = "myio-hp__icon";
23021
- iconEl.innerHTML = icon;
23039
+ iconEl.innerHTML = icon2;
23022
23040
  if (style?.iconColor) iconEl.style.color = style.iconColor;
23023
23041
  left.appendChild(iconEl);
23024
23042
  }
@@ -23497,10 +23515,10 @@ var EntityListPanel = class {
23497
23515
  }
23498
23516
  }
23499
23517
  /** Update icon */
23500
- setIcon(icon) {
23501
- this.options.icon = icon;
23518
+ setIcon(icon2) {
23519
+ this.options.icon = icon2;
23502
23520
  if (this.headerComponent) {
23503
- this.headerComponent.setIcon(icon);
23521
+ this.headerComponent.setIcon(icon2);
23504
23522
  }
23505
23523
  }
23506
23524
  /** Update background watermark image */
@@ -23550,7 +23568,7 @@ var EntityListPanel = class {
23550
23568
  const {
23551
23569
  title,
23552
23570
  subtitle,
23553
- icon,
23571
+ icon: icon2,
23554
23572
  quantity,
23555
23573
  backgroundImage,
23556
23574
  searchPlaceholder,
@@ -23569,7 +23587,7 @@ var EntityListPanel = class {
23569
23587
  this.headerComponent = new HeaderPanelComponent({
23570
23588
  title,
23571
23589
  subtitle,
23572
- icon,
23590
+ icon: icon2,
23573
23591
  quantity,
23574
23592
  style: titleStyle,
23575
23593
  showBottomBorder: false,
@@ -24050,10 +24068,10 @@ var CardGridPanel = class {
24050
24068
  }
24051
24069
  }
24052
24070
  /** Update icon */
24053
- setIcon(icon) {
24054
- this.options.icon = icon;
24071
+ setIcon(icon2) {
24072
+ this.options.icon = icon2;
24055
24073
  if (this.headerComponent) {
24056
- this.headerComponent.setIcon(icon);
24074
+ this.headerComponent.setIcon(icon2);
24057
24075
  }
24058
24076
  }
24059
24077
  /** Set maximize state without triggering callback (for external reset) */
@@ -24109,7 +24127,7 @@ var CardGridPanel = class {
24109
24127
  render() {
24110
24128
  const {
24111
24129
  title,
24112
- icon,
24130
+ icon: icon2,
24113
24131
  quantity,
24114
24132
  gridMinCardWidth,
24115
24133
  titleStyle,
@@ -24124,7 +24142,7 @@ var CardGridPanel = class {
24124
24142
  this.root.innerHTML = "";
24125
24143
  this.headerComponent = new HeaderPanelComponent({
24126
24144
  title,
24127
- icon,
24145
+ icon: icon2,
24128
24146
  quantity,
24129
24147
  style: titleStyle,
24130
24148
  showBottomBorder: true,
@@ -28263,20 +28281,20 @@ async function openRealTimeTelemetryModal(params) {
28263
28281
  }
28264
28282
  const todayStr = (/* @__PURE__ */ new Date()).toLocaleDateString(locale, { day: "2-digit", month: "2-digit", year: "numeric" });
28265
28283
  const dateHtml = `<span style="margin-left:8px;font-size:13px;font-weight:400;opacity:0.55;">(${todayStr})</span>`;
28266
- const icon = (glyph, title) => `<span title="${title}" style="margin-left:8px;cursor:default;font-size:16px;vertical-align:middle;">${glyph}</span>`;
28284
+ const icon2 = (glyph, title) => `<span title="${title}" style="margin-left:8px;cursor:default;font-size:16px;vertical-align:middle;">${glyph}</span>`;
28267
28285
  let iconHtml;
28268
28286
  if (!hasTelemetryToday()) {
28269
- iconHtml = icon("\u274C", "Sem telemetrias de hoje para este dispositivo");
28287
+ iconHtml = icon2("\u274C", "Sem telemetrias de hoje para este dispositivo");
28270
28288
  } else if (centralStatus === "offline") {
28271
- iconHtml = icon("\u{1F534}", `Central offline (${STATUS_MAX_RETRIES} falhas seguidas)`);
28289
+ iconHtml = icon2("\u{1F534}", `Central offline (${STATUS_MAX_RETRIES} falhas seguidas)`);
28272
28290
  } else if (deviceStatus === "offline") {
28273
- iconHtml = icon("\u{1F534}", `Dispositivo offline (${STATUS_MAX_RETRIES} verifica\xE7\xF5es seguidas sem telemetria recente)`);
28291
+ iconHtml = icon2("\u{1F534}", `Dispositivo offline (${STATUS_MAX_RETRIES} verifica\xE7\xF5es seguidas sem telemetria recente)`);
28274
28292
  } else if (centralStatus === "warning") {
28275
- iconHtml = icon("\u26A0\uFE0F", `Aten\xE7\xE3o: central sem resposta (tentativa ${centralFailStreak}/${STATUS_MAX_RETRIES})`);
28293
+ iconHtml = icon2("\u26A0\uFE0F", `Aten\xE7\xE3o: central sem resposta (tentativa ${centralFailStreak}/${STATUS_MAX_RETRIES})`);
28276
28294
  } else if (deviceStatus === "warning") {
28277
- iconHtml = icon("\u26A0\uFE0F", `Aten\xE7\xE3o: ${deviceStaleLabel()} (verifica\xE7\xE3o ${deviceStaleStreak}/${STATUS_MAX_RETRIES})`);
28295
+ iconHtml = icon2("\u26A0\uFE0F", `Aten\xE7\xE3o: ${deviceStaleLabel()} (verifica\xE7\xE3o ${deviceStaleStreak}/${STATUS_MAX_RETRIES})`);
28278
28296
  } else {
28279
- iconHtml = icon("\u2705", "H\xE1 telemetrias de hoje e o dispositivo est\xE1 respondendo");
28297
+ iconHtml = icon2("\u2705", "H\xE1 telemetrias de hoje e o dispositivo est\xE1 respondendo");
28280
28298
  }
28281
28299
  chartTitleEl.innerHTML = `Telemetria em Tempo Real de hoje${dateHtml}${iconHtml}`;
28282
28300
  }
@@ -28647,7 +28665,7 @@ async function openRealTimeTelemetryModal(params) {
28647
28665
  }
28648
28666
  injectCardTooltipStyles();
28649
28667
  const ok = checkDeviceHistory.filter((r) => r.status === "ok").length;
28650
- const fail = checkDeviceHistory.filter((r) => r.status === "offline").length;
28668
+ const fail2 = checkDeviceHistory.filter((r) => r.status === "offline").length;
28651
28669
  const total = checkDeviceHistory.length;
28652
28670
  const firstTs = checkDeviceHistory[0]?.ts;
28653
28671
  const uptimeLabel = firstTs ? (() => {
@@ -28666,10 +28684,10 @@ async function openRealTimeTelemetryModal(params) {
28666
28684
  minute: "2-digit",
28667
28685
  second: "2-digit"
28668
28686
  });
28669
- const icon = r.status === "ok" ? "\u2705" : "\u274C";
28670
- return `<div class="rtt-tt-history-row">${icon} ${dt}</div>`;
28687
+ const icon2 = r.status === "ok" ? "\u2705" : "\u274C";
28688
+ return `<div class="rtt-tt-history-row">${icon2} ${dt}</div>`;
28671
28689
  }).join("");
28672
- const failBlock = fail > 0 ? `<div style="margin-top:8px;padding:6px 8px;background:#fff5f5;border-radius:6px;font-size:11px;color:#e74c3c;">\u26A0\uFE0F ${fail} falha${fail > 1 ? "s" : ""} registrada${fail > 1 ? "s" : ""}</div>` : "";
28690
+ const failBlock = fail2 > 0 ? `<div style="margin-top:8px;padding:6px 8px;background:#fff5f5;border-radius:6px;font-size:11px;color:#e74c3c;">\u26A0\uFE0F ${fail2} falha${fail2 > 1 ? "s" : ""} registrada${fail2 > 1 ? "s" : ""}</div>` : "";
28673
28691
  const tooltip = document.createElement("div");
28674
28692
  tooltip.id = "rtt-status-tooltip";
28675
28693
  if (currentTheme === "dark") tooltip.dataset["theme"] = "dark";
@@ -28689,7 +28707,7 @@ async function openRealTimeTelemetryModal(params) {
28689
28707
  ${centralId ? `<div style="font-family:ui-monospace,monospace;background:#f1f5f9;border-radius:5px;padding:3px 8px;font-size:11px;color:#475569;">\u{1F511} Central ID: <b>${centralId}</b></div>` : ""}
28690
28708
  <div style="font-size:12px;">\u{1F4E1} <b>${ok}</b> chamadas com sucesso${total > 0 ? ` de ${total}` : ""}</div>
28691
28709
  <div style="font-size:12px;">\u23F1\uFE0F Monitorando h\xE1: <b>${uptimeLabel}</b></div>
28692
- ${fail > 0 ? `<div style="font-size:12px;color:#e74c3c;">\u274C <b>${fail}</b> falha${fail > 1 ? "s" : ""}</div>` : ""}
28710
+ ${fail2 > 0 ? `<div style="font-size:12px;color:#e74c3c;">\u274C <b>${fail2}</b> falha${fail2 > 1 ? "s" : ""}</div>` : ""}
28693
28711
  </div>
28694
28712
  ${failBlock}
28695
28713
  </div>
@@ -28739,9 +28757,9 @@ async function openRealTimeTelemetryModal(params) {
28739
28757
  minute: "2-digit",
28740
28758
  second: "2-digit"
28741
28759
  }) : "--";
28742
- function row(icon, label, value) {
28760
+ function row(icon2, label, value) {
28743
28761
  return `<div style="display:flex;flex-direction:column;gap:1px;padding:5px 0;border-bottom:1px solid #f3f4f6;">
28744
- <span style="font-size:10px;color:#9ca3af;font-weight:500;">${icon} ${label}</span>
28762
+ <span style="font-size:10px;color:#9ca3af;font-weight:500;">${icon2} ${label}</span>
28745
28763
  <span style="font-family:monospace;font-size:12px;color:#1f2937;font-weight:600;word-break:break-all;">${value || "\u2014"}</span>
28746
28764
  </div>`;
28747
28765
  }
@@ -29189,11 +29207,11 @@ async function openRealTimeTelemetryModal(params) {
29189
29207
  function showCoverageNotice(text2, resume) {
29190
29208
  if (!coverageNoticeEl) return;
29191
29209
  coverageNoticeEl.textContent = "";
29192
- const icon = document.createElement("span");
29193
- icon.textContent = "\u26A0\uFE0F ";
29210
+ const icon2 = document.createElement("span");
29211
+ icon2.textContent = "\u26A0\uFE0F ";
29194
29212
  const msg = document.createElement("span");
29195
29213
  msg.textContent = text2;
29196
- coverageNoticeEl.append(icon, msg);
29214
+ coverageNoticeEl.append(icon2, msg);
29197
29215
  coverageResume = resume ? { startISO: resume.startISO, endISO: resume.endISO } : null;
29198
29216
  if (resume) {
29199
29217
  const link = document.createElement("a");
@@ -29738,8 +29756,8 @@ async function openRealTimeTelemetryModal(params) {
29738
29756
  if (!chart) return;
29739
29757
  chart.options.responsive = false;
29740
29758
  const w = chartContainer.clientWidth - 40;
29741
- const h2 = chartContainer.clientHeight - 60;
29742
- chart.resize(Math.max(w, 200), Math.max(h2, 120));
29759
+ const h3 = chartContainer.clientHeight - 60;
29760
+ chart.resize(Math.max(w, 200), Math.max(h3, 120));
29743
29761
  })
29744
29762
  );
29745
29763
  }
@@ -29885,8 +29903,8 @@ async function openRealTimeTelemetryModal(params) {
29885
29903
  URL.revokeObjectURL(url);
29886
29904
  }
29887
29905
  function ensureRoom2(doc, nextY, minRoom = 12) {
29888
- const h2 = doc.internal.pageSize.getHeight();
29889
- if (nextY + minRoom > h2 - 15) {
29906
+ const h3 = doc.internal.pageSize.getHeight();
29907
+ if (nextY + minRoom > h3 - 15) {
29890
29908
  doc.addPage();
29891
29909
  return 20;
29892
29910
  }
@@ -29985,8 +30003,8 @@ async function openRealTimeTelemetryModal(params) {
29985
30003
  if (isExpanded) {
29986
30004
  chart.options.responsive = false;
29987
30005
  const w = chartContainer.clientWidth - 40;
29988
- const h2 = chartContainer.clientHeight - 60;
29989
- chart.resize(Math.max(w, 200), Math.max(h2, 120));
30006
+ const h3 = chartContainer.clientHeight - 60;
30007
+ chart.resize(Math.max(w, 200), Math.max(h3, 120));
29990
30008
  } else {
29991
30009
  chart.options.responsive = true;
29992
30010
  chartCanvas.style.height = "";
@@ -30774,10 +30792,10 @@ var BASControlPanel = class {
30774
30792
  }
30775
30793
  return items.join("");
30776
30794
  }
30777
- renderTelemetryItem(label, value, unit, icon) {
30795
+ renderTelemetryItem(label, value, unit, icon2) {
30778
30796
  return `
30779
30797
  <div class="myio-bas-telemetry-item">
30780
- <span class="myio-bas-telemetry-icon">${icon}</span>
30798
+ <span class="myio-bas-telemetry-icon">${icon2}</span>
30781
30799
  <div class="myio-bas-telemetry-content">
30782
30800
  <span class="myio-bas-telemetry-label">${label}</span>
30783
30801
  <span class="myio-bas-telemetry-value">${value} <span class="myio-bas-telemetry-unit">${unit}</span></span>
@@ -34143,20 +34161,20 @@ function mixHex(a, b, ratio) {
34143
34161
  };
34144
34162
  return `#${mix(0)}${mix(2)}${mix(4)}`;
34145
34163
  }
34146
- function hslToHex(h2, s, l) {
34164
+ function hslToHex(h3, s, l) {
34147
34165
  const sat = s / 100;
34148
34166
  const lig = l / 100;
34149
- const k = (n) => (n + h2 / 30) % 12;
34167
+ const k = (n) => (n + h3 / 30) % 12;
34150
34168
  const a = sat * Math.min(lig, 1 - lig);
34151
34169
  const f = (n) => lig - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
34152
34170
  const to = (v) => Math.round(v * 255).toString(16).padStart(2, "0");
34153
34171
  return `#${to(f(0))}${to(f(8))}${to(f(4))}`;
34154
34172
  }
34155
34173
  function hashColor(label, dark) {
34156
- let h2 = 5381;
34157
- for (let i = 0; i < label.length; i++) h2 = (h2 << 5) + h2 + label.charCodeAt(i) | 0;
34158
- const hue = Math.abs(h2) % 360;
34159
- const sat = 55 + Math.abs(h2 >> 8) % 25;
34174
+ let h3 = 5381;
34175
+ for (let i = 0; i < label.length; i++) h3 = (h3 << 5) + h3 + label.charCodeAt(i) | 0;
34176
+ const hue = Math.abs(h3) % 360;
34177
+ const sat = 55 + Math.abs(h3 >> 8) % 25;
34160
34178
  return hslToHex(hue, sat, dark ? 58 : 44);
34161
34179
  }
34162
34180
  function paletteColor(base, index, dark) {
@@ -34365,11 +34383,11 @@ function createParticipationChart(container, params) {
34365
34383
  ].join(" ");
34366
34384
  }
34367
34385
  function buildPieSvg2(entries, total) {
34368
- const svg = document.createElementNS(SVG_NS, "svg");
34386
+ const svg2 = document.createElementNS(SVG_NS, "svg");
34369
34387
  const SIZE = 300;
34370
- svg.setAttribute("viewBox", `0 0 ${SIZE} ${SIZE}`);
34371
- svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
34372
- svg.setAttribute("role", "img");
34388
+ svg2.setAttribute("viewBox", `0 0 ${SIZE} ${SIZE}`);
34389
+ svg2.setAttribute("preserveAspectRatio", "xMidYMid meet");
34390
+ svg2.setAttribute("role", "img");
34373
34391
  const cx = SIZE / 2;
34374
34392
  const cy = SIZE / 2;
34375
34393
  const ro = 128;
@@ -34401,7 +34419,7 @@ function createParticipationChart(container, params) {
34401
34419
  path.addEventListener("mouseleave", () => {
34402
34420
  path.style.transform = "";
34403
34421
  });
34404
- svg.appendChild(path);
34422
+ svg2.appendChild(path);
34405
34423
  attachItemTooltip(path, item, pct);
34406
34424
  if (pct >= 8) {
34407
34425
  const rl = (ro + ri) / 2;
@@ -34418,10 +34436,10 @@ function createParticipationChart(container, params) {
34418
34436
  text2.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
34419
34437
  text2.setAttribute("pointer-events", "none");
34420
34438
  text2.textContent = fmtPct(pct);
34421
- svg.appendChild(text2);
34439
+ svg2.appendChild(text2);
34422
34440
  }
34423
34441
  });
34424
- return svg;
34442
+ return svg2;
34425
34443
  }
34426
34444
  function buildBarsSvg(entries, total) {
34427
34445
  const sorted = [...entries].sort((a, b) => b.item.value - a.item.value);
@@ -34433,10 +34451,10 @@ function createParticipationChart(container, params) {
34433
34451
  const maxValue = sorted.reduce((m, e) => Math.max(m, e.item.value), 0);
34434
34452
  const textColor = resolvedText();
34435
34453
  const mutedColor = resolvedMuted();
34436
- const svg = document.createElementNS(SVG_NS, "svg");
34437
- svg.setAttribute("viewBox", `0 0 ${W} ${H}`);
34438
- svg.setAttribute("preserveAspectRatio", "xMidYMin meet");
34439
- svg.setAttribute("role", "img");
34454
+ const svg2 = document.createElementNS(SVG_NS, "svg");
34455
+ svg2.setAttribute("viewBox", `0 0 ${W} ${H}`);
34456
+ svg2.setAttribute("preserveAspectRatio", "xMidYMin meet");
34457
+ svg2.setAttribute("role", "img");
34440
34458
  sorted.forEach(({ item, color }, row) => {
34441
34459
  const pct = total > 0 ? item.value / total * 100 : 0;
34442
34460
  const y = row * ROW_H + 4;
@@ -34450,7 +34468,7 @@ function createParticipationChart(container, params) {
34450
34468
  label.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
34451
34469
  const raw = item.label || "";
34452
34470
  label.textContent = raw.length > 18 ? `${raw.slice(0, 17)}\u2026` : raw;
34453
- svg.appendChild(label);
34471
+ svg2.appendChild(label);
34454
34472
  const rect = document.createElementNS(SVG_NS, "rect");
34455
34473
  rect.setAttribute("x", String(LABEL_W));
34456
34474
  rect.setAttribute("y", String(y + 3));
@@ -34460,7 +34478,7 @@ function createParticipationChart(container, params) {
34460
34478
  rect.setAttribute("fill", color);
34461
34479
  rect.setAttribute("class", `${PARTICIPATION_CHART_CSS_PREFIX}__bar-rect`);
34462
34480
  rect.setAttribute("data-key", keyOf(item));
34463
- svg.appendChild(rect);
34481
+ svg2.appendChild(rect);
34464
34482
  attachItemTooltip(rect, item, pct);
34465
34483
  const value = document.createElementNS(SVG_NS, "text");
34466
34484
  value.setAttribute("x", String(LABEL_W + barW + 6));
@@ -34470,9 +34488,9 @@ function createParticipationChart(container, params) {
34470
34488
  value.setAttribute("font-size", "10.5");
34471
34489
  value.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
34472
34490
  value.textContent = `${settings.formatValue(item.value)}${settings.unit ? ` ${settings.unit}` : ""} \xB7 ${fmtPct(pct)}`;
34473
- svg.appendChild(value);
34491
+ svg2.appendChild(value);
34474
34492
  });
34475
- return svg;
34493
+ return svg2;
34476
34494
  }
34477
34495
  function buildLegend2(total) {
34478
34496
  const legend = document.createElement("div");
@@ -34538,15 +34556,15 @@ function createParticipationChart(container, params) {
34538
34556
  root.appendChild(body);
34539
34557
  }
34540
34558
  async function svgToPng(scale = 2) {
34541
- const svg = root.querySelector("svg");
34542
- if (!svg) {
34559
+ const svg2 = root.querySelector("svg");
34560
+ if (!svg2) {
34543
34561
  console.warn("[ParticipationChart] Nada para exportar \u2014 gr\xE1fico vazio.");
34544
34562
  return null;
34545
34563
  }
34546
- const vb = svg.viewBox.baseVal;
34564
+ const vb = svg2.viewBox.baseVal;
34547
34565
  const width = vb && vb.width ? vb.width : 300;
34548
34566
  const height = vb && vb.height ? vb.height : 300;
34549
- const clone = svg.cloneNode(true);
34567
+ const clone = svg2.cloneNode(true);
34550
34568
  clone.setAttribute("xmlns", SVG_NS);
34551
34569
  clone.setAttribute("width", String(width));
34552
34570
  clone.setAttribute("height", String(height));
@@ -34882,14 +34900,14 @@ function createExportButton(kind, container, params = {}) {
34882
34900
  const label = settings.label ?? defaultLabel;
34883
34901
  const locked = !!settings.locked;
34884
34902
  const disabled = locked || !!settings.disabled;
34885
- const icon = locked ? LOCK_ICON : settings.icon ?? defaultIcon;
34903
+ const icon2 = locked ? LOCK_ICON : settings.icon ?? defaultIcon;
34886
34904
  btn.className = `${EXPORT_BUTTON_CSS_PREFIX}${locked ? ` ${EXPORT_BUTTON_CSS_PREFIX}--locked` : ""}`;
34887
34905
  btn.disabled = disabled;
34888
34906
  btn.style.borderColor = colors2.border;
34889
34907
  btn.style.color = colors2.text;
34890
34908
  btn.style.background = colors2.bg;
34891
34909
  btn.setAttribute("aria-label", label);
34892
- btn.innerHTML = `${icon ? `<span class="${EXPORT_BUTTON_CSS_PREFIX}__icon">${icon}</span>` : ""}${label}`;
34910
+ btn.innerHTML = `${icon2 ? `<span class="${EXPORT_BUTTON_CSS_PREFIX}__icon">${icon2}</span>` : ""}${label}`;
34893
34911
  tooltipCleanup?.();
34894
34912
  tooltipCleanup = null;
34895
34913
  const tt = settings.tooltip;
@@ -40813,11 +40831,11 @@ var PowerLimitsModalView = class {
40813
40831
  const statusKey = status === "standby" ? "standBy" : status;
40814
40832
  const config2 = STATUS_CONFIG[statusKey];
40815
40833
  const formValues = this.formData[status];
40816
- const icon = domainIcons[statusKey];
40834
+ const icon2 = domainIcons[statusKey];
40817
40835
  return `
40818
40836
  <div class="myio-power-limits-card-item myio-status-${status}" style="--status-color: ${config2.color}; --status-bg: ${config2.bgColor};">
40819
40837
  <div class="myio-card-header">
40820
- <span class="myio-status-icon">${icon}</span>
40838
+ <span class="myio-status-icon">${icon2}</span>
40821
40839
  <span class="myio-status-indicator"></span>
40822
40840
  <span class="myio-status-label">${config2.label}</span>
40823
40841
  </div>
@@ -48317,7 +48335,7 @@ var AnnotationsTab = class {
48317
48335
  const isReject = type === "rejected";
48318
48336
  const isComment = type === "comment";
48319
48337
  let title;
48320
- let icon;
48338
+ let icon2;
48321
48339
  let headerClass;
48322
48340
  let btnClass;
48323
48341
  let labelText;
@@ -48327,7 +48345,7 @@ var AnnotationsTab = class {
48327
48345
  let isRequired;
48328
48346
  if (isApprove) {
48329
48347
  title = "Aprovar Anota\xE7\xE3o";
48330
- icon = "\u2713";
48348
+ icon2 = "\u2713";
48331
48349
  headerClass = "response-modal__header--approve";
48332
48350
  btnClass = "response-modal__btn--approve";
48333
48351
  labelText = "Observa\xE7\xE3o (opcional)";
@@ -48337,7 +48355,7 @@ var AnnotationsTab = class {
48337
48355
  isRequired = false;
48338
48356
  } else if (isReject) {
48339
48357
  title = "Rejeitar Anota\xE7\xE3o";
48340
- icon = "\u2717";
48358
+ icon2 = "\u2717";
48341
48359
  headerClass = "response-modal__header--reject";
48342
48360
  btnClass = "response-modal__btn--reject";
48343
48361
  labelText = "Justificativa";
@@ -48347,7 +48365,7 @@ var AnnotationsTab = class {
48347
48365
  isRequired = true;
48348
48366
  } else if (isComment) {
48349
48367
  title = "Adicionar Coment\xE1rio";
48350
- icon = "\u{1F4AC}";
48368
+ icon2 = "\u{1F4AC}";
48351
48369
  headerClass = "response-modal__header--comment";
48352
48370
  btnClass = "response-modal__btn--comment";
48353
48371
  labelText = "Coment\xE1rio";
@@ -48357,7 +48375,7 @@ var AnnotationsTab = class {
48357
48375
  isRequired = true;
48358
48376
  } else {
48359
48377
  title = "Arquivar Anota\xE7\xE3o";
48360
- icon = "\u2B07\uFE0F";
48378
+ icon2 = "\u2B07\uFE0F";
48361
48379
  headerClass = "response-modal__header--archive";
48362
48380
  btnClass = "response-modal__btn--archive-modal";
48363
48381
  labelText = "Justificativa";
@@ -48371,7 +48389,7 @@ var AnnotationsTab = class {
48371
48389
  overlay.innerHTML = `
48372
48390
  <div class="response-modal">
48373
48391
  <div class="response-modal__header ${headerClass}">
48374
- <span class="response-modal__icon">${icon}</span>
48392
+ <span class="response-modal__icon">${icon2}</span>
48375
48393
  <span class="response-modal__title">${title}</span>
48376
48394
  </div>
48377
48395
  <div class="response-modal__body">
@@ -50627,9 +50645,9 @@ var AnnotationsTab = class {
50627
50645
  ` : ""}
50628
50646
  <div class="annotation-detail__history">
50629
50647
  <div class="annotation-detail__history-title">Hist\xF3rico (${annotation.history.length + (annotation.responses?.length || 0)} eventos)</div>
50630
- ${annotation.history.map((h2) => `
50648
+ ${annotation.history.map((h3) => `
50631
50649
  <div class="annotation-detail__history-item">
50632
- <strong>${h2.action}</strong> por ${h2.userName} em ${this.formatDate(h2.timestamp)}
50650
+ <strong>${h3.action}</strong> por ${h3.userName} em ${this.formatDate(h3.timestamp)}
50633
50651
  </div>
50634
50652
  `).join("")}
50635
50653
  ${(annotation.responses || []).map((r) => `
@@ -51850,9 +51868,9 @@ function seededRand(seed) {
51850
51868
  };
51851
51869
  }
51852
51870
  function hashStr(s) {
51853
- let h2 = 0;
51854
- for (let i = 0; i < s.length; i++) h2 = Math.imul(31, h2) + s.charCodeAt(i) | 0;
51855
- return Math.abs(h2);
51871
+ let h3 = 0;
51872
+ for (let i = 0; i < s.length; i++) h3 = Math.imul(31, h3) + s.charCodeAt(i) | 0;
51873
+ return Math.abs(h3);
51856
51874
  }
51857
51875
  function generateBuckets(alarm, devices, period = "mes") {
51858
51876
  const count = alarm.occurrenceCount || 1;
@@ -51937,11 +51955,11 @@ function generateDowDistribution(alarm) {
51937
51955
  function generateHodDistribution(alarm) {
51938
51956
  const count = alarm.occurrenceCount || 1;
51939
51957
  const rand = seededRand(hashStr(alarm.id + "hod"));
51940
- const weights = Array.from({ length: 24 }, (_, h2) => {
51941
- if (h2 < 6) return 0.05 + rand() * 0.05;
51942
- if (h2 < 10) return 0.3 + rand() * 0.3;
51943
- if (h2 <= 19) return 0.7 + rand() * 0.6;
51944
- if (h2 <= 22) return 0.3 + rand() * 0.3;
51958
+ const weights = Array.from({ length: 24 }, (_, h3) => {
51959
+ if (h3 < 6) return 0.05 + rand() * 0.05;
51960
+ if (h3 < 10) return 0.3 + rand() * 0.3;
51961
+ if (h3 <= 19) return 0.7 + rand() * 0.6;
51962
+ if (h3 <= 22) return 0.3 + rand() * 0.3;
51945
51963
  return 0.05 + rand() * 0.05;
51946
51964
  });
51947
51965
  const wSum = weights.reduce((a, b) => a + b, 0);
@@ -52074,7 +52092,7 @@ function createHodChart(canvas, vals) {
52074
52092
  return new Chart2(canvas, {
52075
52093
  type: "bar",
52076
52094
  data: {
52077
- labels: Array.from({ length: 24 }, (_, h2) => `${h2}h`),
52095
+ labels: Array.from({ length: 24 }, (_, h3) => `${h3}h`),
52078
52096
  datasets: [{
52079
52097
  label: "Ocorr\xEAncias",
52080
52098
  data: vals,
@@ -60562,12 +60580,12 @@ var TicketsTab = class {
60562
60580
  const container = this.config.container;
60563
60581
  const toggle = container.querySelector("#ct-new-ticket-toggle");
60564
60582
  const body = container.querySelector("#ct-new-ticket-body");
60565
- const icon = container.querySelector("#ct-collapse-icon");
60583
+ const icon2 = container.querySelector("#ct-collapse-icon");
60566
60584
  if (toggle && body) {
60567
60585
  toggle.addEventListener("click", () => {
60568
60586
  const isOpen = body.style.display !== "none";
60569
60587
  body.style.display = isOpen ? "none" : "block";
60570
- if (icon) icon.textContent = isOpen ? "\u25BC" : "\u25B2";
60588
+ if (icon2) icon2.textContent = isOpen ? "\u25BC" : "\u25B2";
60571
60589
  });
60572
60590
  }
60573
60591
  if (this.config.requesterEmail) {
@@ -60779,13 +60797,13 @@ ${description}` : description;
60779
60797
  return;
60780
60798
  }
60781
60799
  area.innerHTML = this._selectedFiles.map((f, i) => {
60782
- const icon = this._getFileIcon(f);
60800
+ const icon2 = this._getFileIcon(f);
60783
60801
  const isImage = f.type.startsWith("image/");
60784
60802
  const tooltip = `${f.name}
60785
60803
  ${this._formatFileSize(f.size)} \xB7 ${f.type || "arquivo"}`;
60786
60804
  return `
60787
60805
  <div class="ct-file-chip" data-index="${i}" title="${this.esc(tooltip)}">
60788
- ${isImage ? `<img class="ct-file-thumb" src="${URL.createObjectURL(f)}" alt="${this.esc(f.name)}">` : `<span class="ct-file-icon">${icon}</span>`}
60806
+ ${isImage ? `<img class="ct-file-thumb" src="${URL.createObjectURL(f)}" alt="${this.esc(f.name)}">` : `<span class="ct-file-icon">${icon2}</span>`}
60789
60807
  <span class="ct-file-name">${this.esc(f.name.length > 18 ? f.name.slice(0, 16) + "\u2026" : f.name)}</span>
60790
60808
  <span class="ct-file-size">${this._formatFileSize(f.size)}</span>
60791
60809
  <button type="button" class="ct-file-remove" data-index="${i}" title="Remover">\u2715</button>
@@ -62448,11 +62466,11 @@ var SettingsModalView = class _SettingsModalView {
62448
62466
  formatUptime(seconds) {
62449
62467
  if (seconds == null || Number.isNaN(seconds)) return "\u2014";
62450
62468
  const d = Math.floor(seconds / 86400);
62451
- const h2 = Math.floor(seconds % 86400 / 3600);
62469
+ const h3 = Math.floor(seconds % 86400 / 3600);
62452
62470
  const m = Math.floor(seconds % 3600 / 60);
62453
62471
  const parts = [];
62454
62472
  if (d > 0) parts.push(`${d}d`);
62455
- if (h2 > 0 || d > 0) parts.push(`${h2}h`);
62473
+ if (h3 > 0 || d > 0) parts.push(`${h3}h`);
62456
62474
  parts.push(`${m}min`);
62457
62475
  return parts.join(" ");
62458
62476
  }
@@ -65551,11 +65569,11 @@ function formatIsoRelativeSimple(iso) {
65551
65569
  function formatUptime(seconds) {
65552
65570
  if (seconds == null || Number.isNaN(seconds)) return "\u2014";
65553
65571
  const d = Math.floor(seconds / 86400);
65554
- const h2 = Math.floor(seconds % 86400 / 3600);
65572
+ const h3 = Math.floor(seconds % 86400 / 3600);
65555
65573
  const m = Math.floor(seconds % 3600 / 60);
65556
65574
  const parts = [];
65557
65575
  if (d > 0) parts.push(`${d}d`);
65558
- if (h2 > 0 || d > 0) parts.push(`${h2}h`);
65576
+ if (h3 > 0 || d > 0) parts.push(`${h3}h`);
65559
65577
  parts.push(`${m}min`);
65560
65578
  return parts.join(" ");
65561
65579
  }
@@ -68610,7 +68628,7 @@ var WelcomeModalView = class _WelcomeModalView {
68610
68628
  const meta = card.metaCounts || {};
68611
68629
  const details = card.metaDetails || {};
68612
68630
  const loadingBody = '<div style="opacity:.7;padding:6px 0">Carregando\u2026</div>';
68613
- const header = (icon, label, count) => `<div style="font-weight:800;font-size:13px;margin-bottom:8px">${icon} ${label}${count === null || count === void 0 ? "" : ` (${count})`} \u2014 ${esc8(card.title)}</div>`;
68631
+ const header = (icon2, label, count) => `<div style="font-weight:800;font-size:13px;margin-bottom:8px">${icon2} ${label}${count === null || count === void 0 ? "" : ` (${count})`} \u2014 ${esc8(card.title)}</div>`;
68614
68632
  const row = (titleHtml, subHtml) => `<div style="padding:6px 0;border-top:1px solid #334155">
68615
68633
  <div style="font-weight:600">${titleHtml}</div>
68616
68634
  ${subHtml ? `<div style="opacity:.7">${subHtml}</div>` : ""}
@@ -69295,15 +69313,15 @@ var WelcomeModalView = class _WelcomeModalView {
69295
69313
  if (svgIcon) {
69296
69314
  ctaBtn.appendChild(svgIcon);
69297
69315
  } else {
69298
- const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
69299
- svg.setAttribute("viewBox", "0 0 24 24");
69300
- svg.setAttribute("fill", "none");
69301
- svg.setAttribute("stroke", "currentColor");
69302
- svg.setAttribute("stroke-width", "2");
69303
- svg.setAttribute("stroke-linecap", "round");
69304
- svg.setAttribute("stroke-linejoin", "round");
69305
- svg.innerHTML = '<line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" />';
69306
- ctaBtn.appendChild(svg);
69316
+ const svg2 = document.createElementNS("http://www.w3.org/2000/svg", "svg");
69317
+ svg2.setAttribute("viewBox", "0 0 24 24");
69318
+ svg2.setAttribute("fill", "none");
69319
+ svg2.setAttribute("stroke", "currentColor");
69320
+ svg2.setAttribute("stroke-width", "2");
69321
+ svg2.setAttribute("stroke-linecap", "round");
69322
+ svg2.setAttribute("stroke-linejoin", "round");
69323
+ svg2.innerHTML = '<line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" />';
69324
+ ctaBtn.appendChild(svg2);
69307
69325
  }
69308
69326
  }
69309
69327
  }
@@ -71164,10 +71182,10 @@ function createHeaderComponent(params) {
71164
71182
  const categoriesHtml = categories.map((c) => {
71165
71183
  const name = String(c?.name ?? c?.label ?? "Categoria");
71166
71184
  const deviceCount = Number(c?.deviceCount ?? c?.count ?? 0);
71167
- const icon = String(c?.icon ?? "");
71185
+ const icon2 = String(c?.icon ?? "");
71168
71186
  return `
71169
71187
  <div class="myio-info-tooltip__row" style="padding: 6px 0; gap: 8px;">
71170
- <span class="myio-info-tooltip__label">${icon ? `${icon} ` : ""}${name}</span>
71188
+ <span class="myio-info-tooltip__label">${icon2 ? `${icon2} ` : ""}${name}</span>
71171
71189
  <span class="myio-info-tooltip__value myio-info-tooltip__value--highlight">${deviceCount}</span>
71172
71190
  </div>
71173
71191
  `;
@@ -72465,11 +72483,11 @@ function createOverlay() {
72465
72483
  overlay.style.setProperty("--fc-primary-hover", colors.primaryHover);
72466
72484
  return overlay;
72467
72485
  }
72468
- function createAlertBox(icon, title, message, buttonLabel) {
72486
+ function createAlertBox(icon2, title, message, buttonLabel) {
72469
72487
  const box = document.createElement("div");
72470
72488
  box.className = "myio-footer-alert-box";
72471
72489
  box.innerHTML = `
72472
- <div class="myio-footer-alert-icon">${icon}</div>
72490
+ <div class="myio-footer-alert-icon">${icon2}</div>
72473
72491
  <h2 class="myio-footer-alert-title">${title}</h2>
72474
72492
  <p class="myio-footer-alert-message">${message}</p>
72475
72493
  <button class="myio-footer-alert-button" type="button">${buttonLabel}</button>
@@ -75889,8 +75907,8 @@ function addCanvasToPdf(doc, canvas, x = 10, y = 20, maxWmm = 190) {
75889
75907
  return y + mmH;
75890
75908
  }
75891
75909
  function ensureRoom(doc, nextY, minRoom = 40) {
75892
- const h2 = doc.internal.pageSize.getHeight();
75893
- if (nextY + minRoom > h2) {
75910
+ const h3 = doc.internal.pageSize.getHeight();
75911
+ if (nextY + minRoom > h3) {
75894
75912
  doc.addPage();
75895
75913
  return 20;
75896
75914
  }
@@ -77647,9 +77665,9 @@ function openGoalsPanel(params) {
77647
77665
  };
77648
77666
  const onWriteFailure = (res) => {
77649
77667
  state6.saving = false;
77650
- const conflict = readVersionConflict(res);
77651
- if (conflict !== null) {
77652
- state6.conflictVersion = conflict;
77668
+ const conflict2 = readVersionConflict(res);
77669
+ if (conflict2 !== null) {
77670
+ state6.conflictVersion = conflict2;
77653
77671
  state6.conflict = true;
77654
77672
  state6.pendingReapply = dirtySnapshot;
77655
77673
  reload();
@@ -77715,9 +77733,9 @@ function openGoalsPanel(params) {
77715
77733
  reload();
77716
77734
  return;
77717
77735
  }
77718
- const conflict = readVersionConflict(res);
77719
- if (conflict !== null) {
77720
- state6.conflictVersion = conflict;
77736
+ const conflict2 = readVersionConflict(res);
77737
+ if (conflict2 !== null) {
77738
+ state6.conflictVersion = conflict2;
77721
77739
  state6.conflict = true;
77722
77740
  reload();
77723
77741
  } else {
@@ -77739,9 +77757,9 @@ function openGoalsPanel(params) {
77739
77757
  reload();
77740
77758
  return;
77741
77759
  }
77742
- const conflict = readVersionConflict(res);
77743
- if (conflict !== null) {
77744
- state6.conflictVersion = conflict;
77760
+ const conflict2 = readVersionConflict(res);
77761
+ if (conflict2 !== null) {
77762
+ state6.conflictVersion = conflict2;
77745
77763
  state6.conflict = true;
77746
77764
  reload();
77747
77765
  } else {
@@ -77767,7 +77785,7 @@ function openGoalsPanel(params) {
77767
77785
  const value = sampleHourValue();
77768
77786
  const day = `${state6.year}-03-15`;
77769
77787
  const lines = ["bucket,value"];
77770
- for (let h2 = 0; h2 < 24; h2++) lines.push(`${day}T${pad2(h2)},${value}`);
77788
+ for (let h3 = 0; h3 < 24; h3++) lines.push(`${day}T${pad2(h3)},${value}`);
77771
77789
  return lines.join("\n");
77772
77790
  }
77773
77791
  function downloadCsv(csv, suffix) {
@@ -77821,8 +77839,8 @@ function openGoalsPanel(params) {
77821
77839
  state6.importApplied = res.data;
77822
77840
  reload();
77823
77841
  } else {
77824
- const conflict = readVersionConflict(res);
77825
- if (conflict !== null) state6.conflictVersion = conflict;
77842
+ const conflict2 = readVersionConflict(res);
77843
+ if (conflict2 !== null) state6.conflictVersion = conflict2;
77826
77844
  else state6.saveError = res.error && res.error.message || "Failed to apply import";
77827
77845
  }
77828
77846
  renderImportBody();
@@ -78034,19 +78052,19 @@ function openGoalsPanel(params) {
78034
78052
  if (!yearOptions.includes(state6.year)) yearOptions.unshift(state6.year);
78035
78053
  const actions = state6.editing ? `
78036
78054
  <button class="myio-goals-btn myio-goals-btn-outline" data-action="open-import" ${state6.loading || state6.error ? "disabled" : ""}>
78037
- ${icon("upload")} ${i18n2.importBtn}
78055
+ ${icon2("upload")} ${i18n2.importBtn}
78038
78056
  </button>
78039
78057
  <button class="myio-goals-btn myio-goals-btn-outline" data-action="view-summary" ${state6.loading ? "disabled" : ""}>
78040
- ${icon("eye")} ${i18n2.viewSummary}
78058
+ ${icon2("eye")} ${i18n2.viewSummary}
78041
78059
  </button>
78042
78060
  <button class="myio-goals-btn myio-goals-btn-primary" data-action="save" ${state6.loading || state6.error || state6.saving ? "disabled" : ""}>
78043
- ${icon("save")} ${state6.saving ? i18n2.saving : i18n2.save}
78061
+ ${icon2("save")} ${state6.saving ? i18n2.saving : i18n2.save}
78044
78062
  </button>` : `
78045
78063
  <button class="myio-goals-btn myio-goals-btn-outline" data-action="download-hourly" ${state6.loading ? "disabled" : ""}>
78046
- ${icon("download")} ${i18n2.downloadHourlyExample}
78064
+ ${icon2("download")} ${i18n2.downloadHourlyExample}
78047
78065
  </button>
78048
78066
  <button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit" ${state6.loading || state6.error ? "disabled" : ""}>
78049
- ${icon("pencil")} ${i18n2.enableEditing}
78067
+ ${icon2("pencil")} ${i18n2.enableEditing}
78050
78068
  </button>`;
78051
78069
  return `
78052
78070
  <div class="myio-goals-toolbar">
@@ -78064,9 +78082,9 @@ function openGoalsPanel(params) {
78064
78082
  </select>
78065
78083
  </label>
78066
78084
  <div class="myio-goals-chips">
78067
- <span class="myio-goals-chip myio-goals-chip-accent">${icon("target")} ${i18n2.domains[state6.domain]} \xB7 ${i18n2.aggregation[cfg.aggregationMethod]}</span>
78085
+ <span class="myio-goals-chip myio-goals-chip-accent">${icon2("target")} ${i18n2.domains[state6.domain]} \xB7 ${i18n2.aggregation[cfg.aggregationMethod]}</span>
78068
78086
  <span class="myio-goals-chip myio-goals-chip-mono">${unitLabel2()}</span>
78069
- <span class="myio-goals-chip myio-goals-chip-violet">${icon("history")} ${i18n2.currentVersion.replace("{n}", version2)}</span>
78087
+ <span class="myio-goals-chip myio-goals-chip-violet">${icon2("history")} ${i18n2.currentVersion.replace("{n}", version2)}</span>
78070
78088
  ${renderMarginChip()}
78071
78089
  ${renderDeviceGranularityChip()}
78072
78090
  ${renderCoverageChip()}
@@ -78133,7 +78151,7 @@ function openGoalsPanel(params) {
78133
78151
  ${state6.saving ? "disabled" : ""} />
78134
78152
  <span class="myio-goals-margin-pct">%</span>
78135
78153
  <button class="myio-goals-btn myio-goals-btn-outline myio-goals-btn-sm" data-action="save-margin" ${state6.saving ? "disabled" : ""}>
78136
- ${icon("save")} ${i18n2.margin.save}
78154
+ ${icon2("save")} ${i18n2.margin.save}
78137
78155
  </button>
78138
78156
  ${pct != null ? `<button class="myio-goals-btn myio-goals-btn-outline myio-goals-btn-sm" data-action="clear-margin" ${state6.saving ? "disabled" : ""}>${i18n2.margin.clear}</button>` : ""}
78139
78157
  <span class="myio-goals-margin-hint">${i18n2.margin.hint}</span>
@@ -78142,24 +78160,24 @@ function openGoalsPanel(params) {
78142
78160
  function renderMessages() {
78143
78161
  let html = "";
78144
78162
  if (state6.conflict) {
78145
- html += `<div class="myio-goals-alert myio-goals-alert-amber">${icon("alert")} ${i18n2.versionConflict}</div>`;
78163
+ html += `<div class="myio-goals-alert myio-goals-alert-amber">${icon2("alert")} ${i18n2.versionConflict}</div>`;
78146
78164
  }
78147
78165
  if (state6.saveError && !state6.conflict) {
78148
- html += `<div class="myio-goals-alert myio-goals-alert-red">${icon("alert")} ${esc4(state6.saveError)}</div>`;
78166
+ html += `<div class="myio-goals-alert myio-goals-alert-red">${icon2("alert")} ${esc4(state6.saveError)}</div>`;
78149
78167
  }
78150
78168
  if (state6.saved && !state6.saveError) {
78151
- html += `<div class="myio-goals-alert myio-goals-alert-green">${icon("check")} ${i18n2.saveSuccess}</div>`;
78169
+ html += `<div class="myio-goals-alert myio-goals-alert-green">${icon2("check")} ${i18n2.saveSuccess}</div>`;
78152
78170
  }
78153
78171
  return html;
78154
78172
  }
78155
78173
  function renderMain() {
78156
78174
  if (state6.loading) {
78157
- return `<div class="myio-goals-center">${icon("spinner")} <span>${i18n2.loading}</span></div>`;
78175
+ return `<div class="myio-goals-center">${icon2("spinner")} <span>${i18n2.loading}</span></div>`;
78158
78176
  }
78159
78177
  if (state6.error) {
78160
78178
  return `
78161
78179
  <div class="myio-goals-center myio-goals-center-col">
78162
- ${icon("alert-lg")}
78180
+ ${icon2("alert-lg")}
78163
78181
  <p>${esc4(state6.error)}</p>
78164
78182
  <button class="myio-goals-btn myio-goals-btn-outline" data-action="retry">${i18n2.retry}</button>
78165
78183
  </div>`;
@@ -78172,20 +78190,20 @@ function openGoalsPanel(params) {
78172
78190
  if (!s.hasData) {
78173
78191
  return `
78174
78192
  <div class="myio-goals-center myio-goals-center-col">
78175
- ${icon("target-lg")}
78193
+ ${icon2("target-lg")}
78176
78194
  <p>${i18n2.noData.replace("{year}", state6.year)}</p>
78177
- <button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit">${icon("pencil")} ${i18n2.enableEditing}</button>
78195
+ <button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit">${icon2("pencil")} ${i18n2.enableEditing}</button>
78178
78196
  </div>`;
78179
78197
  }
78180
78198
  const avg = isAverage();
78181
- const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` : icon("sigma");
78199
+ const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` : icon2("sigma");
78182
78200
  const kpis = [
78183
- { ic: icon("calendar"), label: i18n2.summary.year, value: String(state6.year) },
78201
+ { ic: icon2("calendar"), label: i18n2.summary.year, value: String(state6.year) },
78184
78202
  { ic: glyph, label: avg ? i18n2.summary.yearAverage : i18n2.summary.yearTotal, value: fmt2(s.yearValue) },
78185
- { ic: icon("calendar-range"), label: i18n2.summary.monthsWithGoal, value: `${s.monthsWithGoal} / 12` },
78186
- { ic: icon("calendar-days"), label: i18n2.summary.daysWithGoal, value: String(s.daysWithGoal) },
78187
- { ic: icon("trend"), label: i18n2.summary.avgPerMonth, value: fmt2(s.avgPerMonth) },
78188
- { ic: icon("trend"), label: i18n2.summary.avgPerDay, value: fmt2(s.avgPerDay) }
78203
+ { ic: icon2("calendar-range"), label: i18n2.summary.monthsWithGoal, value: `${s.monthsWithGoal} / 12` },
78204
+ { ic: icon2("calendar-days"), label: i18n2.summary.daysWithGoal, value: String(s.daysWithGoal) },
78205
+ { ic: icon2("trend"), label: i18n2.summary.avgPerMonth, value: fmt2(s.avgPerMonth) },
78206
+ { ic: icon2("trend"), label: i18n2.summary.avgPerDay, value: fmt2(s.avgPerDay) }
78189
78207
  ];
78190
78208
  const marginPct = currentMarginPct();
78191
78209
  const adjAnnual = state6.goals && state6.goals.tree && state6.goals.tree.annual ? state6.goals.tree.annual.adjustedValue : null;
@@ -78198,7 +78216,7 @@ function openGoalsPanel(params) {
78198
78216
  }
78199
78217
  const topCol = (title, items, labeler) => `
78200
78218
  <div class="myio-goals-topcard">
78201
- <h4>${icon("trend")} ${title}</h4>
78219
+ <h4>${icon2("trend")} ${title}</h4>
78202
78220
  ${items.length === 0 ? `<p class="myio-goals-muted">\u2014</p>` : `<ol>${items.map(
78203
78221
  (e, i) => `
78204
78222
  <li>
@@ -78237,9 +78255,9 @@ function openGoalsPanel(params) {
78237
78255
  const version2 = state6.goals ? state6.goals.version : 0;
78238
78256
  const crumb = `
78239
78257
  <nav class="myio-goals-crumb">
78240
- <button data-action="crumb-months" class="${state6.level === "month" ? "active" : ""}">${icon("home")} ${i18n2.breadcrumbYear.replace("{year}", state6.year)}</button>
78241
- ${state6.selectedMonth ? `${icon("chevron")}<button data-action="crumb-days" class="${state6.level === "day" ? "active" : ""}">${i18n2.months[state6.selectedMonth]}</button>` : ""}
78242
- ${state6.selectedMonth && state6.selectedDay && state6.level === "hour" ? `${icon("chevron")}<span class="active">${i18n2.breadcrumbDay.replace("{day}", Number(state6.selectedDay))}</span>` : ""}
78258
+ <button data-action="crumb-months" class="${state6.level === "month" ? "active" : ""}">${icon2("home")} ${i18n2.breadcrumbYear.replace("{year}", state6.year)}</button>
78259
+ ${state6.selectedMonth ? `${icon2("chevron")}<button data-action="crumb-days" class="${state6.level === "day" ? "active" : ""}">${i18n2.months[state6.selectedMonth]}</button>` : ""}
78260
+ ${state6.selectedMonth && state6.selectedDay && state6.level === "hour" ? `${icon2("chevron")}<span class="active">${i18n2.breadcrumbDay.replace("{day}", Number(state6.selectedDay))}</span>` : ""}
78243
78261
  </nav>`;
78244
78262
  const emptyHint = state6.level === "month" && monthlyFilledCount() === 0 && version2 === 0 ? `<p class="myio-goals-muted">${i18n2.empty}</p>` : "";
78245
78263
  const drillHint = state6.level !== "hour" ? `<p class="myio-goals-microhint">${state6.level === "month" ? i18n2.drill.openMonthHint : i18n2.drill.openDayHint}</p>` : "";
@@ -78249,14 +78267,14 @@ function openGoalsPanel(params) {
78249
78267
  const confirmed = node && node.derived === false;
78250
78268
  const cellLabel = state6.level === "month" ? i18n2.months[key] : state6.level === "day" ? i18n2.dayCell.replace("{day}", Number(key)) : `${key}:00`;
78251
78269
  const canDrill = state6.level !== "hour";
78252
- const labelEl = canDrill ? `<button class="myio-goals-cell-drill" data-action="${state6.level === "month" ? "open-month" : "open-day"}" data-key="${key}" title="${i18n2.drill.openTitle}">${cellLabel} ${icon("chevron-sm")}</button>` : `<span class="myio-goals-cell-label">${cellLabel}</span>`;
78270
+ const labelEl = canDrill ? `<button class="myio-goals-cell-drill" data-action="${state6.level === "month" ? "open-month" : "open-day"}" data-key="${key}" title="${i18n2.drill.openTitle}">${cellLabel} ${icon2("chevron-sm")}</button>` : `<span class="myio-goals-cell-label">${cellLabel}</span>`;
78253
78271
  const val = state6.draft[key] !== void 0 ? esc4(state6.draft[key]) : "";
78254
78272
  const minAttr = cfg.allowsNegative ? "" : 'min="0"';
78255
78273
  return `
78256
78274
  <div class="myio-goals-cell">
78257
78275
  <div class="myio-goals-cell-head">
78258
78276
  ${labelEl}
78259
- ${icon("pencil-sm")}
78277
+ ${icon2("pencil-sm")}
78260
78278
  </div>
78261
78279
  <div class="myio-goals-cell-input">
78262
78280
  <input type="number" step="any" ${minAttr} data-cell="${key}" value="${val}" placeholder="\u2014" />
@@ -78266,7 +78284,7 @@ function openGoalsPanel(params) {
78266
78284
  </div>`;
78267
78285
  }).join("");
78268
78286
  const totalLabel = state6.level === "month" ? avg ? i18n2.summary.yearAverage : i18n2.summary.yearTotal : state6.level === "day" ? avg ? i18n2.monthAverage : i18n2.monthTotal : avg ? i18n2.dayAverage : i18n2.dayTotal;
78269
- const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` : icon("sigma");
78287
+ const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` : icon2("sigma");
78270
78288
  const total = computedTotal();
78271
78289
  return `
78272
78290
  <div class="myio-goals-editor">
@@ -78279,7 +78297,7 @@ function openGoalsPanel(params) {
78279
78297
  <span class="myio-goals-total-val" id="myio-goals-computed-total">${total === null ? "\u2014" : fmt2(total)}</span>
78280
78298
  </div>
78281
78299
  <div class="myio-goals-legend">
78282
- <span>${icon("pencil-sm")} ${i18n2.legendEditable}</span>
78300
+ <span>${icon2("pencil-sm")} ${i18n2.legendEditable}</span>
78283
78301
  <span>${glyph} ${i18n2.legendComputed}</span>
78284
78302
  </div>
78285
78303
  </div>`;
@@ -78300,12 +78318,12 @@ function openGoalsPanel(params) {
78300
78318
  const diff = Math.max(0, Date.now() - then);
78301
78319
  const s = Math.floor(diff / 1e3);
78302
78320
  const m = Math.floor(s / 60);
78303
- const h2 = Math.floor(m / 60);
78304
- const d = Math.floor(h2 / 24);
78321
+ const h3 = Math.floor(m / 60);
78322
+ const d = Math.floor(h3 / 24);
78305
78323
  const T = i18n2.time;
78306
78324
  if (s < 60) return T.now;
78307
78325
  if (m < 60) return T.min.replace("{n}", m);
78308
- if (h2 < 24) return T.hour.replace("{n}", h2);
78326
+ if (h3 < 24) return T.hour.replace("{n}", h3);
78309
78327
  if (d < 30) return T.day.replace("{n}", d);
78310
78328
  return new Date(iso).toLocaleDateString(locale);
78311
78329
  }
@@ -78314,7 +78332,7 @@ function openGoalsPanel(params) {
78314
78332
  const history = state6.goals && state6.goals.history || [];
78315
78333
  const version2 = state6.goals ? state6.goals.version : 0;
78316
78334
  const DETAIL_PREVIEW = 8;
78317
- const items = history.length === 0 ? `<div class="myio-goals-center myio-goals-center-col myio-goals-hist-empty">${icon("clock")}<p>${i18n2.history.empty}</p></div>` : `<ol class="myio-goals-timeline">${history.map((ev, idx) => {
78335
+ const items = history.length === 0 ? `<div class="myio-goals-center myio-goals-center-col myio-goals-hist-empty">${icon2("clock")}<p>${i18n2.history.empty}</p></div>` : `<ol class="myio-goals-timeline">${history.map((ev, idx) => {
78318
78336
  const actor = ev.actor ? `${String(ev.actor).slice(0, 8)}\u2026` : i18n2.history.system;
78319
78337
  const extra = ev.bucketCount - (ev.details ? ev.details.length : 0);
78320
78338
  const chips = (ev.details || []).slice(0, DETAIL_PREVIEW).map(
@@ -78323,7 +78341,7 @@ function openGoalsPanel(params) {
78323
78341
  const more = extra > 0 ? `<span class="myio-goals-tl-more">${i18n2.history.moreDetails.replace("{n}", extra)}</span>` : "";
78324
78342
  return `
78325
78343
  <li class="myio-goals-tl-item">
78326
- <span class="myio-goals-tl-dot">${icon(ev.source === "IMPORT" ? "upload-sm" : ev.source === "DELETE" ? "trash-sm" : "pencil-sm")}</span>
78344
+ <span class="myio-goals-tl-dot">${icon2(ev.source === "IMPORT" ? "upload-sm" : ev.source === "DELETE" ? "trash-sm" : "pencil-sm")}</span>
78327
78345
  <div class="myio-goals-tl-head">
78328
78346
  <span class="myio-goals-tl-title">${i18n2.history.source[ev.source] || i18n2.history.source.EDIT}</span>
78329
78347
  <span class="myio-goals-tl-ver">v${ev.version}</span>
@@ -78336,7 +78354,7 @@ function openGoalsPanel(params) {
78336
78354
  return `
78337
78355
  <div class="myio-goals-history">
78338
78356
  <div class="myio-goals-history-head">
78339
- <h3>${icon("clock")} ${i18n2.history.title}</h3>
78357
+ <h3>${icon2("clock")} ${i18n2.history.title}</h3>
78340
78358
  <span class="myio-goals-history-meta">${i18n2.domains[state6.domain]} \xB7 ${state6.year} \xB7 ${i18n2.currentVersion.replace("{n}", version2)}</span>
78341
78359
  </div>
78342
78360
  ${items}
@@ -78348,7 +78366,7 @@ function openGoalsPanel(params) {
78348
78366
  <div class="myio-goals-import-dialog">
78349
78367
  <div class="myio-goals-import-card">
78350
78368
  <div class="myio-goals-import-header">
78351
- <span class="myio-goals-import-icon">${icon("upload")}</span>
78369
+ <span class="myio-goals-import-icon">${icon2("upload")}</span>
78352
78370
  <div>
78353
78371
  <h3>${i18n2.import.title}</h3>
78354
78372
  <p>${i18n2.import.subtitle.replace("{domain}", i18n2.domains[state6.domain]).replace("{year}", state6.year)}</p>
@@ -78383,9 +78401,9 @@ ${state6.year}-03-15T08,15`;
78383
78401
  <div class="myio-goals-import-inputhead">
78384
78402
  <label>${i18n2.import.csvLabel}</label>
78385
78403
  <div class="myio-goals-import-links">
78386
- <button data-action="download-template">${icon("download")} ${i18n2.import.downloadTemplate}</button>
78387
- <button data-action="download-hourly">${icon("download")} ${i18n2.import.downloadHourlyExample}</button>
78388
- <button data-action="import-upload">${icon("upload")} ${i18n2.import.uploadFile}</button>
78404
+ <button data-action="download-template">${icon2("download")} ${i18n2.import.downloadTemplate}</button>
78405
+ <button data-action="download-hourly">${icon2("download")} ${i18n2.import.downloadHourlyExample}</button>
78406
+ <button data-action="import-upload">${icon2("upload")} ${i18n2.import.uploadFile}</button>
78389
78407
  <input type="file" id="myio-goals-csv-file" accept=".csv,.txt,text/csv,text/plain" style="display:none" />
78390
78408
  </div>
78391
78409
  </div>
@@ -78398,22 +78416,22 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
78398
78416
  </div>`;
78399
78417
  }
78400
78418
  if (state6.saveError && state6.conflictVersion === null) {
78401
- html += `<div class="myio-goals-alert myio-goals-alert-red">${icon("alert")} ${esc4(state6.saveError)}</div>`;
78419
+ html += `<div class="myio-goals-alert myio-goals-alert-red">${icon2("alert")} ${esc4(state6.saveError)}</div>`;
78402
78420
  }
78403
78421
  if (state6.conflictVersion !== null) {
78404
- html += `<div class="myio-goals-alert myio-goals-alert-amber">${icon("alert")} ${i18n2.import.conflict}</div>`;
78422
+ html += `<div class="myio-goals-alert myio-goals-alert-amber">${icon2("alert")} ${i18n2.import.conflict}</div>`;
78405
78423
  }
78406
78424
  if (result) html += renderImportSummary(result, counts);
78407
78425
  return html;
78408
78426
  }
78409
78427
  function renderImportSummary(result, counts) {
78410
78428
  const persisted = result.dryRun === false;
78411
- const badge = persisted ? `<span class="myio-goals-chip myio-goals-chip-accent">${icon("check")} ${i18n2.import.appliedBadge.replace("{version}", result.version || 0)}</span>` : `<span class="myio-goals-chip myio-goals-chip-mono">${i18n2.import.previewBadge}</span>`;
78429
+ const badge = persisted ? `<span class="myio-goals-chip myio-goals-chip-accent">${icon2("check")} ${i18n2.import.appliedBadge.replace("{version}", result.version || 0)}</span>` : `<span class="myio-goals-chip myio-goals-chip-mono">${i18n2.import.previewBadge}</span>`;
78412
78430
  let html = `
78413
78431
  <div class="myio-goals-import-summary">
78414
78432
  <div class="myio-goals-import-counts">
78415
- <span class="myio-goals-chip myio-goals-chip-accent">${icon("check")} ${i18n2.import.okCount.replace("{n}", result.okCount)}</span>
78416
- ${result.errorCount > 0 ? `<span class="myio-goals-chip myio-goals-chip-red">${icon("alert")} ${i18n2.import.errorCount.replace("{n}", result.errorCount)}</span>` : ""}
78433
+ <span class="myio-goals-chip myio-goals-chip-accent">${icon2("check")} ${i18n2.import.okCount.replace("{n}", result.okCount)}</span>
78434
+ ${result.errorCount > 0 ? `<span class="myio-goals-chip myio-goals-chip-red">${icon2("alert")} ${i18n2.import.errorCount.replace("{n}", result.errorCount)}</span>` : ""}
78417
78435
  ${badge}
78418
78436
  </div>`;
78419
78437
  if (!persisted && counts && result.okCount > 0) {
@@ -78427,7 +78445,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
78427
78445
  <div class="myio-goals-import-diags">
78428
78446
  <p class="myio-goals-import-diags-title">${i18n2.import.diagnosticsTitle}</p>
78429
78447
  <ul>${result.diagnostics.map(
78430
- (d) => `<li>${icon("alert-sm")} <span><span class="myio-goals-diag-line">${i18n2.import.line.replace("{line}", d.line)}</span>${d.bucket ? ` <span class="myio-goals-diag-bucket">[${esc4(d.bucket)}]</span>` : ""} ${esc4(d.reason)}</span></li>`
78448
+ (d) => `<li>${icon2("alert-sm")} <span><span class="myio-goals-diag-line">${i18n2.import.line.replace("{line}", d.line)}</span>${d.bucket ? ` <span class="myio-goals-diag-bucket">[${esc4(d.bucket)}]</span>` : ""} ${esc4(d.reason)}</span></li>`
78431
78449
  ).join("")}</ul>
78432
78450
  </div>`;
78433
78451
  }
@@ -78447,7 +78465,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
78447
78465
  }
78448
78466
  const canPreview = state6.csv.trim().length > 0 && !state6.saving;
78449
78467
  const canConfirm = !!state6.importPreview && state6.importPreview.okCount > 0 && !state6.saving && !state6.importApplied;
78450
- const right = state6.importPreview ? `<button class="myio-goals-btn myio-goals-btn-primary" data-action="import-confirm" ${canConfirm ? "" : "disabled"}>${icon("upload")} ${i18n2.import.confirm.replace("{n}", state6.importPreview.okCount)}</button>` : `<button class="myio-goals-btn myio-goals-btn-primary" data-action="import-preview" ${canPreview ? "" : "disabled"}>${icon("upload")} ${i18n2.import.preview}</button>`;
78468
+ const right = state6.importPreview ? `<button class="myio-goals-btn myio-goals-btn-primary" data-action="import-confirm" ${canConfirm ? "" : "disabled"}>${icon2("upload")} ${i18n2.import.confirm.replace("{n}", state6.importPreview.okCount)}</button>` : `<button class="myio-goals-btn myio-goals-btn-primary" data-action="import-preview" ${canPreview ? "" : "disabled"}>${icon2("upload")} ${i18n2.import.preview}</button>`;
78451
78469
  return `
78452
78470
  <button class="myio-goals-btn myio-goals-btn-outline" data-action="import-close" ${state6.saving ? "disabled" : ""}>${i18n2.import.cancel}</button>
78453
78471
  ${right}`;
@@ -78459,7 +78477,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
78459
78477
  if (body) body.innerHTML = renderImportInner();
78460
78478
  if (footer) footer.innerHTML = renderImportFooter();
78461
78479
  }
78462
- function icon(name) {
78480
+ function icon2(name) {
78463
78481
  const S2 = (p2) => `<svg class="myio-goals-ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${p2}</svg>`;
78464
78482
  switch (name) {
78465
78483
  case "target":
@@ -82001,7 +82019,7 @@ var EnergySummaryTooltip = {
82001
82019
  }))
82002
82020
  });
82003
82021
  categories.forEach((cat, catIndex) => {
82004
- const icon = CATEGORY_ICONS[cat.id] || CATEGORY_ICONS.outros;
82022
+ const icon2 = CATEGORY_ICONS[cat.id] || CATEGORY_ICONS.outros;
82005
82023
  const hasChildren = cat.children && cat.children.length > 0;
82006
82024
  const hasShoppingBreakdown = cat.byShoppingBreakdown && cat.byShoppingBreakdown.length > 0;
82007
82025
  const isExpandable = hasChildren || hasShoppingBreakdown;
@@ -82011,7 +82029,7 @@ var EnergySummaryTooltip = {
82011
82029
  ${isExpandable ? `
82012
82030
  <button class="energy-summary-tooltip__expand-toggle" data-target="cat-${catIndex}" title="Expandir">+</button>
82013
82031
  ` : ""}
82014
- <span class="energy-summary-tooltip__category-icon">${icon}</span>
82032
+ <span class="energy-summary-tooltip__category-icon">${icon2}</span>
82015
82033
  <span>${cat.name}</span>
82016
82034
  </span>
82017
82035
  <span class="energy-summary-tooltip__category-count">${cat.deviceCount}</span>
@@ -82678,10 +82696,10 @@ var EnergySummaryTooltip = {
82678
82696
  return;
82679
82697
  }
82680
82698
  this._cancelDevicePopupDelayedHide();
82681
- const icon = this._getStatusIcon(statusKey);
82699
+ const icon2 = this._getStatusIcon(statusKey);
82682
82700
  const content = this._buildDeviceListContent(statusKey, label, count);
82683
82701
  InfoTooltip2.show(triggerElement, {
82684
- icon,
82702
+ icon: icon2,
82685
82703
  title: `${label} (${count})`,
82686
82704
  content
82687
82705
  });
@@ -83995,7 +84013,7 @@ var WaterSummaryTooltip = {
83995
84013
  return html;
83996
84014
  }
83997
84015
  categories.forEach((cat, catIndex) => {
83998
- const icon = WATER_CATEGORY_ICONS[cat.id] || WATER_CATEGORY_ICONS.areaComum;
84016
+ const icon2 = WATER_CATEGORY_ICONS[cat.id] || WATER_CATEGORY_ICONS.areaComum;
83999
84017
  const hasChildren = cat.children && cat.children.length > 0;
84000
84018
  const hasShoppingBreakdown = cat.byShoppingBreakdown && cat.byShoppingBreakdown.length > 0;
84001
84019
  const isExpandable = hasChildren || hasShoppingBreakdown;
@@ -84005,7 +84023,7 @@ var WaterSummaryTooltip = {
84005
84023
  ${isExpandable ? `
84006
84024
  <button class="water-summary-tooltip__expand-toggle" data-target="water-cat-${catIndex}" title="Expandir">+</button>
84007
84025
  ` : ""}
84008
- <span class="water-summary-tooltip__category-icon">${icon}</span>
84026
+ <span class="water-summary-tooltip__category-icon">${icon2}</span>
84009
84027
  <span>${cat.name}</span>
84010
84028
  </span>
84011
84029
  <span class="water-summary-tooltip__category-count">${cat.deviceCount}</span>
@@ -84603,10 +84621,10 @@ var WaterSummaryTooltip = {
84603
84621
  return;
84604
84622
  }
84605
84623
  this._cancelDevicePopupDelayedHide();
84606
- const icon = this._getStatusIcon(statusKey);
84624
+ const icon2 = this._getStatusIcon(statusKey);
84607
84625
  const content = this._buildDeviceListContent(statusKey, label, count);
84608
84626
  InfoTooltip2.show(triggerElement, {
84609
- icon,
84627
+ icon: icon2,
84610
84628
  title: `${label} (${count})`,
84611
84629
  content
84612
84630
  });
@@ -86198,10 +86216,10 @@ function generateContentHTML(data) {
86198
86216
  <div class="myio-temp-sensor-tooltip__list">
86199
86217
  ${displayDevices.map((d) => {
86200
86218
  const statusClass = d.status === "ok" ? "ok" : d.status === "warn" ? "warn" : "unknown";
86201
- const icon = d.status === "ok" ? "\u2714" : d.status === "warn" ? "\u26A0" : "?";
86219
+ const icon2 = d.status === "ok" ? "\u2714" : d.status === "warn" ? "\u26A0" : "?";
86202
86220
  return `
86203
86221
  <div class="myio-temp-sensor-tooltip__list-item myio-temp-sensor-tooltip__list-item--${statusClass}">
86204
- <span class="myio-temp-sensor-tooltip__list-icon">${icon}</span>
86222
+ <span class="myio-temp-sensor-tooltip__list-icon">${icon2}</span>
86205
86223
  <span class="myio-temp-sensor-tooltip__list-name">${d.name}</span>
86206
86224
  <span class="myio-temp-sensor-tooltip__list-value">${d.temp.toFixed(1)}\xB0C</span>
86207
86225
  </div>
@@ -87059,7 +87077,7 @@ function generateHeaderHTML5(data) {
87059
87077
  </div>
87060
87078
  `;
87061
87079
  }
87062
- function generateDomainHTML(domain, icon, name, counts, isTemperature = false) {
87080
+ function generateDomainHTML(domain, icon2, name, counts, isTemperature = false) {
87063
87081
  const isExpanded = state5.expandedDomains.has(domain);
87064
87082
  const expandedClass = isExpanded ? "expanded" : "";
87065
87083
  let detailsHTML = "";
@@ -87096,7 +87114,7 @@ function generateDomainHTML(domain, icon, name, counts, isTemperature = false) {
87096
87114
  <div class="myio-contract-summary-tooltip__domain ${expandedClass}" data-domain="${domain}">
87097
87115
  <div class="myio-contract-summary-tooltip__domain-header" data-toggle-domain="${domain}">
87098
87116
  <div class="myio-contract-summary-tooltip__domain-info">
87099
- <span class="myio-contract-summary-tooltip__domain-icon">${icon}</span>
87117
+ <span class="myio-contract-summary-tooltip__domain-icon">${icon2}</span>
87100
87118
  <span class="myio-contract-summary-tooltip__domain-name">${name}</span>
87101
87119
  </div>
87102
87120
  <div style="display: flex; align-items: center; gap: 8px;">
@@ -93236,11 +93254,11 @@ function renderRow(row, level) {
93236
93254
  const pct = row.pct;
93237
93255
  const caret = hasChildren ? `<button class="myio-gbt__caret${open ? " is-open" : ""}" data-caret="${id}" title="Expandir/recolher">\u25B8</button>` : `<span class="myio-gbt__caret-spacer"></span>`;
93238
93256
  const swatch = row.color ? `<span class="myio-gbt__swatch" style="background:${esc6(row.color)}"></span>` : "";
93239
- const icon = row.icon ? `<span class="myio-gbt__icon">${esc6(row.icon)}</span>` : "";
93257
+ const icon2 = row.icon ? `<span class="myio-gbt__icon">${esc6(row.icon)}</span>` : "";
93240
93258
  const chipHtml = row.delta ? renderDeltaChip(row.delta) : "";
93241
93259
  const pctHtml = !row.delta && pct != null && isFinite(pct) ? `<span class="myio-gbt__pct">${esc6(fmtPct3(pct))}</span>` : "";
93242
93260
  const rowClass = level > 0 ? "myio-gbt__row myio-gbt__row--child" : "myio-gbt__row";
93243
- let html = `<div class="${rowClass}">` + caret + swatch + icon + `<span class="myio-gbt__label">${esc6(row.label)}</span><span class="myio-gbt__value">${esc6(row.valueText)}</span>` + chipHtml + pctHtml + `</div>`;
93261
+ let html = `<div class="${rowClass}">` + caret + swatch + icon2 + `<span class="myio-gbt__label">${esc6(row.label)}</span><span class="myio-gbt__value">${esc6(row.valueText)}</span>` + chipHtml + pctHtml + `</div>`;
93244
93262
  if (hasChildren) {
93245
93263
  const childHtml = row.children.map((c) => renderRow(c, level + 1)).join("");
93246
93264
  html += `<div class="myio-gbt__children${open ? " is-open" : ""}" data-children="${id}">${childHtml}</div>`;
@@ -93275,16 +93293,16 @@ function createGoalsBarTooltip(opts) {
93275
93293
  function positionAt(clientX, clientY) {
93276
93294
  const rect = el2.getBoundingClientRect();
93277
93295
  const w = rect.width || 280;
93278
- const h2 = rect.height || 200;
93296
+ const h3 = rect.height || 200;
93279
93297
  const pad = 12;
93280
93298
  const gap = 16;
93281
93299
  let left = clientX + gap;
93282
93300
  let top = clientY + gap;
93283
93301
  if (left + w > window.innerWidth - pad) left = clientX - w - gap;
93284
93302
  if (left < pad) left = Math.max(pad, (window.innerWidth - w) / 2);
93285
- if (top + h2 > window.innerHeight - pad) top = clientY - h2 - gap;
93303
+ if (top + h3 > window.innerHeight - pad) top = clientY - h3 - gap;
93286
93304
  if (top < pad) top = pad;
93287
- if (top + h2 > window.innerHeight - pad) top = Math.max(pad, window.innerHeight - h2 - pad);
93305
+ if (top + h3 > window.innerHeight - pad) top = Math.max(pad, window.innerHeight - h3 - pad);
93288
93306
  el2.style.left = `${Math.round(left)}px`;
93289
93307
  el2.style.top = `${Math.round(top)}px`;
93290
93308
  }
@@ -93524,13 +93542,13 @@ function _buildDayBoundaries(startISO, endISO) {
93524
93542
  }
93525
93543
  function _buildHourBoundaries(dateISO) {
93526
93544
  const result = [];
93527
- for (let h2 = 0; h2 < 24; h2++) {
93545
+ for (let h3 = 0; h3 < 24; h3++) {
93528
93546
  const start = /* @__PURE__ */ new Date(`${dateISO}T00:00:00`);
93529
- start.setHours(h2, 0, 0, 0);
93547
+ start.setHours(h3, 0, 0, 0);
93530
93548
  const end = new Date(start);
93531
- end.setHours(h2, 59, 59, 999);
93549
+ end.setHours(h3, 59, 59, 999);
93532
93550
  result.push({
93533
- label: `${String(h2).padStart(2, "0")}h`,
93551
+ label: `${String(h3).padStart(2, "0")}h`,
93534
93552
  startTs: start.getTime(),
93535
93553
  endTs: end.getTime()
93536
93554
  });
@@ -96905,7 +96923,7 @@ var MODE_DEFAULTS = {
96905
96923
  }
96906
96924
  };
96907
96925
  function mixHex2(hexA, hexB, pctB) {
96908
- const n = (h2) => parseInt(h2.slice(1), 16);
96926
+ const n = (h3) => parseInt(h3.slice(1), 16);
96909
96927
  const a = n(hexA);
96910
96928
  const b = n(hexB);
96911
96929
  const ch = (sa, sb) => Math.round(sa + (sb - sa) * pctB);
@@ -97851,11 +97869,11 @@ var TariffApiClient = class {
97851
97869
  this.basePath = config2.basePath ?? "api/v1";
97852
97870
  }
97853
97871
  authHeaders() {
97854
- const h2 = {};
97855
- if (this.cfg.apiKey) h2["X-API-Key"] = this.cfg.apiKey;
97856
- if (this.cfg.jwt) h2["Authorization"] = `Bearer ${this.cfg.jwt}`;
97857
- if (this.cfg.tenantId) h2["X-Tenant-Id"] = this.cfg.tenantId;
97858
- return h2;
97872
+ const h3 = {};
97873
+ if (this.cfg.apiKey) h3["X-API-Key"] = this.cfg.apiKey;
97874
+ if (this.cfg.jwt) h3["Authorization"] = `Bearer ${this.cfg.jwt}`;
97875
+ if (this.cfg.tenantId) h3["X-Tenant-Id"] = this.cfg.tenantId;
97876
+ return h3;
97859
97877
  }
97860
97878
  /** Read the tariff tree. `granularity` defaults to `day` server-side. */
97861
97879
  async getTariff(sel, granularity = "hour") {
@@ -98117,7 +98135,7 @@ function bandToPanelEntry(band, customerId) {
98117
98135
  function expandDayToHourBuckets(date, price) {
98118
98136
  assertValidCivilDate(date);
98119
98137
  const out = [];
98120
- for (let h2 = 0; h2 < 24; h2++) out.push({ level: "HOUR", ref: `${date}T${pad23(h2)}`, price });
98138
+ for (let h3 = 0; h3 < 24; h3++) out.push({ level: "HOUR", ref: `${date}T${pad23(h3)}`, price });
98121
98139
  return out;
98122
98140
  }
98123
98141
  function expandBandHours(date, startHour, endHour, price) {
@@ -98126,7 +98144,7 @@ function expandBandHours(date, startHour, endHour, price) {
98126
98144
  throw new Error(`Invalid hour band ${startHour}-${endHour} for ${date}`);
98127
98145
  }
98128
98146
  const out = [];
98129
- for (let h2 = startHour; h2 <= endHour; h2++) out.push({ level: "HOUR", ref: `${date}T${pad23(h2)}`, price });
98147
+ for (let h3 = startHour; h3 <= endHour; h3++) out.push({ level: "HOUR", ref: `${date}T${pad23(h3)}`, price });
98130
98148
  return out;
98131
98149
  }
98132
98150
  function bandDateBounds(band) {
@@ -98176,12 +98194,12 @@ function expandBandToHourBucketsByYear(band) {
98176
98194
  function collapseHoursToBands(date, hours, dims) {
98177
98195
  const sorted = [...hours].sort((a, b) => a.hour - b.hour);
98178
98196
  const runs = [];
98179
- for (const h2 of sorted) {
98197
+ for (const h3 of sorted) {
98180
98198
  const cur = runs[runs.length - 1];
98181
- if (cur && h2.hour === cur.endHour + 1 && h2.price === cur.price) {
98182
- cur.endHour = h2.hour;
98199
+ if (cur && h3.hour === cur.endHour + 1 && h3.price === cur.price) {
98200
+ cur.endHour = h3.hour;
98183
98201
  } else {
98184
- runs.push({ startHour: h2.hour, endHour: h2.hour, price: h2.price });
98202
+ runs.push({ startHour: h3.hour, endHour: h3.hour, price: h3.price });
98185
98203
  }
98186
98204
  }
98187
98205
  return runs.map(
@@ -98201,13 +98219,13 @@ function dayNodeToHours(node) {
98201
98219
  const hourly = node.hourly || {};
98202
98220
  const hourKeys = Object.keys(hourly);
98203
98221
  if (hourKeys.length === 0) {
98204
- return dayPrice != null ? Array.from({ length: 24 }, (_, h2) => ({ hour: h2, price: dayPrice })) : null;
98222
+ return dayPrice != null ? Array.from({ length: 24 }, (_, h3) => ({ hour: h3, price: dayPrice })) : null;
98205
98223
  }
98206
98224
  const out = [];
98207
- for (let h2 = 0; h2 < 24; h2++) {
98208
- const ov = hourly[String(h2)];
98225
+ for (let h3 = 0; h3 < 24; h3++) {
98226
+ const ov = hourly[String(h3)];
98209
98227
  const price = ov && typeof ov.price === "string" ? ov.price : dayPrice;
98210
- if (price != null) out.push({ hour: h2, price });
98228
+ if (price != null) out.push({ hour: h3, price });
98211
98229
  }
98212
98230
  return out.length ? out : null;
98213
98231
  }
@@ -98994,11 +99012,11 @@ var GoalsMoneyClient = class {
98994
99012
  this.basePath = config2.basePath ?? "api/v1";
98995
99013
  }
98996
99014
  authHeaders() {
98997
- const h2 = {};
98998
- if (this.cfg.apiKey) h2["X-API-Key"] = this.cfg.apiKey;
98999
- if (this.cfg.jwt) h2["Authorization"] = `Bearer ${this.cfg.jwt}`;
99000
- if (this.cfg.tenantId) h2["X-Tenant-Id"] = this.cfg.tenantId;
99001
- return h2;
99015
+ const h3 = {};
99016
+ if (this.cfg.apiKey) h3["X-API-Key"] = this.cfg.apiKey;
99017
+ if (this.cfg.jwt) h3["Authorization"] = `Bearer ${this.cfg.jwt}`;
99018
+ if (this.cfg.tenantId) h3["X-Tenant-Id"] = this.cfg.tenantId;
99019
+ return h3;
99002
99020
  }
99003
99021
  goalsPath(sel) {
99004
99022
  return `/customers/${encodeURIComponent(sel.customerId)}/goals`;
@@ -103905,14 +103923,14 @@ function renderLojasStep3(state6, modalId, colors2, t) {
103905
103923
  }
103906
103924
  function renderAttrRow(key, value, readonly, suggestion, colors2, modalId, t, isFetchable = false, helpText) {
103907
103925
  const hasValue = value !== null && value !== void 0 && value !== "";
103908
- const icon = hasValue ? "\u2705" : "\u26A0\uFE0F";
103926
+ const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
103909
103927
  const inputBorder = hasValue ? colors2.border : colors2.warning;
103910
103928
  return `
103911
103929
  <div style="
103912
103930
  display: flex; align-items: center; gap: 12px;
103913
103931
  padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
103914
103932
  ">
103915
- <span style="font-size: 16px;">${icon}</span>
103933
+ <span style="font-size: 16px;">${icon2}</span>
103916
103934
  <span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
103917
103935
  ${key}
103918
103936
  ${helpText ? `<span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>` : ""}
@@ -103947,7 +103965,7 @@ function renderAttrRow(key, value, readonly, suggestion, colors2, modalId, t, is
103947
103965
  }
103948
103966
  function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
103949
103967
  const hasValue = !!value;
103950
- const icon = hasValue ? "\u2705" : "\u26A0\uFE0F";
103968
+ const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
103951
103969
  const options = [
103952
103970
  "3F_MEDIDOR",
103953
103971
  "HIDROMETRO",
@@ -103966,7 +103984,7 @@ function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
103966
103984
  display: flex; align-items: center; gap: 12px;
103967
103985
  padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
103968
103986
  ">
103969
- <span style="font-size: 16px;">${icon}</span>
103987
+ <span style="font-size: 16px;">${icon2}</span>
103970
103988
  <span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500;">deviceType</span>
103971
103989
  <div style="flex: 1;">
103972
103990
  <select id="${modalId}-deviceType" style="
@@ -103992,7 +104010,7 @@ function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
103992
104010
  }
103993
104011
  function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
103994
104012
  const hasValue = !!value;
103995
- const icon = hasValue ? "\u2705" : "\u26A0\uFE0F";
104013
+ const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
103996
104014
  const profiles = getSuggestedProfiles(deviceType);
103997
104015
  const helpText = "IMPORTANTE: deviceType + deviceProfile definem o tipo do device. Se ambos = 3F_MEDIDOR \u2192 device \xE9 LOJA (energia). Se ambos = HIDROMETRO \u2192 device \xE9 LOJA (\xE1gua).";
103998
104016
  return `
@@ -104000,7 +104018,7 @@ function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
104000
104018
  display: flex; align-items: center; gap: 12px;
104001
104019
  padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
104002
104020
  ">
104003
- <span style="font-size: 16px;">${icon}</span>
104021
+ <span style="font-size: 16px;">${icon2}</span>
104004
104022
  <span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
104005
104023
  deviceProfile
104006
104024
  <span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>
@@ -104021,7 +104039,7 @@ function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
104021
104039
  }
104022
104040
  function renderEntityLabelRow(currentLabel, deviceName, colors2, modalId, t) {
104023
104041
  const hasValue = !!currentLabel;
104024
- const icon = hasValue ? "\u2705" : "\u26A0\uFE0F";
104042
+ const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
104025
104043
  const suggestedValue = currentLabel || deviceName;
104026
104044
  const helpText = "Etiqueta do dispositivo (entityLabel) - aparece no nome exibido da entidade no ThingsBoard";
104027
104045
  return `
@@ -104029,7 +104047,7 @@ function renderEntityLabelRow(currentLabel, deviceName, colors2, modalId, t) {
104029
104047
  display: flex; align-items: center; gap: 12px;
104030
104048
  padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
104031
104049
  ">
104032
- <span style="font-size: 16px;">${icon}</span>
104050
+ <span style="font-size: 16px;">${icon2}</span>
104033
104051
  <span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
104034
104052
  etiqueta
104035
104053
  <span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>
@@ -104303,8 +104321,8 @@ async function openClearGcdrIdsModal(state6) {
104303
104321
  </div>
104304
104322
  </div>`;
104305
104323
  }
104306
- function keyBadges(present, keys) {
104307
- return keys.filter((k) => present[k]).map((k) => `<span style="font-size:9px; background:rgba(220,38,38,0.25); color:#fca5a5; padding:1px 5px; border-radius:3px; margin:1px; display:inline-block;">${k}</span>`).join("");
104324
+ function keyBadges(present2, keys) {
104325
+ return keys.filter((k) => present2[k]).map((k) => `<span style="font-size:9px; background:rgba(220,38,38,0.25); color:#fca5a5; padding:1px 5px; border-radius:3px; margin:1px; display:inline-block;">${k}</span>`).join("");
104308
104326
  }
104309
104327
  function tableHtml(rows, keys) {
104310
104328
  if (rows.length === 0) return '<div style="font-size:12px;color:#6b7280;padding:6px 0;">Nenhum item a limpar.</div>';
@@ -104365,13 +104383,13 @@ async function openClearGcdrIdsModal(state6) {
104365
104383
  await Promise.all(chunks[ci].map(async (entity) => {
104366
104384
  const tbId = entity.id?.id || "";
104367
104385
  const name = entity.name || entity.label || tbId;
104368
- let present = {};
104386
+ let present2 = {};
104369
104387
  try {
104370
104388
  const attrs = await fetchAttrs(tbId);
104371
- for (const k of keysToCheck) present[k] = attrs[k] != null && attrs[k] !== "";
104389
+ for (const k of keysToCheck) present2[k] = attrs[k] != null && attrs[k] !== "";
104372
104390
  } catch {
104373
104391
  }
104374
- targetRows.push({ tbId, name, entityType, present, hasAny: keysToCheck.some((k) => present[k]) });
104392
+ targetRows.push({ tbId, name, entityType, present: present2, hasAny: keysToCheck.some((k) => present2[k]) });
104375
104393
  }));
104376
104394
  const done = deviceRows.length + assetRows.length;
104377
104395
  const bodyEl = overlay.querySelector("#gcdr-clear-body");
@@ -107781,6 +107799,2089 @@ function openGenericModal(params) {
107781
107799
  };
107782
107800
  }
107783
107801
 
107802
+ // src/components/myio-gcdr-login/dom.ts
107803
+ function h2(doc, tag, attrs = {}, ...children) {
107804
+ const el2 = doc.createElement(tag);
107805
+ for (const [k, v] of Object.entries(attrs)) {
107806
+ if (v === null || v === void 0 || v === false) continue;
107807
+ if (k === "class") el2.className = String(v);
107808
+ else if (k === "text") el2.textContent = String(v);
107809
+ else el2.setAttribute(k, v === true ? "" : String(v));
107810
+ }
107811
+ for (const c of children) {
107812
+ if (c === null || c === void 0 || c === false) continue;
107813
+ el2.appendChild(typeof c === "string" ? doc.createTextNode(c) : c);
107814
+ }
107815
+ return el2;
107816
+ }
107817
+ function icon(doc, markup, cls) {
107818
+ const span = doc.createElement("span");
107819
+ if (cls) span.className = cls;
107820
+ span.setAttribute("aria-hidden", "true");
107821
+ span.innerHTML = markup;
107822
+ return span;
107823
+ }
107824
+ function safeCall(label, fn, ...args) {
107825
+ if (!fn) return;
107826
+ try {
107827
+ const r = fn(...args);
107828
+ if (r && typeof r.catch === "function") {
107829
+ r.catch(() => console.error(`[MYIO Login] ${label} failed`));
107830
+ }
107831
+ } catch {
107832
+ console.error(`[MYIO Login] ${label} failed`);
107833
+ }
107834
+ }
107835
+ function storageGet(key) {
107836
+ try {
107837
+ return typeof localStorage !== "undefined" ? localStorage.getItem(key) : null;
107838
+ } catch {
107839
+ return null;
107840
+ }
107841
+ }
107842
+ function storageSet(key, value) {
107843
+ try {
107844
+ if (typeof localStorage === "undefined") return;
107845
+ if (value === null) localStorage.removeItem(key);
107846
+ else localStorage.setItem(key, value);
107847
+ } catch {
107848
+ }
107849
+ }
107850
+ function prefersDark() {
107851
+ try {
107852
+ return typeof matchMedia === "function" && matchMedia("(prefers-color-scheme: dark)").matches;
107853
+ } catch {
107854
+ return false;
107855
+ }
107856
+ }
107857
+ function isCoarsePointer() {
107858
+ try {
107859
+ return typeof matchMedia === "function" && matchMedia("(pointer: coarse)").matches;
107860
+ } catch {
107861
+ return false;
107862
+ }
107863
+ }
107864
+
107865
+ // src/components/myio-gcdr-login/icons.ts
107866
+ var svg = (body, size = 16) => `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${body}</svg>`;
107867
+ var ICONS = {
107868
+ eye: (s) => svg('<path d="M2.06 12.35a1 1 0 0 1 0-.7 10.75 10.75 0 0 1 19.88 0 1 1 0 0 1 0 .7 10.75 10.75 0 0 1-19.88 0"/><circle cx="12" cy="12" r="3"/>', s),
107869
+ eyeOff: (s) => svg('<path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c4.97 0 8.9 3.12 10 7a10.7 10.7 0 0 1-1.67 3.13"/><path d="M14.08 14.16a3 3 0 1 1-4.24-4.24"/><path d="M17.48 17.5A10.7 10.7 0 0 1 12 19c-4.97 0-8.9-3.12-10-7a10.7 10.7 0 0 1 4.52-5.5"/><path d="m2 2 20 20"/>', s),
107870
+ lock: (s) => svg('<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>', s),
107871
+ shieldAlert: (s) => svg('<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="M12 8v4"/><path d="M12 16h.01"/>', s),
107872
+ alert: (s) => svg('<circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/>', s),
107873
+ info: (s) => svg('<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>', s),
107874
+ sun: (s) => svg('<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>', s),
107875
+ moon: (s) => svg('<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>', s),
107876
+ globe: (s) => svg('<circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/>', s),
107877
+ x: (s) => svg('<path d="M18 6 6 18"/><path d="m6 6 12 12"/>', s),
107878
+ arrowLeft: (s) => svg('<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>', s),
107879
+ chevronRight: (s) => svg('<path d="m9 18 6-6-6-6"/>', s),
107880
+ external: (s) => svg('<path d="M7 7h10v10"/><path d="M7 17 17 7"/>', s),
107881
+ book: (s) => svg('<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/>', s),
107882
+ headset: (s) => svg('<path d="M3 11h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Zm0 0a9 9 0 1 1 18 0m0 0v5a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3Z"/><path d="M21 16v2a4 4 0 0 1-4 4h-5"/>', s),
107883
+ plug: (s) => svg('<path d="M12 22v-5"/><path d="M9 8V2"/><path d="M15 8V2"/><path d="M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/>', s),
107884
+ grid: (s) => svg('<rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/>', s),
107885
+ building: (s) => svg('<rect width="16" height="20" x="4" y="2" rx="2" ry="2"/><path d="M9 22v-4h6v4"/><path d="M8 6h.01"/><path d="M16 6h.01"/><path d="M12 6h.01"/><path d="M12 10h.01"/><path d="M12 14h.01"/><path d="M16 10h.01"/><path d="M16 14h.01"/><path d="M8 10h.01"/><path d="M8 14h.01"/>', s),
107886
+ activity: (s) => svg('<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"/>', s),
107887
+ spinner: (s) => svg('<path d="M21 12a9 9 0 1 1-6.219-8.56"/>', s)
107888
+ };
107889
+
107890
+ // src/components/myio-gcdr-login/about.ts
107891
+ var CATEGORIES = [
107892
+ { key: "wiki", icon: "book", items: [
107893
+ { key: "wikiHome", to: "/wiki/p", web: true },
107894
+ { key: "wikiSearch", to: "/wiki/p/search", web: true },
107895
+ { key: "accountGuide", to: "/wiki/p/User-Guides/acesso-a-conta", web: true }
107896
+ ] },
107897
+ { key: "support", icon: "headset", items: [
107898
+ { key: "openTicket", to: "/support", web: true },
107899
+ { key: "forgotPassword", to: "/forgot-password", web: true }
107900
+ ] },
107901
+ { key: "integrations", icon: "plug", items: [
107902
+ { key: "docsAlarms", to: "https://alarms-api.a.myio-bas.com/docs" },
107903
+ { key: "docsGcdr", to: "https://gcdr-api.a.myio-bas.com/docs/" },
107904
+ { key: "docsIngestion", to: "https://api.data.apps.myio-bas.com/api/docs/" },
107905
+ { key: "docsThingsboard", to: "https://dashboard.myio-bas.com/swagger-ui/index.html" },
107906
+ { key: "integrationsGuide", to: "/wiki/p/Integrations/index", web: true },
107907
+ { key: "newIntegration", to: "/wiki/p/integrations/new", web: true }
107908
+ ] },
107909
+ { key: "systems", icon: "grid", items: [
107910
+ { key: "app", to: "https://app.apps.myio-bas.com" },
107911
+ { key: "dashboards", to: "https://dashboard.myio-bas.com" },
107912
+ { key: "alarms", to: "https://alarms-web.a.myio-bas.com" }
107913
+ ] },
107914
+ { key: "institutional", icon: "building", items: [
107915
+ { key: "site", to: "https://myio.com.br" },
107916
+ { key: "privacy", to: "https://myio.com.br/politica-de-privacidade" },
107917
+ { key: "terms" }
107918
+ ] },
107919
+ { key: "status", icon: "activity", items: [{ key: "gcdrHealth", health: true }] }
107920
+ ];
107921
+ function defaultSupportHref(webUrl) {
107922
+ return webUrl ? `${webUrl.replace(/\/+$/, "")}/support` : void 0;
107923
+ }
107924
+ function renderAbout(el2, ctx, t, opts) {
107925
+ const doc = el2.ownerDocument;
107926
+ const { body } = ctx.panel({ eyebrow: t("about.eyebrow"), fill: true, logo: false, bandColor: opts.bandColor ?? "#2E8B57" });
107927
+ const web = opts.webUrl?.replace(/\/+$/, "");
107928
+ const visibleCats = CATEGORIES.filter((c) => c.key === "status" ? !!opts.healthUrl : true);
107929
+ let healthAbort = null;
107930
+ const showGrid = () => {
107931
+ body.textContent = "";
107932
+ const title = h2(doc, "h2", { class: "myio-gcdr-about__title" }, `${t("about.title")} `, h2(doc, "em", { text: t("about.titleHighlight") }));
107933
+ const intro = h2(doc, "p", { class: "myio-gcdr-about__intro", text: t("about.text") });
107934
+ const grid = h2(doc, "div", { class: "myio-gcdr-about__grid" });
107935
+ for (const c of visibleCats) {
107936
+ const btn = h2(
107937
+ doc,
107938
+ "button",
107939
+ { type: "button", class: "myio-gcdr-about__tile" },
107940
+ icon(doc, ICONS[c.icon](22), "myio-gcdr-about__tileicon"),
107941
+ h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: t(`about.cat.${c.key}`) }),
107942
+ h2(doc, "span", { class: "myio-gcdr-about__tiletext", text: t(`about.cat.${c.key}.text`) })
107943
+ );
107944
+ btn.addEventListener("click", () => showCategory(c));
107945
+ grid.appendChild(btn);
107946
+ }
107947
+ body.append(title, intro, grid, h2(doc, "p", { class: "myio-gcdr-about__tagline", text: t("about.tagline") }));
107948
+ };
107949
+ const showCategory = (c) => {
107950
+ body.textContent = "";
107951
+ const back = h2(doc, "button", { type: "button", class: "myio-gcdr-login__link myio-gcdr-about__back" }, icon(doc, ICONS.arrowLeft(14)), ` ${t("about.back")}`);
107952
+ back.addEventListener("click", () => {
107953
+ showGrid();
107954
+ body.querySelector("button")?.focus();
107955
+ });
107956
+ const title = h2(doc, "h2", { class: "myio-gcdr-about__title", text: t(`about.cat.${c.key}`) });
107957
+ const grid = h2(doc, "div", { class: "myio-gcdr-about__grid" });
107958
+ for (const it of c.items) {
107959
+ const label = t(`about.item.${it.key}`);
107960
+ if (it.health) {
107961
+ const dot = h2(doc, "span", { class: "myio-gcdr-about__dot", "data-state": "checking" });
107962
+ const state6 = h2(doc, "span", { class: "myio-gcdr-about__health", role: "status" }, dot, h2(doc, "span", { text: t("about.health.checking") }));
107963
+ grid.appendChild(h2(
107964
+ doc,
107965
+ "div",
107966
+ { class: "myio-gcdr-about__tile", "aria-disabled": "true" },
107967
+ h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: label }),
107968
+ state6
107969
+ ));
107970
+ checkHealth(dot, state6.lastChild);
107971
+ continue;
107972
+ }
107973
+ const href = it.to ? it.web ? web ? `${web}${it.to}` : void 0 : it.to : void 0;
107974
+ if (it.web && !href) continue;
107975
+ if (!href) {
107976
+ grid.appendChild(h2(
107977
+ doc,
107978
+ "div",
107979
+ { class: "myio-gcdr-about__tile", "aria-disabled": "true" },
107980
+ h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: label }),
107981
+ h2(doc, "span", { class: "myio-gcdr-about__tiletext", text: t("about.soon") })
107982
+ ));
107983
+ continue;
107984
+ }
107985
+ grid.appendChild(h2(
107986
+ doc,
107987
+ "a",
107988
+ { class: "myio-gcdr-about__tile", href, target: "_blank", rel: "noopener noreferrer" },
107989
+ h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: label }),
107990
+ h2(doc, "span", { class: "myio-gcdr-about__tiletext" }, `${t("about.open")} `, icon(doc, ICONS.external(12)))
107991
+ ));
107992
+ }
107993
+ body.append(back, title, grid);
107994
+ back.focus();
107995
+ };
107996
+ const checkHealth = (dot, label) => {
107997
+ if (!opts.healthUrl) return;
107998
+ const f = opts.fetchImpl ?? (typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0);
107999
+ if (!f) return;
108000
+ healthAbort?.abort();
108001
+ const ac = new AbortController();
108002
+ healthAbort = ac;
108003
+ const timer = setTimeout(() => ac.abort(), 5e3);
108004
+ f(opts.healthUrl, { signal: ac.signal, credentials: "omit" }).then((r) => r.ok).catch(() => false).then((up4) => {
108005
+ clearTimeout(timer);
108006
+ if (ac.signal.aborted && healthAbort !== ac) return;
108007
+ dot.setAttribute("data-state", up4 ? "online" : "offline");
108008
+ label.textContent = t(up4 ? "about.health.online" : "about.health.offline");
108009
+ });
108010
+ };
108011
+ showGrid();
108012
+ return () => healthAbort?.abort();
108013
+ }
108014
+ function renderSignedOutPrompt(el2, ctx, text2) {
108015
+ const doc = el2.ownerDocument;
108016
+ const { body } = ctx.panel({ eyebrow: "", fill: true, logo: false });
108017
+ const band = body.parentElement?.querySelector(".myio-gcdr-panel__band");
108018
+ band?.remove();
108019
+ body.appendChild(
108020
+ h2(
108021
+ doc,
108022
+ "div",
108023
+ { class: "myio-gcdr-prompt" },
108024
+ icon(doc, ICONS.lock(28), "myio-gcdr-prompt__icon"),
108025
+ h2(doc, "p", { class: "myio-gcdr-prompt__text", text: text2 })
108026
+ )
108027
+ );
108028
+ }
108029
+
108030
+ // src/components/myio-gcdr-login/i18n.ts
108031
+ var PT = {
108032
+ "login.eyebrow": "Acesso",
108033
+ "login.title": "Login",
108034
+ "login.email": "E-mail",
108035
+ "login.password": "Senha",
108036
+ "login.rememberMe": "Lembrar de mim",
108037
+ "login.forgotPassword": "Esqueceu a senha?",
108038
+ "login.signIn": "Entrar",
108039
+ "login.signingIn": "Entrando...",
108040
+ "login.noAccount": "N\xE3o tem uma conta?",
108041
+ "login.createAccount": "Criar conta",
108042
+ "login.emailRequired": "Informe o seu e-mail.",
108043
+ "login.emailInvalid": "Informe um e-mail v\xE1lido, como nome@empresa.com.",
108044
+ "login.emailPlaceholder": "nome@empresa.com",
108045
+ // new
108046
+ "login.passwordRequired": "Informe a sua senha.",
108047
+ "login.showPassword": "Mostrar senha",
108048
+ "login.hidePassword": "Ocultar senha",
108049
+ "login.capsLockOn": "Caps Lock est\xE1 ativado.",
108050
+ "login.notYou": "N\xE3o \xE9 voc\xEA?",
108051
+ "login.askAdmin": "Precisa de acesso? Fale com o administrador do sistema.",
108052
+ "login.newTab": "(abre em nova aba)",
108053
+ "login.gcdrWeb": "Entrar pelo GCDR Web",
108054
+ "login.support": "Falar com o suporte",
108055
+ "login.leaving": "Saindo...",
108056
+ "errors.invalidCredentials": "E-mail ou senha inv\xE1lidos",
108057
+ "errors.networkError": "Erro de conex\xE3o. Verifique sua internet.",
108058
+ "errors.loginFailed": "N\xE3o foi poss\xEDvel entrar no momento. Tente novamente em instantes.",
108059
+ "errors.lockedTitle": "Conta bloqueada",
108060
+ "errors.lockedText": "Esta conta foi bloqueada ap\xF3s 6 tentativas de login com senha incorreta (ou por um administrador). Por seguran\xE7a, somente um administrador pode liberar o acesso \u2014 os administradores j\xE1 foram avisados por e-mail.",
108061
+ "errors.attemptsLeft_one": "Senha incorreta \u2014 resta {{count}} tentativa.",
108062
+ "errors.attemptsLeft_other": "Senha incorreta \u2014 restam {{count}} tentativas.",
108063
+ "errors.lastAttempt": "Senha incorreta \u2014 esta \xE9 a sua \xFAltima tentativa.",
108064
+ "errors.lockWarning": "Na 6\xAA senha errada a conta \xE9 bloqueada e s\xF3 um administrador consegue liberar. Se n\xE3o lembra a senha, redefina agora em vez de tentar de novo.",
108065
+ "errors.goToForgot": "Esqueci minha senha \u2014 redefinir agora",
108066
+ "errors.invalidWithAttempts_one": "E-mail ou senha inv\xE1lidos. Resta {{count}} tentativa antes do bloqueio.",
108067
+ "errors.invalidWithAttempts_other": "E-mail ou senha inv\xE1lidos. Restam {{count}} tentativas antes do bloqueio.",
108068
+ "errors.captchaFailed": "N\xE3o foi poss\xEDvel confirmar que voc\xEA n\xE3o \xE9 um rob\xF4. Aguarde a verifica\xE7\xE3o e tente de novo.",
108069
+ // new
108070
+ "errors.tooManyRequests": "Muitas tentativas. Aguarde alguns minutos e tente novamente.",
108071
+ "errors.timeout": "O servidor demorou para responder. Tente novamente.",
108072
+ "errors.integrationError": "N\xE3o foi poss\xEDvel entrar no momento. Tente novamente em instantes.",
108073
+ "errors.mfaUnsupported": "Esta conta exige verifica\xE7\xE3o em duas etapas, ainda n\xE3o dispon\xEDvel nesta tela.",
108074
+ "errors.postLoginFailed": "N\xE3o foi poss\xEDvel concluir a entrada. Tente novamente.",
108075
+ "errors.leaveFailed": "N\xE3o foi poss\xEDvel sair agora. Tente novamente.",
108076
+ "errors.captchaLoadFailed": "N\xE3o foi poss\xEDvel carregar a verifica\xE7\xE3o.",
108077
+ "errors.invalidCredentialsHelp": "Confira o e-mail digitado. Se estiver correto e voc\xEA tiver certeza da senha, sua conta pode ainda n\xE3o estar liberada \u2014 {{who}}.",
108078
+ "errors.helpSupport": "fale com o suporte",
108079
+ "errors.helpAdmin": "fale com o administrador do sistema",
108080
+ "notice.sessionExpired": "Sua sess\xE3o expirou. Por favor, entre novamente.",
108081
+ "notice.sessionExpiredModal": "Sua sess\xE3o expirou. Entre novamente \u2014 esta tela ser\xE1 mantida.",
108082
+ "aside.signedOutPrompt": "Fa\xE7a o login para ter acesso \xE0s funcionalidades.",
108083
+ "about.eyebrow": "Sobre a MYIO",
108084
+ "about.title": "Medi\xE7\xE3o e atua\xE7\xE3o remota",
108085
+ "about.titleHighlight": "IoT",
108086
+ "about.text": "Escolha um assunto para ver o que voc\xEA pode acessar sem entrar na conta.",
108087
+ "about.tagline": "Efici\xEAncia | Seguran\xE7a | Sustentabilidade",
108088
+ "about.health.checking": "Verificando\u2026",
108089
+ "about.health.online": "No ar",
108090
+ "about.health.offline": "Indispon\xEDvel",
108091
+ "about.back": "Voltar",
108092
+ "about.open": "Abrir",
108093
+ "about.soon": "Em breve",
108094
+ "about.cat.wiki": "Wiki",
108095
+ "about.cat.wiki.text": "Base de conhecimento, guias e respostas.",
108096
+ "about.cat.support": "Atendimento",
108097
+ "about.cat.support.text": "Chamados, tickets e d\xFAvidas.",
108098
+ "about.cat.integrations": "Integra\xE7\xF5es",
108099
+ "about.cat.integrations.text": "Documenta\xE7\xE3o das APIs e guias de integra\xE7\xE3o.",
108100
+ "about.cat.systems": "Sistemas",
108101
+ "about.cat.systems.text": "Acesso aos sistemas MYIO.",
108102
+ "about.cat.institutional": "Institucional",
108103
+ "about.cat.institutional.text": "Sobre a MYIO, site, privacidade e termos.",
108104
+ "about.cat.status": "Status",
108105
+ "about.cat.status.text": "Situa\xE7\xE3o dos sistemas agora.",
108106
+ "about.item.wikiHome": "Wiki p\xFAblica",
108107
+ "about.item.wikiSearch": "Buscar na wiki",
108108
+ "about.item.accountGuide": "Acesso \xE0 conta",
108109
+ "about.item.openTicket": "Abrir chamado",
108110
+ "about.item.forgotPassword": "Esqueci minha senha",
108111
+ "about.item.docsAlarms": "Alarms",
108112
+ "about.item.docsGcdr": "GCDR",
108113
+ "about.item.docsIngestion": "Ingestion",
108114
+ "about.item.docsThingsboard": "ThingsBoard",
108115
+ "about.item.integrationsGuide": "Guia de integra\xE7\xF5es",
108116
+ "about.item.newIntegration": "Cadastrar integra\xE7\xE3o",
108117
+ "about.item.app": "App MYIO",
108118
+ "about.item.dashboards": "Dashboards",
108119
+ "about.item.alarms": "Alarmes",
108120
+ "about.item.site": "Site da MYIO",
108121
+ "about.item.privacy": "Privacidade",
108122
+ "about.item.terms": "Termos de servi\xE7o",
108123
+ "about.item.gcdrHealth": "GCDR",
108124
+ "toolbar.toDark": "Usar tema escuro",
108125
+ "toolbar.toLight": "Usar tema claro",
108126
+ "toolbar.language": "Idioma",
108127
+ "modal.close": "Fechar"
108128
+ };
108129
+ var EN = {
108130
+ "login.eyebrow": "Access",
108131
+ "login.title": "Login",
108132
+ "login.email": "Email",
108133
+ "login.password": "Password",
108134
+ "login.rememberMe": "Remember me",
108135
+ "login.forgotPassword": "Forgot password?",
108136
+ "login.signIn": "Sign In",
108137
+ "login.signingIn": "Signing in...",
108138
+ "login.noAccount": "Don't have an account?",
108139
+ "login.createAccount": "Create account",
108140
+ "login.emailRequired": "Enter your e-mail.",
108141
+ "login.emailInvalid": "Enter a valid e-mail, like name@company.com.",
108142
+ "login.emailPlaceholder": "name@company.com",
108143
+ "login.passwordRequired": "Enter your password.",
108144
+ "login.showPassword": "Show password",
108145
+ "login.hidePassword": "Hide password",
108146
+ "login.capsLockOn": "Caps Lock is on.",
108147
+ "login.notYou": "Not you?",
108148
+ "login.askAdmin": "Need access? Contact your system administrator.",
108149
+ "login.newTab": "(opens in a new tab)",
108150
+ "login.gcdrWeb": "Sign in on GCDR Web",
108151
+ "login.support": "Contact support",
108152
+ "login.leaving": "Leaving...",
108153
+ "errors.invalidCredentials": "Invalid e-mail or password",
108154
+ "errors.networkError": "Network error. Please check your connection.",
108155
+ "errors.loginFailed": "Unable to sign in right now. Please try again shortly.",
108156
+ "errors.lockedTitle": "Account locked",
108157
+ "errors.lockedText": "This account was locked after 6 sign-in attempts with a wrong password (or by an administrator). For security, only an administrator can unlock it \u2014 the administrators were already notified by e-mail.",
108158
+ "errors.attemptsLeft_one": "Wrong password \u2014 {{count}} attempt left.",
108159
+ "errors.attemptsLeft_other": "Wrong password \u2014 {{count}} attempts left.",
108160
+ "errors.lastAttempt": "Wrong password \u2014 this is your last attempt.",
108161
+ "errors.lockWarning": "On the 6th wrong password the account is locked and only an administrator can unlock it. If you don't remember the password, reset it now instead of trying again.",
108162
+ "errors.goToForgot": "Forgot my password \u2014 reset now",
108163
+ "errors.invalidWithAttempts_one": "Invalid e-mail or password. {{count}} attempt left before the lock.",
108164
+ "errors.invalidWithAttempts_other": "Invalid e-mail or password. {{count}} attempts left before the lock.",
108165
+ "errors.captchaFailed": "Could not confirm you are not a robot. Wait for the check and try again.",
108166
+ "errors.tooManyRequests": "Too many attempts. Wait a few minutes and try again.",
108167
+ "errors.timeout": "The server took too long to answer. Please try again.",
108168
+ "errors.integrationError": "Unable to sign in right now. Please try again shortly.",
108169
+ "errors.mfaUnsupported": "This account requires two-step verification, not yet available on this screen.",
108170
+ "errors.postLoginFailed": "Could not finish signing in. Please try again.",
108171
+ "errors.leaveFailed": "Could not leave right now. Please try again.",
108172
+ "errors.captchaLoadFailed": "Could not load the verification.",
108173
+ "errors.invalidCredentialsHelp": "Check the e-mail you typed. If it is right and you are sure of the password, your account may not be enabled yet \u2014 {{who}}.",
108174
+ "errors.helpSupport": "contact support",
108175
+ "errors.helpAdmin": "contact your system administrator",
108176
+ "notice.sessionExpired": "Your session has expired. Please sign in again.",
108177
+ "notice.sessionExpiredModal": "Your session has expired. Sign in again \u2014 this screen will be kept.",
108178
+ "aside.signedOutPrompt": "Sign in to access the features.",
108179
+ "about.eyebrow": "About MYIO",
108180
+ "about.title": "Remote metering and control",
108181
+ "about.titleHighlight": "IoT",
108182
+ "about.text": "Pick a subject to see what you can reach without signing in.",
108183
+ "about.tagline": "Efficiency | Safety | Sustainability",
108184
+ "about.health.checking": "Checking\u2026",
108185
+ "about.health.online": "Up",
108186
+ "about.health.offline": "Unavailable",
108187
+ "about.back": "Back",
108188
+ "about.open": "Open",
108189
+ "about.soon": "Coming soon",
108190
+ "about.cat.wiki": "Wiki",
108191
+ "about.cat.wiki.text": "Knowledge base, guides and answers.",
108192
+ "about.cat.support": "Support",
108193
+ "about.cat.support.text": "Tickets and questions.",
108194
+ "about.cat.integrations": "Integrations",
108195
+ "about.cat.integrations.text": "API documentation and integration guides.",
108196
+ "about.cat.systems": "Systems",
108197
+ "about.cat.systems.text": "Access to the MYIO systems.",
108198
+ "about.cat.institutional": "About us",
108199
+ "about.cat.institutional.text": "About MYIO, website, privacy and terms.",
108200
+ "about.cat.status": "Status",
108201
+ "about.cat.status.text": "How the systems are right now.",
108202
+ "about.item.wikiHome": "Public wiki",
108203
+ "about.item.wikiSearch": "Search the wiki",
108204
+ "about.item.accountGuide": "Account access",
108205
+ "about.item.openTicket": "Open a ticket",
108206
+ "about.item.forgotPassword": "Forgot my password",
108207
+ "about.item.docsAlarms": "Alarms",
108208
+ "about.item.docsGcdr": "GCDR",
108209
+ "about.item.docsIngestion": "Ingestion",
108210
+ "about.item.docsThingsboard": "ThingsBoard",
108211
+ "about.item.integrationsGuide": "Integrations guide",
108212
+ "about.item.newIntegration": "Submit an integration",
108213
+ "about.item.app": "MYIO App",
108214
+ "about.item.dashboards": "Dashboards",
108215
+ "about.item.alarms": "Alarms",
108216
+ "about.item.site": "MYIO website",
108217
+ "about.item.privacy": "Privacy",
108218
+ "about.item.terms": "Terms of service",
108219
+ "about.item.gcdrHealth": "GCDR",
108220
+ "toolbar.toDark": "Use dark theme",
108221
+ "toolbar.toLight": "Use light theme",
108222
+ "toolbar.language": "Language",
108223
+ "modal.close": "Close"
108224
+ };
108225
+ var DICTIONARIES = { "pt-BR": PT, en: EN };
108226
+ function interpolate(text2, vars) {
108227
+ if (!vars) return text2;
108228
+ return text2.replace(/\{\{(\w+)\}\}/g, (_m, k) => vars[k] != null ? String(vars[k]) : "");
108229
+ }
108230
+ function translate(locale, key, vars, overrides) {
108231
+ let k = key;
108232
+ if (vars && typeof vars.count === "number") {
108233
+ const cat = new Intl.PluralRules(locale).select(vars.count);
108234
+ k = `${key}_${cat === "one" ? "one" : "other"}`;
108235
+ }
108236
+ const text2 = overrides?.[locale]?.[k] ?? DICTIONARIES[locale][k] ?? overrides?.["pt-BR"]?.[k] ?? DICTIONARIES["pt-BR"][k] ?? k;
108237
+ return interpolate(text2, vars);
108238
+ }
108239
+ function localize(value, locale) {
108240
+ if (value == null) return "";
108241
+ if (typeof value === "string") return value;
108242
+ return value[locale] ?? value["pt-BR"] ?? value.en ?? "";
108243
+ }
108244
+ function detectLocale(stored) {
108245
+ if (stored === "pt-BR" || stored === "en") return stored;
108246
+ const nav = typeof navigator !== "undefined" ? navigator.language || "" : "";
108247
+ return nav.toLowerCase().startsWith("en") ? "en" : "pt-BR";
108248
+ }
108249
+
108250
+ // src/components/myio-gcdr-login/styles.ts
108251
+ var STYLE_VERSION = "1";
108252
+ var STYLE_ATTR = "data-myio-gcdr-version";
108253
+ var REFS_ATTR = "data-myio-gcdr-refs";
108254
+ var FONT_ID = "myio-gcdr-font-nunito";
108255
+ var CSS3 = `
108256
+ .myio-gcdr-shell, .myio-gcdr-overlay {
108257
+ --myio-gcdr-accent: #6B4ABF;
108258
+ --myio-gcdr-accent-hover: #5A3CA8;
108259
+ --myio-gcdr-card: #FBFAFE;
108260
+ --myio-gcdr-ring: #E1DAF4;
108261
+ --myio-gcdr-title: #1E1B2E;
108262
+ --myio-gcdr-text: #55506A;
108263
+ --myio-gcdr-footer: #F0ECFA;
108264
+ --myio-gcdr-input: #FFFFFF;
108265
+ --myio-gcdr-input-border: #D1D5DB;
108266
+ --myio-gcdr-link: #6B4ABF;
108267
+ --myio-gcdr-pill: rgba(255,255,255,0.70);
108268
+ --myio-gcdr-aside-band: #2E8B57;
108269
+ box-sizing: border-box;
108270
+ font-family: 'Nunito', ui-sans-serif, system-ui, sans-serif;
108271
+ line-height: 1.5;
108272
+ color: var(--myio-gcdr-title);
108273
+ -webkit-font-smoothing: antialiased;
108274
+ }
108275
+ .myio-gcdr-shell[data-theme="dark"], .myio-gcdr-overlay[data-theme="dark"] {
108276
+ --myio-gcdr-card: #1E1A2E;
108277
+ --myio-gcdr-ring: #3A3158;
108278
+ --myio-gcdr-title: #FFFFFF;
108279
+ --myio-gcdr-text: #D1D5DB;
108280
+ --myio-gcdr-footer: #251F3A;
108281
+ --myio-gcdr-input: #2B2440;
108282
+ --myio-gcdr-input-border: #3A3158;
108283
+ --myio-gcdr-link: #B9A5F0;
108284
+ --myio-gcdr-pill: rgba(43,36,64,0.80);
108285
+ }
108286
+ .myio-gcdr-shell [hidden], .myio-gcdr-overlay [hidden] { display: none !important; }
108287
+ .myio-gcdr-shell *, .myio-gcdr-shell *::before, .myio-gcdr-shell *::after,
108288
+ .myio-gcdr-overlay *, .myio-gcdr-overlay *::before, .myio-gcdr-overlay *::after { box-sizing: border-box; }
108289
+
108290
+ /* \u2500\u2500 Shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
108291
+ .myio-gcdr-shell {
108292
+ position: relative; min-height: 100%; width: 100%;
108293
+ display: flex; flex-direction: column; align-items: center;
108294
+ padding: 16px; isolation: isolate;
108295
+ }
108296
+ .myio-gcdr-shell__wallpaper {
108297
+ position: absolute; inset: 0; z-index: -1; overflow: hidden;
108298
+ background-color: #EEEAF8;
108299
+ background-image: var(--myio-gcdr-wp, none), linear-gradient(180deg, #DCD2F3 0%, #EEEAF8 45%, #F7F5FC 100%);
108300
+ background-position: center; background-size: cover; background-repeat: no-repeat;
108301
+ }
108302
+ .myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper {
108303
+ background-color: #15121F;
108304
+ background-image: var(--myio-gcdr-wp, none), linear-gradient(180deg, #1B1530 0%, #15121F 45%, #111827 100%);
108305
+ }
108306
+ .myio-gcdr-shell__wallpaper::before { content: ''; position: absolute; inset: 0;
108307
+ background: rgba(255,255,255,0.22); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
108308
+ .myio-gcdr-shell__wallpaper::after { content: ''; position: absolute; inset: 0;
108309
+ background: linear-gradient(135deg, rgba(107,74,191,0.34) 0%, rgba(107,74,191,0.14) 50%, rgba(107,74,191,0.34) 100%); }
108310
+ .myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper::before { background: rgba(255,255,255,0.05); }
108311
+ .myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper::after {
108312
+ background: linear-gradient(135deg, rgba(45,22,105,0.55) 0%, rgba(27,21,48,0.30) 50%, rgba(45,22,105,0.55) 100%); }
108313
+
108314
+ .myio-gcdr-shell__top { width: 100%; }
108315
+ .myio-gcdr-shell__block { width: 100%; max-width: 28rem; margin: auto 0; display: flex; flex-direction: column; }
108316
+ .myio-gcdr-shell[data-size="lg"] .myio-gcdr-shell__block { max-width: 32rem; }
108317
+ .myio-gcdr-shell[data-size="xl"] .myio-gcdr-shell__block { max-width: 37rem; }
108318
+ @media (min-width: 1024px) {
108319
+ .myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__block { max-width: 72rem; }
108320
+ }
108321
+ .myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 28rem; }
108322
+ @media (min-width: 640px) { .myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 42rem; } }
108323
+ @media (min-width: 1024px) { .myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 1800px; padding: 0 12px; } }
108324
+
108325
+ .myio-gcdr-shell__toprow { display: flex; justify-content: flex-end; margin-bottom: 12px; }
108326
+ .myio-gcdr-shell__pill {
108327
+ display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; justify-content: flex-end;
108328
+ border-radius: 9999px; background: var(--myio-gcdr-pill); padding: 4px 8px;
108329
+ box-shadow: 0 1px 2px rgba(0,0,0,0.05); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
108330
+ }
108331
+ .myio-gcdr-shell__iconbtn {
108332
+ display: inline-flex; align-items: center; gap: 6px; min-height: 36px; min-width: 36px; justify-content: center;
108333
+ border: 0; background: transparent; color: var(--myio-gcdr-text); border-radius: 8px; padding: 6px 10px;
108334
+ font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
108335
+ }
108336
+ .myio-gcdr-shell__iconbtn:hover { background: rgba(107,74,191,0.10); color: var(--myio-gcdr-title); }
108337
+ .myio-gcdr-shell__iconbtn:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
108338
+
108339
+ .myio-gcdr-shell__split { display: flex; flex-direction: column; gap: 24px; }
108340
+ @media (min-width: 1024px) {
108341
+ .myio-gcdr-shell__split { flex-direction: row; align-items: stretch; }
108342
+ .myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__split { height: clamp(600px, calc(100vh - 10rem), 880px); }
108343
+ .myio-gcdr-shell__aside { flex: 1 1 0; min-width: 0; display: flex; }
108344
+ .myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__main { flex: 0 0 28rem; }
108345
+ .myio-gcdr-shell[data-width="cockpit"][data-has-aside="true"] .myio-gcdr-shell__main { flex: 1 1 0; }
108346
+ }
108347
+ .myio-gcdr-shell__main { display: flex; min-width: 0; min-height: 0; }
108348
+ .myio-gcdr-shell__main > * { flex: 1 1 auto; min-width: 0; }
108349
+ @media (max-width: 1023.98px) {
108350
+ .myio-gcdr-shell[data-aside-compact="hide"] .myio-gcdr-shell__aside { display: none; }
108351
+ .myio-gcdr-shell[data-aside-compact="stack"] .myio-gcdr-shell__aside { order: 2; display: flex; }
108352
+ }
108353
+ .myio-gcdr-shell__aside[hidden], .myio-gcdr-shell__below[hidden], .myio-gcdr-shell__top[hidden] { display: none !important; }
108354
+ .myio-gcdr-shell__below { margin-top: 16px; text-align: center; }
108355
+ .myio-gcdr-shell__build { display: inline-block; font-size: 12px; color: #55506A; border-radius: 9999px;
108356
+ background: var(--myio-gcdr-pill); padding: 4px 12px; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
108357
+ .myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__build { color: #E5E7EB; }
108358
+ .myio-gcdr-shell__slot:focus { outline: none; }
108359
+ .myio-gcdr-sr { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
108360
+
108361
+ /* \u2500\u2500 Card panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
108362
+ .myio-gcdr-panel {
108363
+ display: flex; flex-direction: column; overflow: hidden; width: 100%;
108364
+ border-radius: 16px; background: var(--myio-gcdr-card);
108365
+ box-shadow: 0 18px 50px rgba(40,20,90,0.30), 0 0 0 1px var(--myio-gcdr-ring);
108366
+ }
108367
+ .myio-gcdr-panel[data-fill="true"] { height: 100%; }
108368
+ .myio-gcdr-panel__band {
108369
+ position: relative; display: flex; flex-shrink: 0; align-items: center; justify-content: space-between; gap: 16px;
108370
+ height: 68px; padding: 0 32px; background: var(--myio-gcdr-band, var(--myio-gcdr-accent));
108371
+ }
108372
+ .myio-gcdr-panel__tint { position: absolute; inset: 0; background: var(--myio-gcdr-tint, transparent); pointer-events: none; }
108373
+ .myio-gcdr-panel__eyebrow { position: relative; font-size: 14px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.14em; color: #FFFFFF; }
108374
+ .myio-gcdr-panel__logo { position: relative; height: 28px; width: auto; display: block; }
108375
+ .myio-gcdr-panel__wordmark { position: relative; color: #fff; font-weight: 900; font-size: 20px; letter-spacing: 0.04em; }
108376
+ .myio-gcdr-panel__body { padding: 28px 32px 32px; flex: 1 1 auto; overflow-y: auto; min-height: 0; }
108377
+ .myio-gcdr-panel__title { margin: 0 0 20px; font-size: 26px; font-weight: 800; line-height: 1.2; color: var(--myio-gcdr-title); }
108378
+ .myio-gcdr-panel__footer { padding: 16px 32px; text-align: center; font-size: 14px; color: var(--myio-gcdr-text);
108379
+ background: var(--myio-gcdr-footer); border-top: 1px solid var(--myio-gcdr-ring); }
108380
+
108381
+ /* \u2500\u2500 Form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
108382
+ .myio-gcdr-login__form { display: flex; flex-direction: column; gap: 20px; margin: 0; }
108383
+ .myio-gcdr-login__field { display: flex; flex-direction: column; gap: 6px; }
108384
+ .myio-gcdr-login__label { font-size: 14px; font-weight: 700; color: var(--myio-gcdr-title); }
108385
+ .myio-gcdr-login__control { position: relative; display: flex; }
108386
+ .myio-gcdr-login__input {
108387
+ width: 100%; font: inherit; font-size: 16px; color: var(--myio-gcdr-title);
108388
+ background: var(--myio-gcdr-input); border: 1px solid var(--myio-gcdr-input-border);
108389
+ border-radius: 12px; padding: 10px 14px; outline: none; transition: border-color .15s, box-shadow .15s;
108390
+ }
108391
+ .myio-gcdr-login__input::placeholder { color: #9CA3AF; }
108392
+ .myio-gcdr-login__input:focus { border-color: var(--myio-gcdr-accent); box-shadow: 0 0 0 3px rgba(107,74,191,0.30); }
108393
+ .myio-gcdr-login__input[aria-invalid="true"] { border-color: #FCA5A5; }
108394
+ .myio-gcdr-login__input[readonly] { opacity: .75; }
108395
+ .myio-gcdr-login__input--password { padding-right: 48px; }
108396
+ .myio-gcdr-login__eye {
108397
+ position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 40px; height: 40px;
108398
+ display: inline-flex; align-items: center; justify-content: center; border: 0; background: transparent;
108399
+ color: var(--myio-gcdr-text); border-radius: 8px; cursor: pointer;
108400
+ }
108401
+ .myio-gcdr-login__eye:focus-visible { outline: 2px solid var(--myio-gcdr-accent); }
108402
+ .myio-gcdr-login__fielderror { font-size: 13px; color: #DC2626; }
108403
+ .myio-gcdr-shell[data-theme="dark"] .myio-gcdr-login__fielderror { color: #FCA5A5; }
108404
+ .myio-gcdr-login__hint { font-size: 12px; color: #B45309; }
108405
+ .myio-gcdr-login__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
108406
+ .myio-gcdr-login__remember { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; color: var(--myio-gcdr-text); cursor: pointer; min-height: 32px; }
108407
+ .myio-gcdr-login__remember input { width: 16px; height: 16px; accent-color: var(--myio-gcdr-accent); }
108408
+ .myio-gcdr-login__link { font-size: 14px; font-weight: 600; color: var(--myio-gcdr-link); text-decoration: none; background: none; border: 0; padding: 0; cursor: pointer; font-family: inherit; }
108409
+ .myio-gcdr-login__link:hover { color: var(--myio-gcdr-accent-hover); text-decoration: underline; }
108410
+ .myio-gcdr-login__submit {
108411
+ display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 48px;
108412
+ border: 0; border-radius: 12px; padding: 12px 24px; font: inherit; font-size: 16px; font-weight: 700;
108413
+ color: #fff; background: var(--myio-gcdr-accent); cursor: pointer; transition: background .15s, opacity .15s;
108414
+ }
108415
+ .myio-gcdr-login__submit:hover { background: var(--myio-gcdr-accent-hover); }
108416
+ .myio-gcdr-login__submit[aria-disabled="true"], .myio-gcdr-login__submit:disabled { opacity: .55; cursor: not-allowed; }
108417
+ .myio-gcdr-login__submit:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
108418
+ .myio-gcdr-login__submit[data-style="hotPage"] { border-radius: 10px; min-height: 52px; font-size: 17px; letter-spacing: .01em; box-shadow: 0 6px 16px rgba(107,74,191,0.35); }
108419
+ .myio-gcdr-login__spin { display: inline-flex; animation: myio-gcdr-spin 0.9s linear infinite; }
108420
+ @keyframes myio-gcdr-spin { to { transform: rotate(360deg); } }
108421
+
108422
+ /* \u2500\u2500 Banners \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
108423
+ .myio-gcdr-login__alerts { display: flex; flex-direction: column; gap: 12px; }
108424
+ .myio-gcdr-login__alerts:empty { display: none; }
108425
+ .myio-gcdr-login__alerts:not(:empty) { margin-bottom: 20px; }
108426
+ .myio-gcdr-login__field > .myio-gcdr-login__link { align-self: flex-start; }
108427
+ .myio-gcdr-banner { display: flex; gap: 10px; align-items: flex-start; border-radius: 12px; padding: 12px 14px; font-size: 14px; line-height: 1.45; border: 1px solid; }
108428
+ .myio-gcdr-banner:focus { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
108429
+ .myio-gcdr-banner__icon { flex-shrink: 0; margin-top: 2px; }
108430
+ .myio-gcdr-banner__body { display: flex; flex-direction: column; gap: 6px; }
108431
+ .myio-gcdr-banner__title { font-weight: 800; }
108432
+ .myio-gcdr-banner--error { background: #FEF2F2; border-color: #FECACA; color: #991B1B; }
108433
+ .myio-gcdr-banner--warning { background: #FFFBEB; border-color: #FDE68A; color: #92400E; }
108434
+ .myio-gcdr-banner--info { background: #F5F3FF; border-color: #DDD6FE; color: #4C1D95; }
108435
+ .myio-gcdr-shell[data-theme="dark"] .myio-gcdr-banner--error { background: rgba(127,29,29,0.35); border-color: rgba(248,113,113,0.45); color: #FECACA; }
108436
+ .myio-gcdr-shell[data-theme="dark"] .myio-gcdr-banner--warning { background: rgba(120,53,15,0.35); border-color: rgba(251,191,36,0.45); color: #FDE68A; }
108437
+ .myio-gcdr-shell[data-theme="dark"] .myio-gcdr-banner--info { background: rgba(76,29,149,0.35); border-color: rgba(167,139,250,0.45); color: #DDD6FE; }
108438
+ .myio-gcdr-banner a, .myio-gcdr-banner button { color: inherit; font-weight: 700; text-decoration: underline; background: none; border: 0; padding: 0; font: inherit; cursor: pointer; text-align: left; }
108439
+
108440
+ /* \u2500\u2500 Aside: about / signed-out prompt \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
108441
+ .myio-gcdr-about__intro { color: var(--myio-gcdr-text); font-size: 14px; margin: 0 0 16px; }
108442
+ .myio-gcdr-about__title { font-size: 24px; font-weight: 800; margin: 0 0 6px; color: var(--myio-gcdr-title); }
108443
+ .myio-gcdr-about__title em { font-style: normal; color: var(--myio-gcdr-aside-band); }
108444
+ .myio-gcdr-about__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
108445
+ .myio-gcdr-about__tile {
108446
+ display: flex; flex-direction: column; gap: 6px; text-align: left; padding: 14px; border-radius: 12px; min-height: 110px;
108447
+ border: 1px solid var(--myio-gcdr-ring); background: var(--myio-gcdr-input); color: var(--myio-gcdr-title);
108448
+ font: inherit; cursor: pointer; text-decoration: none; transition: transform .15s, box-shadow .15s;
108449
+ }
108450
+ .myio-gcdr-about__tile:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(40,20,90,0.12); }
108451
+ .myio-gcdr-about__tile:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
108452
+ .myio-gcdr-about__tile[aria-disabled="true"] { opacity: .6; cursor: default; }
108453
+ .myio-gcdr-about__tileicon { color: var(--myio-gcdr-aside-band); }
108454
+ .myio-gcdr-about__tiletitle { font-weight: 800; font-size: 15px; }
108455
+ .myio-gcdr-about__tiletext { font-size: 13px; color: var(--myio-gcdr-text); }
108456
+ .myio-gcdr-about__back { margin-bottom: 12px; }
108457
+ .myio-gcdr-about__tagline { margin-top: 16px; font-size: 13px; font-weight: 700; color: var(--myio-gcdr-text); text-align: center; }
108458
+ .myio-gcdr-about__health { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; }
108459
+ .myio-gcdr-about__dot { width: 8px; height: 8px; border-radius: 50%; background: #9CA3AF; }
108460
+ .myio-gcdr-about__dot[data-state="online"] { background: #16A34A; }
108461
+ .myio-gcdr-about__dot[data-state="offline"] { background: #DC2626; }
108462
+ .myio-gcdr-prompt { display: flex; flex: 1; flex-direction: column; align-items: center; justify-content: center; gap: 16px; padding: 32px 20px; text-align: center; height: 100%; }
108463
+ .myio-gcdr-prompt__icon { display: inline-flex; width: 56px; height: 56px; align-items: center; justify-content: center; border-radius: 50%; background: #6B4ABF; color: #fff; }
108464
+ .myio-gcdr-prompt__text { margin: 0; font-size: 22px; font-weight: 800; line-height: 1.35; color: var(--myio-gcdr-title); }
108465
+
108466
+ /* \u2500\u2500 Modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
108467
+ .myio-gcdr-overlay { position: fixed; inset: 0; overflow-y: auto; display: flex; }
108468
+ .myio-gcdr-overlay[data-scope="element"] { position: absolute; }
108469
+ .myio-gcdr-overlay__layer { position: fixed; inset: 0; pointer-events: none; }
108470
+ .myio-gcdr-overlay[data-scope="element"] .myio-gcdr-overlay__layer { position: absolute; }
108471
+ .myio-gcdr-overlay__content { position: relative; width: 100%; min-height: 100%; display: flex; }
108472
+ .myio-gcdr-overlay__content > .myio-gcdr-shell { min-height: 100%; background: transparent; }
108473
+ .myio-gcdr-overlay__close { position: absolute; top: 12px; right: 12px; z-index: 2; }
108474
+ @media (prefers-reduced-motion: reduce) {
108475
+ .myio-gcdr-shell *, .myio-gcdr-overlay * { transition: none !important; animation: none !important; }
108476
+ }
108477
+ `;
108478
+ function rootTarget(container) {
108479
+ const root = container.getRootNode ? container.getRootNode() : document;
108480
+ const doc = container.ownerDocument || document;
108481
+ if (typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot) return { head: root, doc };
108482
+ return { head: doc.head || doc.documentElement, doc };
108483
+ }
108484
+ function acquireStyles(container, opts = {}) {
108485
+ const { head, doc } = rootTarget(container);
108486
+ if (opts.loadFont !== false && !doc.getElementById(FONT_ID)) {
108487
+ const link = doc.createElement("link");
108488
+ link.id = FONT_ID;
108489
+ link.rel = "stylesheet";
108490
+ link.href = "https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&display=swap";
108491
+ doc.head?.appendChild(link);
108492
+ }
108493
+ let style = head.querySelector(`style[${STYLE_ATTR}="${STYLE_VERSION}"]`);
108494
+ if (!style) {
108495
+ style = doc.createElement("style");
108496
+ style.setAttribute(STYLE_ATTR, STYLE_VERSION);
108497
+ style.setAttribute(REFS_ATTR, "0");
108498
+ if (opts.nonce) style.setAttribute("nonce", opts.nonce);
108499
+ style.textContent = CSS3;
108500
+ head.appendChild(style);
108501
+ }
108502
+ const el2 = style;
108503
+ el2.setAttribute(REFS_ATTR, String((parseInt(el2.getAttribute(REFS_ATTR) || "0", 10) || 0) + 1));
108504
+ let released = false;
108505
+ return () => {
108506
+ if (released) return;
108507
+ released = true;
108508
+ const n = (parseInt(el2.getAttribute(REFS_ATTR) || "1", 10) || 1) - 1;
108509
+ if (n <= 0) el2.remove();
108510
+ else el2.setAttribute(REFS_ATTR, String(n));
108511
+ };
108512
+ }
108513
+
108514
+ // src/components/myio-gcdr-login/shell.ts
108515
+ var SLOT_NAMES = ["top", "topRight", "aside", "main", "below"];
108516
+ function buildPanel(doc, el2, opts, locale, defaultLogoUrl) {
108517
+ const root = h2(doc, "section", { class: "myio-gcdr-panel", "data-fill": opts.fill ? "true" : null });
108518
+ if (opts.accent) root.style.setProperty("--myio-gcdr-accent", opts.accent);
108519
+ if (opts.bandColor) root.style.setProperty("--myio-gcdr-band", opts.bandColor);
108520
+ if (opts.tint) root.style.setProperty("--myio-gcdr-tint", opts.tint);
108521
+ const band = h2(doc, "header", { class: "myio-gcdr-panel__band" });
108522
+ if (opts.tint) band.appendChild(h2(doc, "span", { class: "myio-gcdr-panel__tint", "aria-hidden": "true" }));
108523
+ band.appendChild(h2(doc, "span", { class: "myio-gcdr-panel__eyebrow", text: localize(opts.eyebrow, locale) }));
108524
+ if (opts.logo !== false) {
108525
+ const url = opts.logoUrl ?? defaultLogoUrl;
108526
+ const wordmark = () => h2(doc, "span", { class: "myio-gcdr-panel__wordmark", text: "MYIO" });
108527
+ if (url) {
108528
+ const img = h2(doc, "img", { class: "myio-gcdr-panel__logo", src: url, alt: "MYIO" });
108529
+ img.addEventListener("error", () => img.replaceWith(wordmark()), { once: true });
108530
+ band.appendChild(img);
108531
+ } else band.appendChild(wordmark());
108532
+ }
108533
+ root.appendChild(band);
108534
+ const body = h2(doc, "div", { class: "myio-gcdr-panel__body" });
108535
+ let title;
108536
+ if (opts.title) {
108537
+ title = h2(doc, "h1", { class: "myio-gcdr-panel__title", text: localize(opts.title, locale), tabindex: "-1" });
108538
+ body.appendChild(title);
108539
+ }
108540
+ root.appendChild(body);
108541
+ let footer;
108542
+ if (opts.footer) {
108543
+ footer = h2(doc, "footer", { class: "myio-gcdr-panel__footer" });
108544
+ root.appendChild(footer);
108545
+ }
108546
+ el2.appendChild(root);
108547
+ return { root, body, footer, title };
108548
+ }
108549
+ function createShellImpl(container, options = {}, internals = {}) {
108550
+ if (!(container instanceof HTMLElement)) throw new TypeError("[MYIO Login] container must be an HTMLElement");
108551
+ const doc = container.ownerDocument;
108552
+ const prefix = options.storageKeyPrefix ?? "myio.login.";
108553
+ const releaseStyles = acquireStyles(container, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
108554
+ let themeSetting = options.theme ?? (storageGet(`${prefix}theme`) || "system");
108555
+ let locale = options.locale ?? detectLocale(storageGet(`${prefix}locale`));
108556
+ let size = options.size ?? "md";
108557
+ let width = options.width ?? "auto";
108558
+ const show = { themeToggle: options.show?.themeToggle !== false, languageSelector: options.show?.languageSelector !== false };
108559
+ const listeners = /* @__PURE__ */ new Set();
108560
+ let destroyed = false;
108561
+ const resolvedTheme = () => themeSetting === "system" ? prefersDark() ? "dark" : "light" : themeSetting;
108562
+ const t = (key, vars) => translate(locale, key, vars, internals.messages);
108563
+ container.textContent = "";
108564
+ const root = h2(doc, "div", {
108565
+ class: "myio-gcdr-shell",
108566
+ "data-theme": resolvedTheme(),
108567
+ "data-size": size,
108568
+ "data-width": width,
108569
+ "data-aside-compact": options.asideCompact ?? "hide",
108570
+ "data-has-aside": "false",
108571
+ lang: locale
108572
+ });
108573
+ const wallpaper = h2(doc, "div", { class: "myio-gcdr-shell__wallpaper", "aria-hidden": "true" });
108574
+ const live = h2(doc, "div", { class: "myio-gcdr-sr", "aria-live": "polite", role: "status" });
108575
+ const top = h2(doc, "div", { class: "myio-gcdr-shell__top myio-gcdr-shell__slot", hidden: true });
108576
+ const block = h2(doc, "div", { class: "myio-gcdr-shell__block" });
108577
+ const toprow = h2(doc, "div", { class: "myio-gcdr-shell__toprow" });
108578
+ const pill = h2(doc, "div", { class: "myio-gcdr-shell__pill" });
108579
+ const langBtn = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn" });
108580
+ const themeBtn = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn" });
108581
+ const topRight = h2(doc, "div", { class: "myio-gcdr-shell__slot", style: "display:contents" });
108582
+ pill.append(langBtn, themeBtn, topRight);
108583
+ toprow.appendChild(pill);
108584
+ const split = h2(doc, "div", { class: "myio-gcdr-shell__split" });
108585
+ const aside = h2(doc, "section", { class: "myio-gcdr-shell__aside myio-gcdr-shell__slot", hidden: true, tabindex: "-1" });
108586
+ const main = h2(doc, "section", { class: "myio-gcdr-shell__main myio-gcdr-shell__slot", tabindex: "-1" });
108587
+ split.append(aside, main);
108588
+ const below = h2(doc, "div", { class: "myio-gcdr-shell__below myio-gcdr-shell__slot", hidden: true });
108589
+ block.append(toprow, split, below);
108590
+ root.append(wallpaper, live, top, block);
108591
+ container.appendChild(root);
108592
+ const applyWallpaper = () => {
108593
+ const wp = options.wallpaper;
108594
+ if (wp === false) {
108595
+ wallpaper.hidden = true;
108596
+ return;
108597
+ }
108598
+ wallpaper.hidden = false;
108599
+ const dark = resolvedTheme() === "dark";
108600
+ let portrait = false;
108601
+ try {
108602
+ portrait = typeof matchMedia === "function" && matchMedia("(orientation: portrait)").matches;
108603
+ } catch {
108604
+ }
108605
+ const url = wp ? dark ? portrait ? wp.mobileDark ?? wp.dark : wp.dark : portrait ? wp.mobileLight ?? wp.light : wp.light : void 0;
108606
+ if (url) wallpaper.style.setProperty("--myio-gcdr-wp", `url("${url.replace(/"/g, "%22")}")`);
108607
+ else wallpaper.style.removeProperty("--myio-gcdr-wp");
108608
+ };
108609
+ const renderControls = () => {
108610
+ langBtn.hidden = !show.languageSelector;
108611
+ themeBtn.hidden = !show.themeToggle;
108612
+ langBtn.textContent = "";
108613
+ langBtn.append(icon(doc, ICONS.globe(16)), h2(doc, "span", { text: locale === "en" ? "EN" : "PT" }));
108614
+ langBtn.setAttribute("aria-label", `${t("toolbar.language")}: ${locale === "en" ? "English" : "Portugu\xEAs"}`);
108615
+ const dark = resolvedTheme() === "dark";
108616
+ themeBtn.textContent = "";
108617
+ themeBtn.append(icon(doc, dark ? ICONS.sun(16) : ICONS.moon(16)));
108618
+ const lbl = dark ? t("toolbar.toLight") : t("toolbar.toDark");
108619
+ themeBtn.setAttribute("aria-label", lbl);
108620
+ themeBtn.setAttribute("title", lbl);
108621
+ };
108622
+ const emit = (what) => {
108623
+ for (const fn of Array.from(listeners)) safeCall("listener", fn, what);
108624
+ };
108625
+ const applyTheme = () => {
108626
+ root.setAttribute("data-theme", resolvedTheme());
108627
+ applyWallpaper();
108628
+ renderControls();
108629
+ emit("theme");
108630
+ };
108631
+ const applyLocale = () => {
108632
+ root.setAttribute("lang", locale);
108633
+ renderControls();
108634
+ emit("locale");
108635
+ };
108636
+ langBtn.addEventListener("click", () => {
108637
+ locale = locale === "en" ? "pt-BR" : "en";
108638
+ storageSet(`${prefix}locale`, locale);
108639
+ applyLocale();
108640
+ safeCall("onLocaleChange", options.onLocaleChange, locale);
108641
+ });
108642
+ themeBtn.addEventListener("click", () => {
108643
+ themeSetting = resolvedTheme() === "dark" ? "light" : "dark";
108644
+ storageSet(`${prefix}theme`, themeSetting);
108645
+ applyTheme();
108646
+ safeCall("onThemeChange", options.onThemeChange, themeSetting);
108647
+ });
108648
+ let mql = null;
108649
+ const onScheme = () => {
108650
+ if (themeSetting === "system") applyTheme();
108651
+ };
108652
+ try {
108653
+ if (typeof matchMedia === "function") {
108654
+ mql = matchMedia("(prefers-color-scheme: dark)");
108655
+ mql.addEventListener?.("change", onScheme);
108656
+ }
108657
+ } catch {
108658
+ mql = null;
108659
+ }
108660
+ const contextFor = (el2, signal) => ({
108661
+ get theme() {
108662
+ return resolvedTheme();
108663
+ },
108664
+ get locale() {
108665
+ return locale;
108666
+ },
108667
+ signal,
108668
+ on(event, fn) {
108669
+ const l = (w) => {
108670
+ if (w === event) fn(event === "theme" ? resolvedTheme() : locale);
108671
+ };
108672
+ listeners.add(l);
108673
+ const off = () => listeners.delete(l);
108674
+ signal.addEventListener("abort", off, { once: true });
108675
+ return off;
108676
+ },
108677
+ panel: (opts) => buildPanel(doc, el2, opts, locale, internals.logoUrl)
108678
+ });
108679
+ const slots = {};
108680
+ const slotEls = { top, topRight, aside, main, below };
108681
+ for (const n of SLOT_NAMES) slots[n] = { el: slotEls[n], kind: "empty", busy: false };
108682
+ const updateLayoutFlags = () => {
108683
+ root.setAttribute("data-has-aside", slots.aside.kind === "empty" ? "false" : "true");
108684
+ aside.hidden = slots.aside.kind === "empty";
108685
+ below.hidden = slots.below.kind === "empty";
108686
+ top.hidden = slots.top.kind === "empty";
108687
+ };
108688
+ const renderBuiltIn = (name, el2, ctx, b) => {
108689
+ if (b.kind === "buildInfo") {
108690
+ if (name !== "below") throw new TypeError("[MYIO Login] buildInfo is only valid in the below slot");
108691
+ el2.appendChild(h2(doc, "p", { class: "myio-gcdr-shell__build", text: b.text }));
108692
+ return;
108693
+ }
108694
+ if (name !== "aside") throw new TypeError(`[MYIO Login] ${b.kind} is only valid in the aside slot`);
108695
+ if (b.kind === "about") {
108696
+ const cleanupAbout = renderAbout(el2, ctx, t, { ...internals.about, healthUrl: b.healthUrl ?? false });
108697
+ const off2 = ctx.on("locale", () => {
108698
+ cleanupAbout();
108699
+ el2.textContent = "";
108700
+ renderAbout(el2, ctx, t, { ...internals.about, healthUrl: b.healthUrl ?? false });
108701
+ });
108702
+ return () => {
108703
+ off2();
108704
+ cleanupAbout();
108705
+ };
108706
+ }
108707
+ const text2 = () => b.text ? localize(b.text, locale) : t("aside.signedOutPrompt");
108708
+ renderSignedOutPrompt(el2, ctx, text2());
108709
+ const off = ctx.on("locale", () => {
108710
+ el2.textContent = "";
108711
+ renderSignedOutPrompt(el2, ctx, text2());
108712
+ });
108713
+ return off;
108714
+ };
108715
+ const setSlot = (name, content, opts) => {
108716
+ if (destroyed) return;
108717
+ if (!SLOT_NAMES.includes(name)) throw new TypeError(`[MYIO Login] unknown slot "${String(name)}"`);
108718
+ const s = slots[name];
108719
+ if (s.busy) {
108720
+ s.pending = { content, opts };
108721
+ queueMicrotask(() => {
108722
+ const p = s.pending;
108723
+ s.pending = void 0;
108724
+ if (p) setSlot(name, p.content, p.opts);
108725
+ });
108726
+ return;
108727
+ }
108728
+ const hadFocus = !!doc.activeElement && s.el.contains(doc.activeElement);
108729
+ s.busy = true;
108730
+ try {
108731
+ s.abort?.abort();
108732
+ if (s.cleanup) safeCall("slot cleanup", s.cleanup);
108733
+ s.cleanup = void 0;
108734
+ s.el.textContent = "";
108735
+ s.kind = "empty";
108736
+ if (content) {
108737
+ const ac = new AbortController();
108738
+ s.abort = ac;
108739
+ const ctx = contextFor(s.el, ac.signal);
108740
+ try {
108741
+ const r = typeof content === "function" ? content(s.el, ctx) : renderBuiltIn(name, s.el, ctx, content);
108742
+ if (typeof r === "function") s.cleanup = r;
108743
+ s.kind = typeof content === "function" ? "host" : "builtIn";
108744
+ } catch (err) {
108745
+ if (err instanceof TypeError && String(err.message).startsWith("[MYIO Login]")) throw err;
108746
+ console.error(`[MYIO Login] slot "${name}" renderer failed`);
108747
+ s.el.textContent = "";
108748
+ s.kind = "empty";
108749
+ }
108750
+ }
108751
+ } finally {
108752
+ s.busy = false;
108753
+ updateLayoutFlags();
108754
+ }
108755
+ const focus = opts?.focus ?? "auto";
108756
+ if (focus instanceof HTMLElement) focus.focus();
108757
+ else if (focus === "auto" && hadFocus && s.el.isConnected) {
108758
+ if (!s.el.hasAttribute("tabindex")) s.el.setAttribute("tabindex", "-1");
108759
+ s.el.focus();
108760
+ }
108761
+ if (opts?.announce) announce(localize(opts.announce, locale));
108762
+ };
108763
+ const announce = (text2) => {
108764
+ live.textContent = "";
108765
+ setTimeout(() => {
108766
+ if (!destroyed) live.textContent = text2;
108767
+ }, 30);
108768
+ };
108769
+ applyWallpaper();
108770
+ renderControls();
108771
+ if (options.buildInfo) setSlot("below", { kind: "buildInfo", text: options.buildInfo });
108772
+ const handle = {
108773
+ setSlot,
108774
+ setTheme(th) {
108775
+ if (destroyed) return;
108776
+ themeSetting = th;
108777
+ applyTheme();
108778
+ },
108779
+ setLocale(l) {
108780
+ if (destroyed || l !== "pt-BR" && l !== "en") return;
108781
+ locale = l;
108782
+ applyLocale();
108783
+ },
108784
+ setSize(sz, w) {
108785
+ if (destroyed) return;
108786
+ size = sz;
108787
+ if (w) width = w;
108788
+ root.setAttribute("data-size", size);
108789
+ root.setAttribute("data-width", width);
108790
+ },
108791
+ setShow(sh) {
108792
+ if (destroyed) return;
108793
+ if (sh.themeToggle !== void 0) show.themeToggle = sh.themeToggle;
108794
+ if (sh.languageSelector !== void 0) show.languageSelector = sh.languageSelector;
108795
+ renderControls();
108796
+ },
108797
+ getState() {
108798
+ const st = {};
108799
+ for (const n of SLOT_NAMES) st[n] = slots[n].kind;
108800
+ return { theme: resolvedTheme(), locale, size, width, slots: st };
108801
+ },
108802
+ get element() {
108803
+ return root;
108804
+ },
108805
+ destroy() {
108806
+ if (destroyed) return;
108807
+ for (const n of SLOT_NAMES) {
108808
+ const s = slots[n];
108809
+ s.abort?.abort();
108810
+ if (s.cleanup) safeCall("slot cleanup", s.cleanup);
108811
+ s.cleanup = void 0;
108812
+ }
108813
+ destroyed = true;
108814
+ listeners.clear();
108815
+ mql?.removeEventListener?.("change", onScheme);
108816
+ root.remove();
108817
+ releaseStyles();
108818
+ },
108819
+ t,
108820
+ contextFor,
108821
+ onChange(fn) {
108822
+ listeners.add(fn);
108823
+ return () => listeners.delete(fn);
108824
+ },
108825
+ announce
108826
+ };
108827
+ return handle;
108828
+ }
108829
+ function createMyioGcdrShell(container, options = {}) {
108830
+ const impl = createShellImpl(container, options);
108831
+ return {
108832
+ setSlot: impl.setSlot,
108833
+ setTheme: impl.setTheme,
108834
+ setLocale: impl.setLocale,
108835
+ setSize: impl.setSize,
108836
+ setShow: impl.setShow,
108837
+ getState: impl.getState,
108838
+ get element() {
108839
+ return impl.element;
108840
+ },
108841
+ destroy: impl.destroy
108842
+ };
108843
+ }
108844
+
108845
+ // src/components/myio-gcdr-login/controller.ts
108846
+ var EMAIL_PATTERN = /^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
108847
+ function validate(emailRaw, password) {
108848
+ const email = emailRaw.trim();
108849
+ let emailError;
108850
+ if (!email) emailError = "login.emailRequired";
108851
+ else if (!EMAIL_PATTERN.test(email)) emailError = "login.emailInvalid";
108852
+ const passwordError = password.length === 0 ? "login.passwordRequired" : void 0;
108853
+ return { email, emailError, passwordError };
108854
+ }
108855
+ function emailKey(email) {
108856
+ return email.trim().toLowerCase();
108857
+ }
108858
+ var KNOWN = /* @__PURE__ */ new Set([
108859
+ "INVALID_CREDENTIALS",
108860
+ "ACCOUNT_LOCKED",
108861
+ "CAPTCHA_FAILED",
108862
+ "TOO_MANY_REQUESTS",
108863
+ "MFA_REQUIRED",
108864
+ "NETWORK",
108865
+ "TIMEOUT",
108866
+ "SERVER",
108867
+ "INTEGRATION_ERROR",
108868
+ "CUSTOM"
108869
+ ]);
108870
+ var ALIASES = {
108871
+ UNAUTHORIZED: "INVALID_CREDENTIALS",
108872
+ HTTP_401: "INVALID_CREDENTIALS",
108873
+ ACCOUNT_PENDING: "INVALID_CREDENTIALS",
108874
+ PENDING_APPROVAL: "INVALID_CREDENTIALS",
108875
+ ACCOUNT_SUSPENDED: "INVALID_CREDENTIALS",
108876
+ ACCOUNT_INACTIVE: "INVALID_CREDENTIALS",
108877
+ EMAIL_NOT_VERIFIED: "INVALID_CREDENTIALS",
108878
+ RATE_LIMITED: "TOO_MANY_REQUESTS",
108879
+ NETWORK_ERROR: "NETWORK"
108880
+ };
108881
+ function normaliseCode(code) {
108882
+ if (typeof code !== "string") return "SERVER";
108883
+ if (KNOWN.has(code)) return code;
108884
+ return ALIASES[code] ?? "SERVER";
108885
+ }
108886
+ function usableCounter(n) {
108887
+ return typeof n === "number" && Number.isInteger(n) && n >= 1 ? n : void 0;
108888
+ }
108889
+ function normaliseResult(raw) {
108890
+ if (!raw || typeof raw !== "object" || typeof raw.ok !== "boolean") {
108891
+ return { kind: "error", code: "INTEGRATION_ERROR" };
108892
+ }
108893
+ const r = raw;
108894
+ if (r.ok) return { kind: "ok", session: r.session };
108895
+ const code = normaliseCode(r.code);
108896
+ return {
108897
+ kind: "error",
108898
+ code,
108899
+ remainingAttempts: code === "INVALID_CREDENTIALS" ? usableCounter(r.remainingAttempts) : void 0,
108900
+ message: code === "CUSTOM" && typeof r.message === "string" ? r.message : void 0,
108901
+ clearPassword: code === "CUSTOM" ? r.clearPassword !== false : void 0
108902
+ };
108903
+ }
108904
+ function normaliseThrown(err) {
108905
+ if (err && typeof err === "object" && err.myioGcdrCode === "TIMEOUT") return "TIMEOUT";
108906
+ return err instanceof TypeError ? "NETWORK" : "SERVER";
108907
+ }
108908
+ var ATTEMPTS_THRESHOLD = 3;
108909
+ function present(o) {
108910
+ switch (o.code) {
108911
+ case "INVALID_CREDENTIALS": {
108912
+ const n = o.remainingAttempts;
108913
+ if (n === void 0)
108914
+ return { tone: "error", keys: ["errors.invalidCredentials"], icon: "alert", clearPassword: true, focus: "password" };
108915
+ if (n > ATTEMPTS_THRESHOLD)
108916
+ return { tone: "error", keys: ["errors.invalidWithAttempts"], count: n, icon: "alert", clearPassword: true, focus: "password" };
108917
+ if (n === 1)
108918
+ return { tone: "warning", keys: ["errors.lastAttempt", "errors.lockWarning"], icon: "shieldAlert", forgotLink: true, clearPassword: true, focus: "password" };
108919
+ return { tone: "warning", keys: ["errors.attemptsLeft", "errors.lockWarning"], count: n, icon: "shieldAlert", forgotLink: true, clearPassword: true, focus: "password" };
108920
+ }
108921
+ case "ACCOUNT_LOCKED":
108922
+ return { tone: "error", keys: ["errors.lockedText"], title: "errors.lockedTitle", icon: "lock", support: true, clearPassword: true, focus: "banner" };
108923
+ case "MFA_REQUIRED":
108924
+ return { tone: "error", keys: ["errors.mfaUnsupported"], icon: "shieldAlert", gcdrWebLink: true, support: true, clearPassword: true, focus: "banner" };
108925
+ case "CAPTCHA_FAILED":
108926
+ return { tone: "error", keys: ["errors.captchaFailed"], icon: "alert", clearPassword: false, focus: "captcha" };
108927
+ case "TOO_MANY_REQUESTS":
108928
+ return { tone: "error", keys: ["errors.tooManyRequests"], icon: "alert", clearPassword: false, focus: "submit" };
108929
+ case "NETWORK":
108930
+ return { tone: "error", keys: ["errors.networkError"], icon: "alert", clearPassword: false, focus: "submit" };
108931
+ case "TIMEOUT":
108932
+ return { tone: "error", keys: ["errors.timeout"], icon: "alert", clearPassword: false, focus: "submit" };
108933
+ case "INTEGRATION_ERROR":
108934
+ return { tone: "error", keys: ["errors.integrationError"], icon: "alert", clearPassword: false, focus: "submit" };
108935
+ case "CUSTOM": {
108936
+ const clear = o.clearPassword !== false;
108937
+ return {
108938
+ tone: "error",
108939
+ keys: o.message ? [] : ["errors.loginFailed"],
108940
+ text: o.message,
108941
+ icon: "alert",
108942
+ clearPassword: clear,
108943
+ focus: clear ? "password" : "submit"
108944
+ };
108945
+ }
108946
+ case "SERVER":
108947
+ default:
108948
+ return { tone: "error", keys: ["errors.loginFailed"], icon: "alert", clearPassword: false, focus: "submit" };
108949
+ }
108950
+ }
108951
+
108952
+ // src/components/myio-gcdr-login/gcdrClient.ts
108953
+ var DEFAULT_TIMEOUT_MS = 15e3;
108954
+ function timeoutError() {
108955
+ const e = new Error("GCDR login timed out");
108956
+ e.myioGcdrCode = "TIMEOUT";
108957
+ return e;
108958
+ }
108959
+ function createMyioGcdrLoginSubmit(options) {
108960
+ if (!options || typeof options.apiUrl !== "string" || !options.apiUrl.trim()) {
108961
+ throw new TypeError("[MYIO Login] gcdr.apiUrl must be a non-empty string");
108962
+ }
108963
+ if (typeof options.tenantId !== "string" || !options.tenantId.trim()) {
108964
+ throw new TypeError("[MYIO Login] gcdr.tenantId must be a non-empty string");
108965
+ }
108966
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
108967
+ if (!(typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0)) {
108968
+ throw new TypeError("[MYIO Login] gcdr.timeoutMs must be a positive number");
108969
+ }
108970
+ const base = options.apiUrl.replace(/\/+$/, "").replace(/\/api\/v\d+$/, "");
108971
+ const url = `${base}/api/v1/auth/login`;
108972
+ return async (input, ctx) => {
108973
+ const doFetch = options.fetch ?? (typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0);
108974
+ if (!doFetch) throw new TypeError("fetch is not available");
108975
+ const ac = new AbortController();
108976
+ let timedOut = false;
108977
+ const onOuterAbort = () => ac.abort();
108978
+ if (ctx?.signal) {
108979
+ if (ctx.signal.aborted) ac.abort();
108980
+ else ctx.signal.addEventListener("abort", onOuterAbort, { once: true });
108981
+ }
108982
+ const timer = setTimeout(() => {
108983
+ timedOut = true;
108984
+ ac.abort();
108985
+ }, timeoutMs);
108986
+ const body = { email: input.email, password: input.password };
108987
+ if (input.captchaToken) body.captchaToken = input.captchaToken;
108988
+ let res;
108989
+ try {
108990
+ res = await doFetch(url, {
108991
+ method: "POST",
108992
+ headers: { "Content-Type": "application/json", "x-tenant-id": options.tenantId, ...options.extraHeaders ?? {} },
108993
+ body: JSON.stringify(body),
108994
+ credentials: "omit",
108995
+ redirect: "error",
108996
+ signal: ac.signal
108997
+ });
108998
+ } catch (err) {
108999
+ if (timedOut) throw timeoutError();
109000
+ if (ac.signal.aborted) throw err;
109001
+ return { ok: false, code: "NETWORK" };
109002
+ } finally {
109003
+ clearTimeout(timer);
109004
+ ctx?.signal?.removeEventListener("abort", onOuterAbort);
109005
+ }
109006
+ let json = void 0;
109007
+ try {
109008
+ json = await res.json();
109009
+ } catch {
109010
+ json = void 0;
109011
+ }
109012
+ return mapGcdrResponse(res.status, json);
109013
+ };
109014
+ }
109015
+ function mapGcdrResponse(status, json) {
109016
+ const j = json && typeof json === "object" ? json : {};
109017
+ if (status >= 200 && status < 300) {
109018
+ const data = j.data;
109019
+ if (data && data.mfaRequired === true) return { ok: false, code: "MFA_REQUIRED" };
109020
+ if (data && typeof data.accessToken === "string" && data.accessToken) return { ok: true, session: data };
109021
+ return { ok: false, code: "INTEGRATION_ERROR" };
109022
+ }
109023
+ const code = typeof j.error?.code === "string" ? j.error.code : void 0;
109024
+ const remaining = j.error?.details?.remainingAttempts;
109025
+ switch (status) {
109026
+ case 400:
109027
+ return { ok: false, code: code === "CAPTCHA_FAILED" ? "CAPTCHA_FAILED" : "SERVER" };
109028
+ case 401:
109029
+ return code === "INVALID_CREDENTIALS" && typeof remaining === "number" ? { ok: false, code: "INVALID_CREDENTIALS", remainingAttempts: remaining } : { ok: false, code: "INVALID_CREDENTIALS" };
109030
+ case 403:
109031
+ return { ok: false, code: code === "ACCOUNT_LOCKED" ? "ACCOUNT_LOCKED" : "SERVER" };
109032
+ case 429:
109033
+ return { ok: false, code: "TOO_MANY_REQUESTS" };
109034
+ default:
109035
+ return { ok: false, code: "SERVER" };
109036
+ }
109037
+ }
109038
+
109039
+ // src/components/myio-gcdr-login/loginView.ts
109040
+ var DEFAULT_SUBMIT_TIMEOUT_MS = 3e4;
109041
+ function fail(msg, code) {
109042
+ const e = new TypeError(`[MYIO Login] ${msg}`);
109043
+ if (code) e.code = code;
109044
+ throw e;
109045
+ }
109046
+ function validateOptions3(container, o) {
109047
+ if (!(container instanceof HTMLElement)) fail("container must be an HTMLElement");
109048
+ if (!o || typeof o !== "object") fail("options are required");
109049
+ const n = [o.onSubmit, o.gcdr, o.auth].filter((x) => x != null).length;
109050
+ if (n !== 1) fail("exactly one of onSubmit, gcdr or auth is required");
109051
+ if (o.auth && o.auth.kind !== "credentials") {
109052
+ fail(`auth.kind "${String(o.auth.kind)}" is not supported`, "MYIO_GCDR_AUTH_UNSUPPORTED");
109053
+ }
109054
+ if (o.auth && typeof o.auth.submit !== "function") fail("auth.submit must be a function");
109055
+ if (o.onSubmit && typeof o.onSubmit !== "function") fail("onSubmit must be a function");
109056
+ if (typeof o.onSuccess !== "function") fail("onSuccess must be a function");
109057
+ if (o.submitTimeoutMs != null && !(Number.isFinite(o.submitTimeoutMs) && o.submitTimeoutMs > 0)) fail("submitTimeoutMs must be a positive number");
109058
+ if (o.captcha) fail("captcha is not available in this version (RFC-0236 PR 2)", "MYIO_GCDR_CAPTCHA_UNSUPPORTED");
109059
+ const kinds = ["about", "signedOutPrompt", "custom", "none"];
109060
+ if (o.aside && !kinds.includes(o.aside.kind)) fail(`unknown aside.kind "${String(o.aside.kind)}"`);
109061
+ if (o.aside?.kind === "custom" && typeof o.aside.render !== "function") fail("aside.render must be a function");
109062
+ if (o.support && (typeof o.support.href !== "string" || !o.support.href)) fail("support.href must be a non-empty string");
109063
+ if (o.embed) {
109064
+ const bad = ["aside", "buildInfo", "theme", "locale", "assets"].filter((k) => o[k] !== void 0);
109065
+ if (o.show?.themeToggle !== void 0 || o.show?.languageSelector !== void 0 || o.show?.wallpaper !== void 0) bad.push("show.(theme|language|wallpaper)");
109066
+ if (bad.length) fail(`with embed, these options belong to the host shell: ${bad.join(", ")}`);
109067
+ if (!o.embed.context || typeof o.embed.context.on !== "function") fail("embed.context must be a slot context");
109068
+ }
109069
+ }
109070
+ function createLoginViewImpl(container, options, internals = {}) {
109071
+ validateOptions3(container, options);
109072
+ const doc = container.ownerDocument;
109073
+ const presentation = internals.presentation ?? "inline";
109074
+ const prefix = options.storageKeyPrefix ?? "myio.login.";
109075
+ const isGcdr = !!options.gcdr;
109076
+ const webUrl = options.links?.gcdrWebUrl?.replace(/\/+$/, "");
109077
+ const strategy = options.gcdr ? createMyioGcdrLoginSubmit(options.gcdr) : options.auth ? options.auth.submit : options.onSubmit;
109078
+ const viewTimeoutMs = isGcdr ? void 0 : options.submitTimeoutMs ?? DEFAULT_SUBMIT_TIMEOUT_MS;
109079
+ let shell;
109080
+ let embedCtx;
109081
+ let releaseEmbedStyles;
109082
+ let cardHost;
109083
+ if (options.embed) {
109084
+ embedCtx = options.embed.context;
109085
+ releaseEmbedStyles = acquireStyles(container, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
109086
+ container.textContent = "";
109087
+ cardHost = container;
109088
+ } else {
109089
+ const wpOpt = internals.shellWallpaper === false || options.show?.wallpaper === false ? false : options.assets?.wallpaper ?? {};
109090
+ shell = createShellImpl(
109091
+ container,
109092
+ {
109093
+ size: options.size ?? "md",
109094
+ theme: options.theme,
109095
+ locale: options.locale,
109096
+ show: { themeToggle: options.show?.themeToggle, languageSelector: options.show?.languageSelector },
109097
+ buildInfo: options.buildInfo,
109098
+ storageKeyPrefix: options.storageKeyPrefix,
109099
+ fonts: options.fonts,
109100
+ cspNonce: options.cspNonce,
109101
+ wallpaper: wpOpt === false ? false : wpOpt,
109102
+ onThemeChange: options.onThemeChange,
109103
+ onLocaleChange: options.onLocaleChange
109104
+ },
109105
+ {
109106
+ messages: options.messages,
109107
+ logoUrl: options.assets?.logoUrl,
109108
+ about: { webUrl, fetchImpl: options.gcdr?.fetch, bandColor: options.brand?.asideHeaderColor }
109109
+ }
109110
+ );
109111
+ cardHost = h2(doc, "div", { style: "display:flex;width:100%" });
109112
+ }
109113
+ const getLocale = () => shell ? shell.getState().locale : embedCtx.locale;
109114
+ const getTheme = () => shell ? shell.getState().theme : embedCtx.theme;
109115
+ const t = (key, vars) => translate(getLocale(), key, vars, options.messages);
109116
+ let phase = "idle";
109117
+ let destroyed = false;
109118
+ let attempt = 0;
109119
+ let attemptAbort = null;
109120
+ let abortCause = null;
109121
+ let successAbort = null;
109122
+ let err = {};
109123
+ let lockedKey = null;
109124
+ let noCounterStreak = 0;
109125
+ let streakKey = null;
109126
+ let notice = options.notice ?? null;
109127
+ let fieldErrors = {};
109128
+ const remembered = storageGet(`${prefix}rememberedEmail`);
109129
+ let emailValue = options.initialEmail ?? remembered ?? "";
109130
+ let rememberValue = !options.initialEmail && !!remembered;
109131
+ let passwordValue = "";
109132
+ let passwordVisible = false;
109133
+ let leaving = false;
109134
+ const linkTarget = options.links?.target ?? (presentation === "modal" ? "_blank" : "_self");
109135
+ const forgot = options.links?.forgotPassword;
109136
+ const forgotShown = forgot === false ? false : !!forgot || isGcdr && !!webUrl;
109137
+ const supportHref = options.support === false ? void 0 : options.support ? options.support.href : (options.aside?.kind ?? "about") === "about" ? defaultSupportHref(webUrl) : void 0;
109138
+ let els = {};
109139
+ const linkEl = (label, target, cls = "myio-gcdr-login__link") => {
109140
+ if (typeof target === "function") {
109141
+ const b = h2(doc, "button", { type: "button", class: cls, text: label });
109142
+ b.addEventListener("click", () => safeCall("link", target, { email: emailValue.trim() }));
109143
+ return b;
109144
+ }
109145
+ const a = h2(doc, "a", { class: cls, href: target, target: linkTarget, rel: linkTarget === "_blank" ? "noopener noreferrer" : null }, label);
109146
+ if (linkTarget === "_blank") a.appendChild(h2(doc, "span", { class: "myio-gcdr-sr", text: ` ${t("login.newTab")}` }));
109147
+ return a;
109148
+ };
109149
+ const forgotTarget = () => !forgotShown ? void 0 : typeof forgot === "string" || typeof forgot === "function" ? forgot : `${webUrl}/forgot-password`;
109150
+ const renderNotice = () => {
109151
+ if (!els.notice) return;
109152
+ els.notice.textContent = "";
109153
+ if (!notice) return;
109154
+ const key = presentation === "modal" ? "notice.sessionExpiredModal" : "notice.sessionExpired";
109155
+ els.notice.appendChild(
109156
+ h2(
109157
+ doc,
109158
+ "div",
109159
+ { class: "myio-gcdr-banner myio-gcdr-banner--info" },
109160
+ icon(doc, ICONS.info(16), "myio-gcdr-banner__icon"),
109161
+ h2(doc, "div", { class: "myio-gcdr-banner__body" }, h2(doc, "span", { text: t(key) }))
109162
+ )
109163
+ );
109164
+ };
109165
+ const renderAlerts = () => {
109166
+ if (!els.alerts) return;
109167
+ els.alerts.textContent = "";
109168
+ els.banner = void 0;
109169
+ if (!err.pres && !err.messageKey) return;
109170
+ const p = err.pres;
109171
+ const tone = p?.tone ?? "error";
109172
+ const body = h2(doc, "div", { class: "myio-gcdr-banner__body" });
109173
+ if (p?.title) body.appendChild(h2(doc, "span", { class: "myio-gcdr-banner__title", text: t(p.title) }));
109174
+ if (p) {
109175
+ if (p.text) body.appendChild(h2(doc, "span", { text: p.text }));
109176
+ p.keys.forEach((k, i) => body.appendChild(h2(doc, "span", { text: t(k, i === 0 && p.count !== void 0 ? { count: p.count } : void 0) })));
109177
+ if (p.forgotLink) {
109178
+ const ft = forgotTarget();
109179
+ if (ft) body.appendChild(linkEl(t("errors.goToForgot"), ft, ""));
109180
+ }
109181
+ if (p.gcdrWebLink && webUrl) body.appendChild(linkEl(t("login.gcdrWeb"), `${webUrl}/login`, ""));
109182
+ if (p.support && supportHref) body.appendChild(linkEl(t("login.support"), supportHref, ""));
109183
+ } else if (err.messageKey) {
109184
+ body.appendChild(h2(doc, "span", { text: t(err.messageKey) }));
109185
+ }
109186
+ if (err.help) {
109187
+ const who = supportHref ? t("errors.helpSupport") : t("errors.helpAdmin");
109188
+ body.appendChild(h2(doc, "span", { text: t("errors.invalidCredentialsHelp", { who }) }));
109189
+ if (supportHref) body.appendChild(linkEl(t("login.support"), supportHref, ""));
109190
+ }
109191
+ const ic = p?.icon === "lock" ? ICONS.lock(16) : p?.icon === "shieldAlert" ? ICONS.shieldAlert(16) : ICONS.alert(16);
109192
+ const banner = h2(doc, "div", { class: `myio-gcdr-banner myio-gcdr-banner--${tone}`, tabindex: "-1" }, icon(doc, ic, "myio-gcdr-banner__icon"), body);
109193
+ els.alerts.appendChild(banner);
109194
+ els.banner = banner;
109195
+ };
109196
+ const syncControls = () => {
109197
+ if (!els.submit || !els.email || !els.password) return;
109198
+ const busy = phase === "submitting" || phase === "success";
109199
+ const blocked = busy || leaving || !!lockedKey;
109200
+ els.submit.setAttribute("aria-disabled", blocked ? "true" : "false");
109201
+ els.submit.setAttribute("aria-busy", busy ? "true" : "false");
109202
+ if (lockedKey && els.banner) {
109203
+ if (!els.banner.id) els.banner.id = `myio-gcdr-lock-${Math.random().toString(36).slice(2, 8)}`;
109204
+ els.submit.setAttribute("aria-describedby", els.banner.id);
109205
+ } else els.submit.removeAttribute("aria-describedby");
109206
+ els.submit.textContent = "";
109207
+ if (busy) {
109208
+ els.submit.append(icon(doc, ICONS.spinner(18), "myio-gcdr-login__spin"), h2(doc, "span", { text: t("login.signingIn") }));
109209
+ } else els.submit.append(h2(doc, "span", { text: t("login.signIn") }));
109210
+ els.email.readOnly = busy || leaving;
109211
+ els.password.readOnly = busy || leaving;
109212
+ };
109213
+ const render3 = () => {
109214
+ if (destroyed) return;
109215
+ if (els.email) emailValue = els.email.value;
109216
+ if (els.password) passwordValue = els.password.value;
109217
+ const hadFocusId = doc.activeElement && cardHost.contains(doc.activeElement) ? doc.activeElement.getAttribute("data-k") : null;
109218
+ cardHost.textContent = "";
109219
+ const locale = getLocale();
109220
+ const { root, body, footer, title } = buildPanel(
109221
+ doc,
109222
+ cardHost,
109223
+ { eyebrow: options.brand?.label ?? t("login.eyebrow"), title: t("login.title"), footer: true, accent: options.brand?.accent, bandColor: options.brand?.bandColor, tint: options.brand?.tint, logoUrl: options.assets?.logoUrl },
109224
+ locale
109225
+ );
109226
+ if (options.size && options.embed) root.style.maxWidth = options.size === "xl" ? "37rem" : options.size === "lg" ? "32rem" : "28rem";
109227
+ else if (options.embed) root.style.maxWidth = "28rem";
109228
+ root.style.margin = "0 auto";
109229
+ if (options.brand?.accent) root.style.setProperty("--myio-gcdr-accent-hover", options.brand.accent);
109230
+ root.setAttribute("data-theme", getTheme());
109231
+ els = { root, title };
109232
+ const noticeEl = h2(doc, "div", { class: "myio-gcdr-login__alerts", role: "status", "aria-live": "polite" });
109233
+ const alerts = h2(doc, "div", { class: "myio-gcdr-login__alerts", role: "alert" });
109234
+ els.notice = noticeEl;
109235
+ els.alerts = alerts;
109236
+ const form = h2(doc, "form", { class: "myio-gcdr-login__form", novalidate: true });
109237
+ const uid2 = Math.random().toString(36).slice(2, 8);
109238
+ const email = h2(doc, "input", {
109239
+ id: `myio-gcdr-email-${uid2}`,
109240
+ "data-k": "email",
109241
+ class: "myio-gcdr-login__input",
109242
+ type: "email",
109243
+ inputmode: "email",
109244
+ autocomplete: "username",
109245
+ autocapitalize: "none",
109246
+ spellcheck: "false",
109247
+ placeholder: t("login.emailPlaceholder"),
109248
+ "aria-invalid": fieldErrors.email ? "true" : "false"
109249
+ });
109250
+ email.value = emailValue;
109251
+ const emailErr = h2(doc, "span", { id: `myio-gcdr-email-err-${uid2}`, class: "myio-gcdr-login__fielderror", text: fieldErrors.email ? t(fieldErrors.email) : "" });
109252
+ if (fieldErrors.email) email.setAttribute("aria-describedby", emailErr.id);
109253
+ const emailField = h2(
109254
+ doc,
109255
+ "div",
109256
+ { class: "myio-gcdr-login__field" },
109257
+ h2(doc, "label", { class: "myio-gcdr-login__label", for: email.id, text: t("login.email") }),
109258
+ email,
109259
+ fieldErrors.email ? emailErr : null
109260
+ );
109261
+ if (options.initialEmail) {
109262
+ const notYou = h2(doc, "button", { type: "button", class: "myio-gcdr-login__link", text: t("login.notYou") });
109263
+ notYou.addEventListener("click", () => {
109264
+ email.value = "";
109265
+ emailValue = "";
109266
+ onEmailInput();
109267
+ email.focus();
109268
+ });
109269
+ emailField.appendChild(notYou);
109270
+ }
109271
+ const password = h2(doc, "input", {
109272
+ id: `myio-gcdr-pass-${uid2}`,
109273
+ "data-k": "password",
109274
+ class: "myio-gcdr-login__input myio-gcdr-login__input--password",
109275
+ type: passwordVisible ? "text" : "password",
109276
+ autocomplete: "current-password",
109277
+ enterkeyhint: "go",
109278
+ placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
109279
+ "aria-invalid": fieldErrors.password ? "true" : "false"
109280
+ });
109281
+ password.value = passwordValue;
109282
+ const passErr = h2(doc, "span", { id: `myio-gcdr-pass-err-${uid2}`, class: "myio-gcdr-login__fielderror", text: fieldErrors.password ? t(fieldErrors.password) : "" });
109283
+ if (fieldErrors.password) password.setAttribute("aria-describedby", passErr.id);
109284
+ const control = h2(doc, "div", { class: "myio-gcdr-login__control" }, password);
109285
+ if (options.show?.passwordToggle !== false) {
109286
+ const eye = h2(doc, "button", { type: "button", class: "myio-gcdr-login__eye", "aria-pressed": passwordVisible ? "true" : "false", "aria-label": t(passwordVisible ? "login.hidePassword" : "login.showPassword"), "aria-controls": password.id });
109287
+ eye.appendChild(icon(doc, passwordVisible ? ICONS.eyeOff(18) : ICONS.eye(18)));
109288
+ eye.addEventListener("click", () => {
109289
+ passwordVisible = !passwordVisible;
109290
+ password.type = passwordVisible ? "text" : "password";
109291
+ eye.setAttribute("aria-pressed", passwordVisible ? "true" : "false");
109292
+ eye.setAttribute("aria-label", t(passwordVisible ? "login.hidePassword" : "login.showPassword"));
109293
+ eye.textContent = "";
109294
+ eye.appendChild(icon(doc, passwordVisible ? ICONS.eyeOff(18) : ICONS.eye(18)));
109295
+ });
109296
+ control.appendChild(eye);
109297
+ }
109298
+ const caps = h2(doc, "span", { class: "myio-gcdr-login__hint", "aria-live": "polite" });
109299
+ const capsCheck = (e) => {
109300
+ const on = typeof e.getModifierState === "function" && e.getModifierState("CapsLock");
109301
+ caps.textContent = on ? t("login.capsLockOn") : "";
109302
+ };
109303
+ password.addEventListener("keydown", capsCheck);
109304
+ password.addEventListener("keyup", capsCheck);
109305
+ const passField = h2(
109306
+ doc,
109307
+ "div",
109308
+ { class: "myio-gcdr-login__field" },
109309
+ h2(doc, "label", { class: "myio-gcdr-login__label", for: password.id, text: t("login.password") }),
109310
+ control,
109311
+ caps,
109312
+ fieldErrors.password ? passErr : null
109313
+ );
109314
+ const row = h2(doc, "div", { class: "myio-gcdr-login__row" });
109315
+ if (options.show?.rememberMe !== false) {
109316
+ const cb = h2(doc, "input", { type: "checkbox" });
109317
+ cb.checked = rememberValue;
109318
+ cb.addEventListener("change", () => {
109319
+ rememberValue = cb.checked;
109320
+ });
109321
+ row.appendChild(h2(doc, "label", { class: "myio-gcdr-login__remember" }, cb, h2(doc, "span", { text: t("login.rememberMe") })));
109322
+ } else row.appendChild(h2(doc, "span"));
109323
+ const ft = forgotTarget();
109324
+ if (ft) row.appendChild(linkEl(t("login.forgotPassword"), ft));
109325
+ const submit = h2(doc, "button", { type: "submit", "data-k": "submit", class: "myio-gcdr-login__submit", "data-style": options.submitStyle ?? "auth" });
109326
+ form.append(emailField, passField, row, submit);
109327
+ form.addEventListener("submit", (e) => {
109328
+ e.preventDefault();
109329
+ void doSubmit();
109330
+ });
109331
+ email.addEventListener("input", () => {
109332
+ emailValue = email.value;
109333
+ onEmailInput();
109334
+ });
109335
+ password.addEventListener("input", () => {
109336
+ passwordValue = password.value;
109337
+ if (fieldErrors.password) {
109338
+ fieldErrors.password = validate(email.value, password.value).passwordError;
109339
+ if (!fieldErrors.password) {
109340
+ password.setAttribute("aria-invalid", "false");
109341
+ passErr.remove();
109342
+ }
109343
+ }
109344
+ });
109345
+ body.append(noticeEl, alerts, form);
109346
+ if (footer) {
109347
+ const reg = options.links?.register;
109348
+ if (reg) {
109349
+ footer.append(h2(doc, "span", { text: `${t("login.noAccount")} ` }), linkEl(t("login.createAccount"), reg));
109350
+ } else footer.appendChild(h2(doc, "span", { text: options.footerText ? localize(options.footerText, locale) : t("login.askAdmin") }));
109351
+ internals.decorateFooter?.(footer, api);
109352
+ }
109353
+ els = { ...els, email, password, submit, caps };
109354
+ renderNotice();
109355
+ renderAlerts();
109356
+ syncControls();
109357
+ if (hadFocusId) cardHost.querySelector(`[data-k="${hadFocusId}"]`)?.focus();
109358
+ };
109359
+ const onEmailInput = () => {
109360
+ const key = emailKey(emailValue);
109361
+ if (fieldErrors.email) {
109362
+ fieldErrors.email = validate(emailValue, "").emailError;
109363
+ if (!fieldErrors.email) render3();
109364
+ }
109365
+ if (lockedKey && key !== lockedKey) {
109366
+ lockedKey = null;
109367
+ err = {};
109368
+ renderAlerts();
109369
+ syncControls();
109370
+ }
109371
+ if (streakKey && key !== streakKey) {
109372
+ noCounterStreak = 0;
109373
+ streakKey = null;
109374
+ }
109375
+ };
109376
+ const focusTarget = (f) => {
109377
+ const el2 = f === "password" ? els.password : f === "email" ? els.email : f === "banner" ? els.banner : els.submit;
109378
+ el2?.focus();
109379
+ };
109380
+ const setError = (code, pres, opts) => {
109381
+ err = { code, pres, help: opts.help };
109382
+ if (pres.clearPassword && els.password) {
109383
+ els.password.value = "";
109384
+ passwordValue = "";
109385
+ }
109386
+ renderAlerts();
109387
+ syncControls();
109388
+ focusTarget(pres.focus);
109389
+ if (opts.notify !== false) safeCall("onError", options.onError, { code, remainingAttempts: opts.remaining });
109390
+ };
109391
+ const doSubmit = async () => {
109392
+ if (destroyed || phase !== "idle" || leaving || lockedKey) return;
109393
+ const email = els.email.value;
109394
+ const password = els.password.value;
109395
+ const v = validate(email, password);
109396
+ fieldErrors = { email: v.emailError, password: v.passwordError };
109397
+ if (v.emailError || v.passwordError) {
109398
+ render3();
109399
+ (v.emailError ? els.email : els.password)?.focus();
109400
+ return;
109401
+ }
109402
+ fieldErrors = {};
109403
+ attempt += 1;
109404
+ const my = attempt;
109405
+ phase = "submitting";
109406
+ err = { ...err, pres: void 0, messageKey: void 0, help: false, code: void 0 };
109407
+ if (passwordVisible) {
109408
+ passwordVisible = false;
109409
+ els.password.type = "password";
109410
+ }
109411
+ renderAlerts();
109412
+ syncControls();
109413
+ const ac = new AbortController();
109414
+ attemptAbort = ac;
109415
+ abortCause = null;
109416
+ let timer;
109417
+ const timeout = new Promise((_, reject) => {
109418
+ if (viewTimeoutMs) timer = setTimeout(() => {
109419
+ abortCause = "timeout";
109420
+ ac.abort();
109421
+ reject(Object.assign(new Error("timeout"), { myioGcdrCode: "TIMEOUT" }));
109422
+ }, viewTimeoutMs);
109423
+ });
109424
+ let outcome;
109425
+ try {
109426
+ const raw = await Promise.race([strategy({ email: v.email, password, remember: rememberValue, locale: getLocale() }, { signal: ac.signal, attempt: my }), timeout]);
109427
+ outcome = normaliseResult(raw);
109428
+ if (outcome.kind === "error" && outcome.code === "INTEGRATION_ERROR" && !(raw && typeof raw === "object" && typeof raw.ok === "boolean")) {
109429
+ console.error("[MYIO Login] INTEGRATION_ERROR: invalid onSubmit result");
109430
+ }
109431
+ } catch (e) {
109432
+ outcome = { kind: "thrown", err: e };
109433
+ } finally {
109434
+ if (timer) clearTimeout(timer);
109435
+ }
109436
+ if (destroyed || my !== attempt || abortCause === "destroy" || abortCause === "exit") return;
109437
+ attemptAbort = null;
109438
+ if (outcome.kind === "thrown") {
109439
+ phase = "idle";
109440
+ const code = abortCause === "timeout" ? "TIMEOUT" : normaliseThrown(outcome.err);
109441
+ setError(code, present({ kind: "error", code }), {});
109442
+ return;
109443
+ }
109444
+ if (outcome.kind === "error") {
109445
+ phase = "idle";
109446
+ const k = emailKey(v.email);
109447
+ let help = false;
109448
+ if (outcome.code === "INVALID_CREDENTIALS" && outcome.remainingAttempts === void 0) {
109449
+ noCounterStreak = streakKey === k ? noCounterStreak + 1 : 1;
109450
+ streakKey = k;
109451
+ help = noCounterStreak >= 2;
109452
+ } else {
109453
+ noCounterStreak = 0;
109454
+ streakKey = null;
109455
+ }
109456
+ if (outcome.code === "ACCOUNT_LOCKED") lockedKey = k;
109457
+ setError(outcome.code, present(outcome), { help, remaining: outcome.remainingAttempts });
109458
+ return;
109459
+ }
109460
+ phase = "success";
109461
+ if (els.password) els.password.value = "";
109462
+ passwordValue = "";
109463
+ err = {};
109464
+ noCounterStreak = 0;
109465
+ if (options.show?.rememberMe !== false) storageSet(`${prefix}rememberedEmail`, rememberValue ? v.email : null);
109466
+ renderAlerts();
109467
+ syncControls();
109468
+ const sa = new AbortController();
109469
+ successAbort = sa;
109470
+ try {
109471
+ await options.onSuccess(outcome.session, { signal: sa.signal });
109472
+ } catch {
109473
+ if (destroyed || sa.signal.aborted) return;
109474
+ console.error("[MYIO Login] onSuccess failed");
109475
+ phase = "idle";
109476
+ err = { messageKey: "errors.postLoginFailed", pres: { tone: "error", keys: ["errors.postLoginFailed"], icon: "alert", clearPassword: true, focus: "password" } };
109477
+ renderAlerts();
109478
+ syncControls();
109479
+ els.password?.focus();
109480
+ return;
109481
+ }
109482
+ if (destroyed || sa.signal.aborted) return;
109483
+ internals.afterSuccess?.();
109484
+ };
109485
+ const api = {
109486
+ abortAttempt() {
109487
+ if (attemptAbort) {
109488
+ abortCause = "exit";
109489
+ attemptAbort.abort();
109490
+ attemptAbort = null;
109491
+ attempt += 1;
109492
+ }
109493
+ if (phase === "submitting") phase = "idle";
109494
+ leaving = true;
109495
+ syncControls();
109496
+ },
109497
+ clearPassword() {
109498
+ if (els.password) els.password.value = "";
109499
+ passwordValue = "";
109500
+ },
109501
+ showLeaveFailed() {
109502
+ leaving = false;
109503
+ err = { messageKey: "errors.leaveFailed", pres: { tone: "error", keys: ["errors.leaveFailed"], icon: "alert", clearPassword: false, focus: "submit" } };
109504
+ renderAlerts();
109505
+ syncControls();
109506
+ },
109507
+ t: (k) => t(k),
109508
+ locale: getLocale,
109509
+ phase: () => phase
109510
+ };
109511
+ let offChange;
109512
+ if (shell) {
109513
+ const asideOpt = options.aside ?? { kind: "about" };
109514
+ if (asideOpt.kind === "about") {
109515
+ const healthUrl = asideOpt.healthUrl !== void 0 ? asideOpt.healthUrl : options.gcdr ? `${options.gcdr.apiUrl.replace(/\/+$/, "").replace(/\/api\/v\d+$/, "")}/health` : false;
109516
+ shell.setSlot("aside", { kind: "about", healthUrl });
109517
+ } else if (asideOpt.kind === "signedOutPrompt") shell.setSlot("aside", { kind: "signedOutPrompt", text: asideOpt.text });
109518
+ else if (asideOpt.kind === "custom") shell.setSlot("aside", asideOpt.render);
109519
+ shell.setSlot("main", (el2) => {
109520
+ el2.appendChild(cardHost);
109521
+ });
109522
+ offChange = shell.onChange(() => render3());
109523
+ } else if (embedCtx) {
109524
+ const offT = embedCtx.on("theme", () => render3());
109525
+ const offL = embedCtx.on("locale", () => render3());
109526
+ offChange = () => {
109527
+ offT();
109528
+ offL();
109529
+ };
109530
+ embedCtx.signal.addEventListener("abort", () => handle.destroy(), { once: true });
109531
+ }
109532
+ render3();
109533
+ const autoFocus = options.autoFocus ?? !isCoarsePointer();
109534
+ if (autoFocus && presentation === "inline") (options.initialEmail ? els.password : els.email)?.focus();
109535
+ const restricted = shell ? {
109536
+ setSlot: (name, content, o) => {
109537
+ if (name === "main") fail("the main slot belongs to the login view");
109538
+ shell.setSlot(name, content, o);
109539
+ },
109540
+ setShow: (s) => shell.setShow(s)
109541
+ } : void 0;
109542
+ const handle = {
109543
+ getState() {
109544
+ return {
109545
+ phase: destroyed ? "destroyed" : leaving ? "leaving" : phase,
109546
+ error: err.code,
109547
+ message: err.messageKey ?? err.pres?.keys[0],
109548
+ locked: !!lockedKey,
109549
+ notice: notice?.code,
109550
+ captcha: "none",
109551
+ email: emailValue.trim() || void 0,
109552
+ locale: getLocale(),
109553
+ theme: getTheme()
109554
+ };
109555
+ },
109556
+ setLocale(l) {
109557
+ if (shell) shell.setLocale(l);
109558
+ },
109559
+ setTheme(th) {
109560
+ if (shell) shell.setTheme(th);
109561
+ },
109562
+ showError(code, extra) {
109563
+ if (destroyed) return;
109564
+ const o = normaliseResult({ ok: false, code, remainingAttempts: extra?.remainingAttempts, message: extra?.message });
109565
+ if (o.kind !== "error") return;
109566
+ if (o.code === "ACCOUNT_LOCKED") lockedKey = emailKey(emailValue);
109567
+ const pres = present(o);
109568
+ err = { code: o.code, pres };
109569
+ renderAlerts();
109570
+ syncControls();
109571
+ },
109572
+ clearError() {
109573
+ if (destroyed) return;
109574
+ err = {};
109575
+ lockedKey = null;
109576
+ renderAlerts();
109577
+ syncControls();
109578
+ },
109579
+ setNotice(n) {
109580
+ if (destroyed) return;
109581
+ notice = n && n.code === "SESSION_EXPIRED" ? n : null;
109582
+ renderNotice();
109583
+ },
109584
+ reset() {
109585
+ if (destroyed || phase !== "success") return;
109586
+ successAbort?.abort();
109587
+ phase = "idle";
109588
+ syncControls();
109589
+ },
109590
+ focus() {
109591
+ (options.initialEmail ? els.password : els.email)?.focus();
109592
+ },
109593
+ get shell() {
109594
+ return restricted;
109595
+ },
109596
+ destroy() {
109597
+ if (destroyed) return;
109598
+ destroyed = true;
109599
+ abortCause = "destroy";
109600
+ attemptAbort?.abort();
109601
+ successAbort?.abort();
109602
+ offChange?.();
109603
+ if (els.password) els.password.value = "";
109604
+ passwordValue = "";
109605
+ if (shell) shell.destroy();
109606
+ else {
109607
+ cardHost.textContent = "";
109608
+ releaseEmbedStyles?.();
109609
+ }
109610
+ },
109611
+ _api: api
109612
+ };
109613
+ return handle;
109614
+ }
109615
+ function createMyioGcdrLoginView(container, options) {
109616
+ const impl = createLoginViewImpl(container, options, { presentation: "inline" });
109617
+ const { _api, ...pub } = impl;
109618
+ void _api;
109619
+ return Object.defineProperty(pub, "shell", { get: () => impl.shell, enumerable: true });
109620
+ }
109621
+
109622
+ // src/components/myio-gcdr-login/modal.ts
109623
+ var MODAL_ATTR = "data-myio-gcdr-modal";
109624
+ var LOCK_ATTR = "data-myio-gcdr-scroll-lock";
109625
+ var INERT_PREV = "data-myio-gcdr-inert-prev";
109626
+ function isMyioGcdrLoginModalOpen(target) {
109627
+ if (target instanceof HTMLElement) return !!target.querySelector(`:scope > [${MODAL_ATTR}]`);
109628
+ const doc = target ?? (typeof document !== "undefined" ? document : void 0);
109629
+ return !!doc?.querySelector(`[${MODAL_ATTR}]`);
109630
+ }
109631
+ function conflict() {
109632
+ const e = new Error("[MYIO Login] a login modal is already open here");
109633
+ e.code = "LOGIN_MODAL_ALREADY_OPEN";
109634
+ throw e;
109635
+ }
109636
+ function openMyioGcdrLoginModal(options) {
109637
+ const ov = options.overlay ?? {};
109638
+ const scopeEl = typeof ov.scope === "object" && ov.scope ? ov.scope.element : null;
109639
+ const doc = scopeEl?.ownerDocument ?? document;
109640
+ const viewport = !scopeEl;
109641
+ const dismissible = ov.dismissible === true;
109642
+ if (viewport && !dismissible && !ov.exit) {
109643
+ throw new TypeError("[MYIO Login] a viewport modal that is not dismissible needs overlay.exit (a way out)");
109644
+ }
109645
+ if (ov.exit && (!ov.exit.href || typeof ov.exit.href !== "string")) throw new TypeError("[MYIO Login] overlay.exit.href is required");
109646
+ if (ov.secondaryAction) {
109647
+ const e = new TypeError("[MYIO Login] overlay.secondaryAction is not available in this version (RFC-0236 PR 4)");
109648
+ e.code = "MYIO_GCDR_SECONDARY_UNSUPPORTED";
109649
+ throw e;
109650
+ }
109651
+ if (viewport ? isMyioGcdrLoginModalOpen(doc) : isMyioGcdrLoginModalOpen(scopeEl)) conflict();
109652
+ const backdrop = ov.backdrop ?? "solid";
109653
+ const opacity = typeof ov.opacity === "number" ? Math.min(1, Math.max(0, ov.opacity)) : 0.5;
109654
+ const blur = typeof ov.blur === "number" ? ov.blur : backdrop === "blur" ? 8 : 4;
109655
+ const previouslyFocused = doc.activeElement;
109656
+ const releaseStyles = acquireStyles(viewport ? doc.body : scopeEl, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
109657
+ const overlay = h2(doc, "div", {
109658
+ class: "myio-gcdr-overlay",
109659
+ [MODAL_ATTR]: "1",
109660
+ role: "dialog",
109661
+ "aria-modal": viewport ? "true" : null,
109662
+ "data-scope": viewport ? "viewport" : "element",
109663
+ "data-backdrop": backdrop
109664
+ });
109665
+ overlay.style.zIndex = String(ov.zIndex ?? 1e4);
109666
+ const layers = [];
109667
+ const layer = (bg, extra = "") => {
109668
+ const l = h2(doc, "div", { class: "myio-gcdr-overlay__layer", "aria-hidden": "true" });
109669
+ l.setAttribute("style", `background:${bg};${extra}`);
109670
+ layers.push(l);
109671
+ overlay.appendChild(l);
109672
+ return l;
109673
+ };
109674
+ const paintBackdrop = (dark) => {
109675
+ layers.splice(0).forEach((l) => l.remove());
109676
+ const blurCss = `-webkit-backdrop-filter:blur(${blur}px);backdrop-filter:blur(${blur}px)`;
109677
+ if (backdrop === "blur") {
109678
+ layer(`rgba(20,12,40,${opacity})`, blurCss);
109679
+ } else {
109680
+ layer(dark ? "linear-gradient(180deg,#1B1530 0%,#15121F 45%,#111827 100%)" : "linear-gradient(180deg,#DCD2F3 0%,#EEEAF8 45%,#F7F5FC 100%)");
109681
+ if (backdrop === "image" && options.assets?.wallpaper) {
109682
+ const wp = options.assets.wallpaper;
109683
+ let portrait = false;
109684
+ try {
109685
+ portrait = matchMedia("(orientation: portrait)").matches;
109686
+ } catch {
109687
+ }
109688
+ const url = dark ? portrait ? wp.mobileDark ?? wp.dark : wp.dark : portrait ? wp.mobileLight ?? wp.light : wp.light;
109689
+ if (url) layer(`url("${url.replace(/"/g, "%22")}") center/cover no-repeat`);
109690
+ }
109691
+ layer(`rgba(255,255,255,${(dark ? 0.1 : 0.44) * opacity})`, blurCss);
109692
+ layer(dark ? "linear-gradient(135deg,rgba(45,22,105,.55) 0%,rgba(27,21,48,.30) 50%,rgba(45,22,105,.55) 100%)" : "linear-gradient(135deg,rgba(107,74,191,.34) 0%,rgba(107,74,191,.14) 50%,rgba(107,74,191,.34) 100%)");
109693
+ }
109694
+ layers.forEach((l) => overlay.insertBefore(l, content));
109695
+ };
109696
+ const content = h2(doc, "div", { class: "myio-gcdr-overlay__content" });
109697
+ overlay.appendChild(content);
109698
+ let restoreStatic = null;
109699
+ if (viewport) doc.body.appendChild(overlay);
109700
+ else {
109701
+ const el2 = scopeEl;
109702
+ if (getComputedStyle(el2).position === "static") {
109703
+ const prev = el2.style.position;
109704
+ el2.style.position = "relative";
109705
+ restoreStatic = () => {
109706
+ el2.style.position = prev;
109707
+ };
109708
+ }
109709
+ el2.appendChild(overlay);
109710
+ }
109711
+ let open = true;
109712
+ let closing = false;
109713
+ let exitTimer;
109714
+ const close = (reason) => {
109715
+ if (!open || closing) return;
109716
+ closing = true;
109717
+ if (exitTimer) clearTimeout(exitTimer);
109718
+ mo?.disconnect();
109719
+ try {
109720
+ view.destroy();
109721
+ } catch {
109722
+ }
109723
+ doc.removeEventListener("keydown", onKey, true);
109724
+ overlay.removeEventListener("keydown", onKey, true);
109725
+ if (viewport) {
109726
+ releaseInert();
109727
+ releaseScroll();
109728
+ }
109729
+ overlay.remove();
109730
+ restoreStatic?.();
109731
+ releaseStyles();
109732
+ open = false;
109733
+ if (previouslyFocused && previouslyFocused.isConnected && typeof previouslyFocused.focus === "function") previouslyFocused.focus();
109734
+ else if (viewport) doc.body.focus?.();
109735
+ safeCall("onClose", options.onClose, reason);
109736
+ };
109737
+ const { overlay: _o, onOpen, onClose, ...viewOpts } = options;
109738
+ void _o;
109739
+ void onClose;
109740
+ const view = createLoginViewImpl(content, { ...viewOpts, aside: options.aside ?? { kind: "none" }, autoFocus: false }, {
109741
+ presentation: "modal",
109742
+ shellWallpaper: false,
109743
+ afterSuccess: () => {
109744
+ if (ov.closeOnSuccess !== false) close("success");
109745
+ },
109746
+ decorateFooter: (footer, api) => {
109747
+ if (!ov.exit) return;
109748
+ const label = localize(ov.exit.label, api.locale());
109749
+ const a = h2(doc, "a", { class: "myio-gcdr-login__link", href: ov.exit.href, style: "display:inline-block;margin-left:12px" }, label);
109750
+ a.addEventListener("click", () => {
109751
+ if (api.phase() === "success") return;
109752
+ api.abortAttempt();
109753
+ api.clearPassword();
109754
+ a.textContent = api.t("login.leaving");
109755
+ a.setAttribute("aria-busy", "true");
109756
+ exitTimer = setTimeout(() => {
109757
+ if (!open) return;
109758
+ a.textContent = label;
109759
+ a.removeAttribute("aria-busy");
109760
+ api.showLeaveFailed();
109761
+ a.focus();
109762
+ }, 2e3);
109763
+ });
109764
+ footer.appendChild(a);
109765
+ }
109766
+ });
109767
+ const shellRoot = content.querySelector(".myio-gcdr-shell");
109768
+ const syncTheme = () => {
109769
+ const dark = view.getState().theme === "dark";
109770
+ overlay.setAttribute("data-theme", dark ? "dark" : "light");
109771
+ paintBackdrop(dark);
109772
+ };
109773
+ syncTheme();
109774
+ const mo = shellRoot ? new MutationObserver(syncTheme) : null;
109775
+ mo?.observe(shellRoot, { attributes: true, attributeFilter: ["data-theme"] });
109776
+ if (backdrop === "blur" && options.show?.themeToggle === void 0) view.shell?.setShow({ themeToggle: false });
109777
+ const title = content.querySelector(".myio-gcdr-panel__title");
109778
+ if (title) {
109779
+ if (!title.id) title.id = `myio-gcdr-title-${Math.random().toString(36).slice(2, 8)}`;
109780
+ overlay.setAttribute("aria-labelledby", title.id);
109781
+ }
109782
+ if (dismissible) {
109783
+ const x = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn myio-gcdr-overlay__close", "aria-label": view._api.t("modal.close") });
109784
+ x.appendChild(icon(doc, ICONS.x(18)));
109785
+ x.addEventListener("click", () => {
109786
+ const p = view.getState().phase;
109787
+ if (p !== "submitting" && p !== "success") close("dismiss");
109788
+ });
109789
+ content.appendChild(x);
109790
+ }
109791
+ const inerted = [];
109792
+ const releaseInert = () => {
109793
+ for (const el2 of inerted) {
109794
+ const prev = el2.getAttribute(INERT_PREV);
109795
+ if (prev === "true") el2.setAttribute("inert", "");
109796
+ else el2.removeAttribute("inert");
109797
+ el2.removeAttribute(INERT_PREV);
109798
+ }
109799
+ inerted.length = 0;
109800
+ };
109801
+ let scrollPrev = null;
109802
+ const releaseScroll = () => {
109803
+ const html = doc.documentElement;
109804
+ const n = Math.max(0, (parseInt(html.getAttribute(LOCK_ATTR) || "1", 10) || 1) - 1);
109805
+ if (n === 0) {
109806
+ html.removeAttribute(LOCK_ATTR);
109807
+ if (scrollPrev) {
109808
+ html.style.overflow = scrollPrev.html;
109809
+ doc.body.style.overflow = scrollPrev.body;
109810
+ }
109811
+ } else html.setAttribute(LOCK_ATTR, String(n));
109812
+ };
109813
+ if (viewport) {
109814
+ for (const el2 of Array.from(doc.body.children)) {
109815
+ if (el2 === overlay || el2.tagName === "SCRIPT" || el2.tagName === "STYLE") continue;
109816
+ el2.setAttribute(INERT_PREV, el2.hasAttribute("inert") ? "true" : "false");
109817
+ el2.setAttribute("inert", "");
109818
+ inerted.push(el2);
109819
+ }
109820
+ const html = doc.documentElement;
109821
+ const n = parseInt(html.getAttribute(LOCK_ATTR) || "0", 10) || 0;
109822
+ if (n === 0) scrollPrev = { html: html.style.overflow, body: doc.body.style.overflow };
109823
+ html.setAttribute(LOCK_ATTR, String(n + 1));
109824
+ html.style.overflow = "hidden";
109825
+ doc.body.style.overflow = "hidden";
109826
+ }
109827
+ const focusables = () => Array.from(overlay.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select,textarea,[tabindex]:not([tabindex="-1"])')).filter((el2) => !el2.hidden && el2.offsetParent !== null);
109828
+ const onKey = (e) => {
109829
+ if (!open) return;
109830
+ if (e.key === "Escape" && dismissible) {
109831
+ const p = view.getState().phase;
109832
+ if (p !== "submitting" && p !== "success") {
109833
+ e.preventDefault();
109834
+ close("dismiss");
109835
+ }
109836
+ return;
109837
+ }
109838
+ if (e.key === "Tab" && viewport) {
109839
+ const list = focusables();
109840
+ if (!list.length) return;
109841
+ const first = list[0];
109842
+ const last = list[list.length - 1];
109843
+ const active = doc.activeElement;
109844
+ if (e.shiftKey && (active === first || !overlay.contains(active))) {
109845
+ e.preventDefault();
109846
+ last.focus();
109847
+ } else if (!e.shiftKey && (active === last || !overlay.contains(active))) {
109848
+ e.preventDefault();
109849
+ first.focus();
109850
+ }
109851
+ }
109852
+ };
109853
+ if (viewport) doc.addEventListener("keydown", onKey, true);
109854
+ else overlay.addEventListener("keydown", onKey, true);
109855
+ const emailInput = content.querySelector('[data-k="email"]');
109856
+ const passInput = content.querySelector('[data-k="password"]');
109857
+ const coarse = (() => {
109858
+ try {
109859
+ return matchMedia("(pointer: coarse)").matches;
109860
+ } catch {
109861
+ return false;
109862
+ }
109863
+ })();
109864
+ const wantInput = options.autoFocus ?? !coarse;
109865
+ ((wantInput ? options.initialEmail ? passInput : emailInput : title) ?? title)?.focus();
109866
+ safeCall("onOpen", onOpen);
109867
+ const handle = {
109868
+ getState: () => view.getState(),
109869
+ setLocale: (l) => view.setLocale(l),
109870
+ setTheme: (th) => view.setTheme(th),
109871
+ showError: (c, x) => view.showError(c, x),
109872
+ clearError: () => view.clearError(),
109873
+ setNotice: (n) => view.setNotice(n),
109874
+ reset: () => view.reset(),
109875
+ focus: () => view.focus(),
109876
+ close: () => close("api"),
109877
+ destroy: () => close("api"),
109878
+ get isOpen() {
109879
+ return open;
109880
+ }
109881
+ };
109882
+ return handle;
109883
+ }
109884
+
107784
109885
  // src/components/img-gallery/ScrollableTabs.ts
107785
109886
  var STYLE_ID11 = "myio-tabs-styles";
107786
109887
  var FONT_LINK_ID3 = "myio-dialog-font-nunito";
@@ -108417,13 +110518,13 @@ function createImgGallery(options) {
108417
110518
  grid.appendChild(item);
108418
110519
  });
108419
110520
  }
108420
- function actionBtn(icon, label, danger, onClick) {
110521
+ function actionBtn(icon2, label, danger, onClick) {
108421
110522
  const b = document.createElement("button");
108422
110523
  b.type = "button";
108423
110524
  b.className = `myio-gallery__abtn${danger ? " myio-gallery__abtn--danger" : ""}`;
108424
110525
  b.setAttribute("aria-label", label);
108425
110526
  b.title = label;
108426
- b.innerHTML = icon;
110527
+ b.innerHTML = icon2;
108427
110528
  b.addEventListener("click", onClick);
108428
110529
  return b;
108429
110530
  }
@@ -116563,7 +118664,7 @@ var MenuView = class {
116563
118664
  */
116564
118665
  bindFilterTooltipEvents(listEl) {
116565
118666
  const icons = listEl.querySelectorAll(".filter-icon[data-tooltip-type]");
116566
- icons.forEach((icon) => {
118667
+ icons.forEach((icon2) => {
116567
118668
  const showHandler = (e) => {
116568
118669
  e.stopPropagation();
116569
118670
  const el2 = e.currentTarget;
@@ -116574,9 +118675,9 @@ var MenuView = class {
116574
118675
  const hideHandler = () => {
116575
118676
  this.hideFilterTooltips();
116576
118677
  };
116577
- icon.addEventListener("mouseenter", showHandler);
116578
- icon.addEventListener("click", showHandler);
116579
- icon.addEventListener("mouseleave", hideHandler);
118678
+ icon2.addEventListener("mouseenter", showHandler);
118679
+ icon2.addEventListener("click", showHandler);
118680
+ icon2.addEventListener("mouseleave", hideHandler);
116580
118681
  });
116581
118682
  }
116582
118683
  /**
@@ -120398,11 +122499,11 @@ var FilterModalView = class {
120398
122499
  const allTab = this.filterTabs.find((t) => t.id === "all");
120399
122500
  let html = "";
120400
122501
  if (allTab) {
120401
- const icon = FILTER_TAB_ICONS["all"] || "";
122502
+ const icon2 = FILTER_TAB_ICONS["all"] || "";
120402
122503
  html += `
120403
122504
  <div class="filter-group filter-group-all">
120404
122505
  <button class="filter-tab active" data-filter="all">
120405
- ${icon} ${allTab.label} (<span id="countAll">${counts["all"] || 0}</span>)
122506
+ ${icon2} ${allTab.label} (<span id="countAll">${counts["all"] || 0}</span>)
120406
122507
  </button>
120407
122508
  </div>
120408
122509
  `;
@@ -120415,12 +122516,12 @@ var FilterModalView = class {
120415
122516
  <span class="filter-group-label">${group.label}</span>
120416
122517
  <div class="filter-group-tabs">
120417
122518
  ${groupTabs.map((tab) => {
120418
- const icon = FILTER_TAB_ICONS[tab.id] || "";
122519
+ const icon2 = FILTER_TAB_ICONS[tab.id] || "";
120419
122520
  const count = counts[tab.id] || 0;
120420
122521
  const expandBtn = count > 0 ? `<button class="filter-tab-expand" data-expand-filter="${tab.id}" title="Ver dispositivos">+</button>` : "";
120421
122522
  return `
120422
122523
  <button class="filter-tab active" data-filter="${tab.id}">
120423
- ${icon} ${tab.label} (<span id="count${tab.id.charAt(0).toUpperCase() + tab.id.slice(1)}">${count}</span>)${expandBtn}
122524
+ ${icon2} ${tab.label} (<span id="count${tab.id.charAt(0).toUpperCase() + tab.id.slice(1)}">${count}</span>)${expandBtn}
120424
122525
  </button>
120425
122526
  `;
120426
122527
  }).join("")}
@@ -120797,7 +122898,7 @@ var FilterModalView = class {
120797
122898
  if (!InfoTooltip2?.InfoTooltip) return;
120798
122899
  const filterTabConfig = this.filterTabs.find((t) => t.id === filterId);
120799
122900
  const label = filterTabConfig?.label || filterId;
120800
- const icon = FILTER_TAB_ICONS[filterId] || "\u{1F4CB}";
122901
+ const icon2 = FILTER_TAB_ICONS[filterId] || "\u{1F4CB}";
120801
122902
  let devicesHtml = "";
120802
122903
  if (devices.length === 0) {
120803
122904
  devicesHtml = `
@@ -120849,7 +122950,7 @@ var FilterModalView = class {
120849
122950
  `;
120850
122951
  }
120851
122952
  InfoTooltip2.InfoTooltip.show(triggerEl, {
120852
- icon,
122953
+ icon: icon2,
120853
122954
  title: `${label} (${devices.length})`,
120854
122955
  content: devicesHtml
120855
122956
  });
@@ -121714,7 +123815,7 @@ var FilterModalComponent = class {
121714
123815
  }
121715
123816
  // ── Private ────────────────────────────────
121716
123817
  render() {
121717
- const { title, icon, categories, sortOptions, devices = [] } = this.options;
123818
+ const { title, icon: icon2, categories, sortOptions, devices = [] } = this.options;
121718
123819
  const hasDevices = this.showDeviceGrid && devices.length > 0;
121719
123820
  const modalClass = `myio-fm myio-fm--${this.themeMode}${hasDevices ? " myio-fm--with-devices" : ""}`;
121720
123821
  const bodyClass = `myio-fm__body${hasDevices ? " myio-fm__body--two-col" : ""}`;
@@ -121722,7 +123823,7 @@ var FilterModalComponent = class {
121722
123823
  <div class="${modalClass}">
121723
123824
  <div class="myio-fm__header">
121724
123825
  <div class="myio-fm__header-left">
121725
- ${icon ? `<span class="myio-fm__icon">${icon}</span>` : ""}
123826
+ ${icon2 ? `<span class="myio-fm__icon">${icon2}</span>` : ""}
121726
123827
  <h2 class="myio-fm__title">${this.escapeHtml(title)}</h2>
121727
123828
  </div>
121728
123829
  <button class="myio-fm__close" title="Fechar">
@@ -121801,7 +123902,7 @@ var FilterModalComponent = class {
121801
123902
  renderDeviceItem(device) {
121802
123903
  const isSelected = this.selectedDeviceIds.has(device.id);
121803
123904
  const statusClass = device.status ? `myio-fm__device-status--${device.status}` : "";
121804
- const icon = device.icon || this.getDefaultDeviceIcon(device.type, device.context);
123905
+ const icon2 = device.icon || this.getDefaultDeviceIcon(device.type, device.context);
121805
123906
  return `
121806
123907
  <div class="myio-fm__device-item${isSelected ? " myio-fm__device-item--selected" : ""}"
121807
123908
  data-device-id="${device.id}"
@@ -121809,7 +123910,7 @@ var FilterModalComponent = class {
121809
123910
  <div class="myio-fm__device-checkbox">
121810
123911
  ${ICON_CHECK}
121811
123912
  </div>
121812
- ${icon ? `<span class="myio-fm__device-icon">${icon}</span>` : ""}
123913
+ ${icon2 ? `<span class="myio-fm__device-icon">${icon2}</span>` : ""}
121813
123914
  <div class="myio-fm__device-info">
121814
123915
  <p class="myio-fm__device-label" title="${this.escapeHtml(device.label)}">${this.escapeHtml(device.label)}</p>
121815
123916
  ${device.type ? `<p class="myio-fm__device-type">${this.escapeHtml(device.type)}</p>` : ""}
@@ -122577,7 +124678,7 @@ function createCustomerCardV1(params) {
122577
124678
 
122578
124679
  // src/components/cards/customer-goals/v1.0.0/styles.ts
122579
124680
  var STYLE_ID13 = "myio-customer-goals-card-css";
122580
- var CSS3 = `
124681
+ var CSS4 = `
122581
124682
  .myio-cgc{
122582
124683
  --cgc-surface:#ffffff;
122583
124684
  --cgc-border:#e2e8f0;
@@ -122680,7 +124781,7 @@ function injectCustomerGoalsCardStyles() {
122680
124781
  if (document.getElementById(STYLE_ID13)) return;
122681
124782
  const tag = document.createElement("style");
122682
124783
  tag.id = STYLE_ID13;
122683
- tag.textContent = CSS3;
124784
+ tag.textContent = CSS4;
122684
124785
  document.head.appendChild(tag);
122685
124786
  }
122686
124787
 
@@ -123795,13 +125896,13 @@ var EnergyPanelView = class {
123795
125896
  /**
123796
125897
  * Build a single card HTML with the TELEMETRY_INFO-inspired layout
123797
125898
  */
123798
- buildCardHTML(type, icon, title, value, percentage, tooltip) {
125899
+ buildCardHTML(type, icon2, title, value, percentage, tooltip) {
123799
125900
  const percDisplay = percentage !== null ? `(${percentage}%)` : "";
123800
125901
  const tooltipHTML = tooltip ? `<span class="energy-panel__card-tooltip" title="${tooltip}">\u2139\uFE0F</span>` : "";
123801
125902
  return `
123802
125903
  <div class="energy-panel__card" data-type="${type}">
123803
125904
  <div class="energy-panel__card-header">
123804
- <span class="energy-panel__card-icon">${icon}</span>
125905
+ <span class="energy-panel__card-icon">${icon2}</span>
123805
125906
  <h3 class="energy-panel__card-title">${title}</h3>
123806
125907
  ${tooltipHTML}
123807
125908
  </div>
@@ -126942,7 +129043,7 @@ var HeaderShoppingView = class {
126942
129043
  emit(event, ...args) {
126943
129044
  const handlers = this.eventHandlers.get(event);
126944
129045
  if (handlers) {
126945
- handlers.forEach((h2) => h2(...args));
129046
+ handlers.forEach((h3) => h3(...args));
126946
129047
  }
126947
129048
  }
126948
129049
  /**
@@ -127398,7 +129499,7 @@ function createHeaderShoppingComponent(params) {
127398
129499
  function emit(event, ...args) {
127399
129500
  const handlers = eventHandlers.get(event);
127400
129501
  if (handlers) {
127401
- handlers.forEach((h2) => h2(...args));
129502
+ handlers.forEach((h3) => h3(...args));
127402
129503
  }
127403
129504
  }
127404
129505
  function on(event, handler) {
@@ -128288,7 +130389,7 @@ var MenuShoppingView = class {
128288
130389
  emit(event, ...args) {
128289
130390
  const handlers = this.eventHandlers.get(event);
128290
130391
  if (handlers) {
128291
- handlers.forEach((h2) => h2(...args));
130392
+ handlers.forEach((h3) => h3(...args));
128292
130393
  }
128293
130394
  }
128294
130395
  /**
@@ -128457,7 +130558,7 @@ function createMenuShoppingComponent(params) {
128457
130558
  function emitEvent(event, ...args) {
128458
130559
  const handlers = eventHandlers.get(event);
128459
130560
  if (handlers) {
128460
- handlers.forEach((h2) => h2(...args));
130561
+ handlers.forEach((h3) => h3(...args));
128461
130562
  }
128462
130563
  }
128463
130564
  function cleanup() {
@@ -130450,8 +132551,8 @@ var TelemetryGridShoppingView = class {
130450
132551
  }
130451
132552
  }
130452
132553
  }
130453
- const icon = this.isMaximized ? '<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/>' : '<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>';
130454
- this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${icon}</svg>`;
132554
+ const icon2 = this.isMaximized ? '<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/>' : '<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>';
132555
+ this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${icon2}</svg>`;
130455
132556
  }
130456
132557
  };
130457
132558
 
@@ -132382,9 +134483,9 @@ var TelemetryInfoShoppingView = class _TelemetryInfoShoppingView {
132382
134483
  this.maximizeBtnEl.style.opacity = "0";
132383
134484
  }
132384
134485
  }
132385
- const icon = this.isMaximized ? '<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" fill="currentColor"/>' : '<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" fill="currentColor"/>';
134486
+ const icon2 = this.isMaximized ? '<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" fill="currentColor"/>' : '<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" fill="currentColor"/>';
132386
134487
  if (this.maximizeBtnEl) {
132387
- this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${icon}</svg>`;
134488
+ this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${icon2}</svg>`;
132388
134489
  }
132389
134490
  this.params.onExpandClick?.();
132390
134491
  }
@@ -139424,7 +141525,7 @@ function renderTrendChart(data, options = {}) {
139424
141525
  Cr\xEDticos
139425
141526
  </span>
139426
141527
  </div>`;
139427
- const svg = `
141528
+ const svg2 = `
139428
141529
  <svg class="alarms-trend-chart" viewBox="0 0 ${width} ${height}" preserveAspectRatio="xMidYMid meet">
139429
141530
  <defs>
139430
141531
  <linearGradient id="gradTotal" x1="0" y1="0" x2="0" y2="1">
@@ -139445,7 +141546,7 @@ function renderTrendChart(data, options = {}) {
139445
141546
  <circle cx="${lastCritical[0].toFixed(1)}" cy="${lastCritical[1].toFixed(1)}" r="4" fill="${criticalColor}" />
139446
141547
  ${xLabels}
139447
141548
  </svg>`;
139448
- return `<div class="alarms-trend-wrap">${svg}${legend}</div>`;
141549
+ return `<div class="alarms-trend-wrap">${svg2}${legend}</div>`;
139449
141550
  }
139450
141551
  function renderStateDonutChart(byState, options = {}) {
139451
141552
  if (!byState) return renderEmptyChart(200, 200, "Sem dados");
@@ -140489,8 +142590,8 @@ var AlarmsNotificationsPanelView = class {
140489
142590
  }
140490
142591
  const th = (label, col, extraClass = "") => {
140491
142592
  const active = this.sortCol === col;
140492
- const icon = active ? `<span class="atbl-sort-icon is-active">${this.sortDir === "asc" ? "\u25B2" : "\u25BC"}</span>` : `<span class="atbl-sort-icon">\u21C5</span>`;
140493
- return `<th class="atbl-th atbl-th--sortable${extraClass ? " " + extraClass : ""}${active ? " is-sorted" : ""}" data-sort-col="${col}">${label}${icon}</th>`;
142593
+ const icon2 = active ? `<span class="atbl-sort-icon is-active">${this.sortDir === "asc" ? "\u25B2" : "\u25BC"}</span>` : `<span class="atbl-sort-icon">\u21C5</span>`;
142594
+ return `<th class="atbl-th atbl-th--sortable${extraClass ? " " + extraClass : ""}${active ? " is-sorted" : ""}" data-sort-col="${col}">${label}${icon2}</th>`;
140494
142595
  };
140495
142596
  const rows = alarms.map((alarm) => {
140496
142597
  const sev = SEVERITY_CONFIG[alarm.severity];
@@ -144097,9 +146198,9 @@ function renderDualLineChart(data) {
144097
146198
  }
144098
146199
  function formatTrendIndicator(trend) {
144099
146200
  if (trend === void 0 || trend === 0) return "";
144100
- const icon = trend > 0 ? "\u2191" : "\u2193";
146201
+ const icon2 = trend > 0 ? "\u2191" : "\u2193";
144101
146202
  const cls = trend > 0 ? "trend-up" : "trend-down";
144102
- return `<span class="trend-indicator ${cls}">${icon}${Math.abs(trend)}</span>`;
146203
+ return `<span class="trend-indicator ${cls}">${icon2}${Math.abs(trend)}</span>`;
144103
146204
  }
144104
146205
  function renderStatusDonutChart(kpis, period) {
144105
146206
  const offlineCritical = kpis.offlineCriticalCount || 0;
@@ -144405,10 +146506,10 @@ function formatHoursDisplay(hours) {
144405
146506
  const mins = Math.round(hours * 60);
144406
146507
  return `${mins}min`;
144407
146508
  }
144408
- const h2 = Math.floor(hours);
144409
- const m = Math.round((hours - h2) * 60);
144410
- if (m === 0) return `${h2}h`;
144411
- return `${h2}h${String(m).padStart(2, "0")}`;
146509
+ const h3 = Math.floor(hours);
146510
+ const m = Math.round((hours - h3) * 60);
146511
+ if (m === 0) return `${h3}h`;
146512
+ return `${h3}h${String(m).padStart(2, "0")}`;
144412
146513
  }
144413
146514
  function renderMTBFTimelineChart(data) {
144414
146515
  if (!data.segments || data.segments.length === 0) {
@@ -147860,12 +149961,12 @@ var SwitchControlView = class {
147860
149961
  document.querySelectorAll(`.${SWITCH_CONTROL_CSS_PREFIX}__modal-overlay`).forEach((el2) => el2.remove());
147861
149962
  const { labels } = this.settings;
147862
149963
  const newStatus = this.state.status === "on" ? "off" : "on";
147863
- const icon = newStatus === "on" ? "\u{1F4A1}" : "\u{1F50C}";
149964
+ const icon2 = newStatus === "on" ? "\u{1F4A1}" : "\u{1F50C}";
147864
149965
  const modal = document.createElement("div");
147865
149966
  modal.className = `${SWITCH_CONTROL_CSS_PREFIX}__modal-overlay`;
147866
149967
  modal.innerHTML = `
147867
149968
  <div class="${SWITCH_CONTROL_CSS_PREFIX}__modal">
147868
- <div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-icon">${icon}</div>
149969
+ <div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-icon">${icon2}</div>
147869
149970
  <h3 class="${SWITCH_CONTROL_CSS_PREFIX}__modal-title">${this.escapeHtml(this.state.name)}</h3>
147870
149971
  <p class="${SWITCH_CONTROL_CSS_PREFIX}__modal-message">${message}</p>
147871
149972
  <div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-actions">
@@ -148192,7 +150293,7 @@ var ActionButtonView = class {
148192
150293
  return classes.join(" ");
148193
150294
  }
148194
150295
  applyAll() {
148195
- const { label, icon, variant, color, textColor, borderRadius, disabled, tooltip } = this.settings;
150296
+ const { label, icon: icon2, variant, color, textColor, borderRadius, disabled, tooltip } = this.settings;
148196
150297
  this.root.className = this.buildClassName();
148197
150298
  this.root.disabled = disabled;
148198
150299
  this.root.style.borderRadius = `${borderRadius}px`;
@@ -148205,8 +150306,8 @@ var ActionButtonView = class {
148205
150306
  this.root.style.color = textColor || color;
148206
150307
  }
148207
150308
  let html = "";
148208
- if (icon) {
148209
- html += `<span class="${ACTION_BUTTON_CSS_PREFIX}__icon">${this.escapeHtml(icon)}</span>`;
150309
+ if (icon2) {
150310
+ html += `<span class="${ACTION_BUTTON_CSS_PREFIX}__icon">${this.escapeHtml(icon2)}</span>`;
148210
150311
  }
148211
150312
  if (label) {
148212
150313
  html += `<span>${this.escapeHtml(label)}</span>`;
@@ -152476,12 +154577,12 @@ function renderTimelineSVG(data, config2) {
152476
154577
  const segWidth = Math.max(x2 - x1, 4);
152477
154578
  const isOn = seg.state === "on";
152478
154579
  const y = isOn ? onY : offY - 15;
152479
- const h2 = isOn ? barHeight : 15;
154580
+ const h3 = isOn ? barHeight : 15;
152480
154581
  const color = isOn ? onColor : offColor;
152481
154582
  const stateClass = isOn ? "on" : "off";
152482
154583
  segmentPaths += `
152483
154584
  <rect
152484
- x="${x1}" y="${y}" width="${segWidth}" height="${h2}"
154585
+ x="${x1}" y="${y}" width="${segWidth}" height="${h3}"
152485
154586
  fill="${color}" rx="3"
152486
154587
  class="${ONOFF_TIMELINE_CSS_PREFIX}__segment ${ONOFF_TIMELINE_CSS_PREFIX}__segment--${stateClass}"
152487
154588
  data-index="${index}"
@@ -152489,7 +154590,7 @@ function renderTimelineSVG(data, config2) {
152489
154590
  `;
152490
154591
  if (showDurationLabels && segWidth > 45) {
152491
154592
  const centerX = x1 + segWidth / 2;
152492
- const centerY = y + h2 / 2 + 3;
154593
+ const centerY = y + h3 / 2 + 3;
152493
154594
  durationLabels += `
152494
154595
  <text
152495
154596
  x="${centerX}" y="${centerY}"
@@ -152516,7 +154617,7 @@ function renderTimelineSVG(data, config2) {
152516
154617
  }
152517
154618
  tooltipAreas += `
152518
154619
  <rect
152519
- x="${x1}" y="${y}" width="${segWidth}" height="${h2}"
154620
+ x="${x1}" y="${y}" width="${segWidth}" height="${h3}"
152520
154621
  fill="transparent"
152521
154622
  class="tooltip-trigger"
152522
154623
  data-state="${stateClass}"
@@ -153925,15 +156026,15 @@ var OnOffDeviceModalView = class {
153925
156026
  if (!anchor) return;
153926
156027
  const ev = this.evalDeviceStatus();
153927
156028
  if (!ev.statusStale && !ev.connectionStale) return;
153928
- const icon = document.createElement("span");
153929
- icon.className = `${ON_OFF_MODAL_CSS_PREFIX}__status-warning`;
153930
- icon.textContent = "\u26A0\uFE0F";
153931
- icon.style.cssText = "cursor: help; font-size: 16px; margin-left: 8px; line-height: 1; user-select: none; display: inline-block;";
153932
- icon.setAttribute("aria-label", "Telemetria de status desatualizada");
153933
- anchor.appendChild(icon);
156029
+ const icon2 = document.createElement("span");
156030
+ icon2.className = `${ON_OFF_MODAL_CSS_PREFIX}__status-warning`;
156031
+ icon2.textContent = "\u26A0\uFE0F";
156032
+ icon2.style.cssText = "cursor: help; font-size: 16px; margin-left: 8px; line-height: 1; user-select: none; display: inline-block;";
156033
+ icon2.setAttribute("aria-label", "Telemetria de status desatualizada");
156034
+ anchor.appendChild(icon2);
153934
156035
  const when = formatStatusTimestamp(ev.statusTs);
153935
156036
  const lastValue = (ev.value || "\u2014").toString().toUpperCase();
153936
- this.statusWarnTooltipCleanup = InfoTooltip_default.attach(icon, () => ({
156037
+ this.statusWarnTooltipCleanup = InfoTooltip_default.attach(icon2, () => ({
153937
156038
  icon: "\u26A0\uFE0F",
153938
156039
  title: "Status possivelmente desatualizado",
153939
156040
  content: `A \xFAltima telemetria de <b>status</b> foi em <b>${when}</b>, h\xE1 mais de ${STATUS_FRESHNESS_MAX_HOURS} horas.<br><br>O estado exibido (<b>${lastValue}</b>) \xE9 o \xFAltimo conhecido e pode n\xE3o refletir o estado atual do dispositivo.`
@@ -154072,8 +156173,8 @@ var OnOffDeviceModalView = class {
154072
156173
  actions.appendChild(btnYes);
154073
156174
  actions.appendChild(btnNo);
154074
156175
  } else {
154075
- const icon = type === "success" ? "\u2705" : "\u274C";
154076
- msg.textContent = `${icon} ${message}`;
156176
+ const icon2 = type === "success" ? "\u2705" : "\u274C";
156177
+ msg.textContent = `${icon2} ${message}`;
154077
156178
  const btnClose = document.createElement("button");
154078
156179
  btnClose.textContent = "Fechar";
154079
156180
  btnClose.style.cssText = `
@@ -154207,12 +156308,12 @@ var OnOffDeviceModalView = class {
154207
156308
  this.updateScheduleButton("\u{1F4C5}", "Agendamento");
154208
156309
  }
154209
156310
  }
154210
- updateScheduleButton(icon, label) {
156311
+ updateScheduleButton(icon2, label) {
154211
156312
  const btn = this.scheduleButtonContainer?.querySelector(`.${ON_OFF_MODAL_CSS_PREFIX}__schedule-btn`);
154212
156313
  if (btn) {
154213
156314
  const iconEl = btn.querySelector("[data-icon]");
154214
156315
  const labelEl = btn.querySelector("[data-label]");
154215
- if (iconEl) iconEl.textContent = icon;
156316
+ if (iconEl) iconEl.textContent = icon2;
154216
156317
  if (labelEl) labelEl.textContent = label;
154217
156318
  }
154218
156319
  }
@@ -159292,10 +161393,10 @@ function renderStep22(plan) {
159292
161393
  const customers = nonSkip.filter((a) => a.entityKind === "customer");
159293
161394
  const assets = nonSkip.filter((a) => a.entityKind === "asset");
159294
161395
  const devices = nonSkip.filter((a) => a.entityKind === "device");
159295
- function sectionHtml(icon, title, actions) {
161396
+ function sectionHtml(icon2, title, actions) {
159296
161397
  if (actions.length === 0) return "";
159297
161398
  return `
159298
- <div class="gcdr-section-title">${icon} ${title} (${actions.length})</div>
161399
+ <div class="gcdr-section-title">${icon2} ${title} (${actions.length})</div>
159299
161400
  <ul class="gcdr-action-list">
159300
161401
  ${actions.map((a) => `
159301
161402
  <li class="gcdr-action-item">
@@ -159986,9 +162087,9 @@ function formatDuration3(ms) {
159986
162087
  if (!ms) return "";
159987
162088
  const min = Math.round(ms / 6e4);
159988
162089
  if (min < 60) return `${min} min`;
159989
- const h2 = Math.floor(min / 60);
162090
+ const h3 = Math.floor(min / 60);
159990
162091
  const rem = min % 60;
159991
- return rem > 0 ? `${h2}h ${rem}min` : `${h2}h`;
162092
+ return rem > 0 ? `${h3}h ${rem}min` : `${h3}h`;
159992
162093
  }
159993
162094
  function renderDaysOfWeek(daysOfWeek) {
159994
162095
  if (!daysOfWeek) return "";
@@ -161120,9 +163221,9 @@ var ProvisioningApiClient = class {
161120
163221
  const newLogs = logs.filter((l) => l.id > lastLogId);
161121
163222
  for (const entry of newLogs) {
161122
163223
  const time = (entry.timestamp ?? "").split(" ")[1] ?? "";
161123
- const icon = STEP_ICONS[entry.step] ?? "\u{1F4CB}";
163224
+ const icon2 = STEP_ICONS[entry.step] ?? "\u{1F4CB}";
161124
163225
  if (entry.level === "INFO" && !entry.message.includes("Progress updated to")) {
161125
- onLog(`${icon} [${time}] ${entry.message}`);
163226
+ onLog(`${icon2} [${time}] ${entry.message}`);
161126
163227
  }
161127
163228
  }
161128
163229
  if (newLogs.length > 0) {
@@ -161245,22 +163346,22 @@ function drawFooter(doc, pageW, pageH, footerH, pageNo, pageCount) {
161245
163346
  doc.setTextColor(40);
161246
163347
  doc.text(label, bx + padX, baseline);
161247
163348
  }
161248
- async function drawTag(doc, x, y, w, h2, device, gateway, allDevices) {
163349
+ async function drawTag(doc, x, y, w, h3, device, gateway, allDevices) {
161249
163350
  const FRAME_SCALE_Y = 1.05;
161250
163351
  const QR_SCALE = 1.7;
161251
163352
  const QR_SHIFT_Y = 3;
161252
163353
  const GAP_AFTER_QR = 6;
161253
- const frameH = h2 * FRAME_SCALE_Y;
161254
- const frameY = y - (frameH - h2) / 2;
163354
+ const frameH = h3 * FRAME_SCALE_Y;
163355
+ const frameY = y - (frameH - h3) / 2;
161255
163356
  doc.setDrawColor(235);
161256
163357
  doc.setLineWidth(0.15);
161257
163358
  doc.rect(x, frameY, w, frameH);
161258
- const pad = Math.max(2, h2 * 0.05);
163359
+ const pad = Math.max(2, h3 * 0.05);
161259
163360
  const innerX = x + pad;
161260
163361
  const innerW = w - pad * 2;
161261
- const titleAreaH = h2 * 0.15;
163362
+ const titleAreaH = h3 * 0.15;
161262
163363
  const qrAreaTop = y + titleAreaH;
161263
- const qrAreaH = h2 - titleAreaH - 12;
163364
+ const qrAreaH = h3 - titleAreaH - 12;
161264
163365
  const displayName = generateDeviceNameWithPrefix(device, void 0, allDevices);
161265
163366
  const rawName = sanitizePdf(displayName);
161266
163367
  const nameFont = Math.max(6, Math.min(11, titleAreaH * 0.45));
@@ -165869,10 +167970,10 @@ ${this._renderToolbar(filteredCount, totalAllUnfiltered)}
165869
167970
  const collapseAllBtn = this.root.querySelector('[data-action="collapse-all"]');
165870
167971
  if (collapseAllBtn) collapseAllBtn.addEventListener("click", () => this._collapseAll());
165871
167972
  const groupHeaders = this.root.querySelectorAll("[data-group-toggle]");
165872
- groupHeaders.forEach((h2) => {
165873
- const key = h2.getAttribute("data-group-toggle") || "";
165874
- h2.addEventListener("click", () => this._toggleGroupCollapsed(key));
165875
- h2.addEventListener("keydown", (e) => {
167973
+ groupHeaders.forEach((h3) => {
167974
+ const key = h3.getAttribute("data-group-toggle") || "";
167975
+ h3.addEventListener("click", () => this._toggleGroupCollapsed(key));
167976
+ h3.addEventListener("keydown", (e) => {
165876
167977
  const ke = e;
165877
167978
  if (ke.key === "Enter" || ke.key === " ") {
165878
167979
  ke.preventDefault();
@@ -166404,7 +168505,7 @@ function validateDeviceProductCode(code) {
166404
168505
 
166405
168506
  // src/components/cards/central-status/v1.0.0/styles.ts
166406
168507
  var STYLE_ID16 = "myio-central-status-card-styles";
166407
- var CSS4 = `
168508
+ var CSS5 = `
166408
168509
  .myio-cscard{
166409
168510
  --cscard-surface:#ffffff;
166410
168511
  --cscard-border:#e2e8f0;
@@ -166709,7 +168810,7 @@ function injectCentralStatusCardStyles() {
166709
168810
  if (document.getElementById(STYLE_ID16)) return;
166710
168811
  const tag = document.createElement("style");
166711
168812
  tag.id = STYLE_ID16;
166712
- tag.textContent = CSS4;
168813
+ tag.textContent = CSS5;
166713
168814
  document.head.appendChild(tag);
166714
168815
  }
166715
168816
 
@@ -168312,6 +170413,9 @@ var version = package_default.version || "0.0.0";
168312
170413
  createModalHeader,
168313
170414
  createMoneyVarianceColumn,
168314
170415
  createMyIOTheme,
170416
+ createMyioGcdrLoginSubmit,
170417
+ createMyioGcdrLoginView,
170418
+ createMyioGcdrShell,
168315
170419
  createNewTicketWizard,
168316
170420
  createOnOffDeviceModal,
168317
170421
  createOnOffTimelineChart,
@@ -168552,6 +170656,7 @@ var version = package_default.version || "0.0.0";
168552
170656
  isInRange,
168553
170657
  isLeapYear,
168554
170658
  isMoneyColumnConfident,
170659
+ isMyioGcdrLoginModalOpen,
168555
170660
  isOnOffDeviceProfile,
168556
170661
  isSolenoidDevice,
168557
170662
  isStoreDevice,
@@ -168613,6 +170718,7 @@ var version = package_default.version || "0.0.0";
168613
170718
  openMeasurementSetupModal,
168614
170719
  openMessageDialog,
168615
170720
  openMetasGuide,
170721
+ openMyioGcdrLoginModal,
168616
170722
  openOnOffDeviceModal,
168617
170723
  openOnboardModal,
168618
170724
  openOperationalComparisonModal,