SPAN Panel
Live Power
-
${e}
+
${t}
${i("card.no_device")}
-
- `}};Xt.styles=$('\n :host {\n --span-accent: var(--primary-color, #4dd9af);\n }\n\n ha-card {\n padding: 24px;\n background: var(--card-background-color, #1c1c1c);\n color: var(--primary-text-color, #e0e0e0);\n border-radius: var(--ha-card-border-radius, 12px);\n border: var(--ha-card-border-width, 1px) solid var(--ha-card-border-color, var(--divider-color, #333));\n box-shadow: var(--ha-card-box-shadow, none);\n }\n\n .panel-header {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: flex-start;\n gap: 8px 16px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--divider-color, #333);\n }\n .header-left { flex: 1 1 300px; min-width: 0; }\n .header-center { flex: 0 0 auto; }\n .header-right { flex: 0 1 auto; min-width: 0; }\n\n .panel-identity {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px 12px;\n margin-bottom: 12px;\n }\n\n .panel-title {\n font-size: 1.8em;\n font-weight: 700;\n margin: 0;\n color: var(--primary-text-color, #fff);\n }\n\n .panel-serial {\n font-size: 0.85em;\n color: var(--secondary-text-color, #999);\n font-family: monospace;\n }\n\n .panel-stats {\n display: flex;\n flex-wrap: wrap;\n gap: 16px 32px;\n }\n\n /* Favorites view header: gear + slide-to-arm + right-anchored legend/W-A cluster. */\n .favorites-summary {\n padding: 8px 24px;\n border-bottom: 1px solid var(--divider-color, #e0e0e0);\n display: flex;\n align-items: center;\n gap: 12px;\n }\n /* Override the generic .gear-icon { margin-left: auto } rule so the\n favorites gear stays flush-left instead of floating to the right of\n the flex row (same idea as .panel-identity .panel-gear does for\n real-panel headers). */\n .favorites-summary .favorites-gear {\n margin-left: 0;\n }\n /* Right-anchored cluster wrapping the shedding legend + W/A unit toggle.\n margin-left:auto moved here from .favorites-summary-unit-toggle so the\n legend and toggle cluster together, matching the real-panel header\n layout. */\n .favorites-summary-right {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 16px;\n }\n .favorites-subdevices-section {\n padding: 8px 16px 0;\n }\n\n /* Favorites view: responsive grid of per-contributing-panel status cards. */\n .favorites-panel-stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));\n gap: 12px;\n padding: 12px 24px;\n border-bottom: 1px solid var(--divider-color, #333);\n }\n .favorites-panel-card {\n background: var(--secondary-background-color, rgba(255, 255, 255, 0.04));\n border: 1px solid var(--divider-color, #333);\n border-radius: 8px;\n padding: 10px 14px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .favorites-panel-card-title {\n font-size: 0.85em;\n font-weight: 600;\n color: var(--primary-text-color);\n opacity: 0.85;\n }\n .favorites-panel-card .panel-stats {\n gap: 10px 20px;\n }\n .favorites-panel-card .stat-value {\n font-size: 1.15em;\n }\n\n .stat { display: flex; flex-direction: column; }\n .stat-label { font-size: 0.8em; color: var(--secondary-text-color, #999); margin-bottom: 2px; }\n .stat-row { display: flex; align-items: baseline; gap: 2px; }\n .stat-value { font-size: 1.5em; font-weight: 700; color: var(--primary-text-color, #fff); }\n .stat-unit { font-size: 0.7em; font-weight: 400; color: var(--secondary-text-color, #999); }\n\n .header-right { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; padding-top: 8px; }\n .header-right-top { display: flex; gap: 20px; align-items: center; }\n .meta-item { font-size: 0.8em; color: var(--secondary-text-color, #999); }\n\n .shedding-legend { display: flex; gap: 12px; flex-wrap: wrap; justify-content: flex-end; }\n .shedding-legend-item { display: inline-flex; align-items: center; gap: 3px; }\n .shedding-legend-item ha-icon { --mdc-icon-size: 16px; }\n .shedding-legend-secondary { --mdc-icon-size: 12px; opacity: 0.8; }\n .shedding-legend-text { font-size: 9px; font-weight: 600; }\n .shedding-legend-label { font-size: 0.7em; color: var(--secondary-text-color, #999); }\n\n .panel-gear {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--secondary-text-color);\n opacity: 0.6;\n padding: 4px;\n margin-left: 8px;\n vertical-align: middle;\n }\n .panel-gear:hover { opacity: 1; }\n .header-center {\n display: flex;\n align-items: flex-start;\n justify-content: center;\n padding-top: 8px;\n }\n .panel-identity .panel-gear {\n margin-left: 0;\n }\n .slide-confirm {\n position: relative;\n display: inline-flex;\n align-items: center;\n width: 160px;\n height: 28px;\n border-radius: 14px;\n background: color-mix(in srgb, var(--primary-color, #4dd9af) 20%, var(--secondary-background-color, #333));\n vertical-align: middle;\n overflow: hidden;\n user-select: none;\n touch-action: none;\n }\n .slide-confirm-text {\n position: absolute;\n width: 100%;\n text-align: center;\n font-size: 0.65em;\n font-weight: 600;\n color: var(--secondary-text-color, #999);\n pointer-events: none;\n z-index: 0;\n }\n .slide-confirm-knob {\n position: absolute;\n left: 2px;\n top: 2px;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: var(--secondary-text-color, #666);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: grab;\n z-index: 1;\n transition: none;\n }\n .slide-confirm-knob ha-icon {\n --mdc-icon-size: 14px;\n color: var(--card-background-color, #1c1c1c);\n }\n .slide-confirm-knob.snapping {\n transition: left 0.25s ease;\n }\n .slide-confirm.confirmed {\n background: color-mix(in srgb, var(--state-active-color, var(--span-accent)) 25%, transparent);\n }\n .slide-confirm.confirmed .slide-confirm-text {\n color: var(--state-active-color, var(--span-accent));\n }\n .slide-confirm.confirmed .slide-confirm-knob {\n background: var(--state-active-color, var(--span-accent));\n }\n .switches-disabled .toggle-pill {\n opacity: 0.3;\n pointer-events: none;\n }\n .unit-toggle {\n display: inline-flex;\n background: var(--secondary-background-color, #333);\n border-radius: 6px;\n overflow: hidden;\n margin-left: 8px;\n }\n .unit-btn {\n padding: 4px 10px;\n border: none;\n background: none;\n color: var(--secondary-text-color);\n font-size: 0.75em;\n font-weight: 600;\n cursor: pointer;\n }\n .unit-btn.unit-active {\n background: var(--primary-color, #4dd9af);\n color: var(--text-primary-color, #000);\n }\n\n .monitoring-summary {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 6px 16px;\n font-size: 0.8em;\n background: rgba(76, 175, 80, 0.1);\n border: 1px solid var(--divider-color, #333);\n border-top: none;\n }\n .monitoring-active { color: #4caf50; }\n .monitoring-counts { display: flex; gap: 12px; }\n .count-warning { color: #ff9800; }\n .count-alert { color: #f44336; }\n .count-overrides { color: var(--secondary-text-color); }\n\n .panel-grid {\n display: grid;\n grid-template-columns: 28px 1fr 1fr 28px;\n gap: 8px;\n align-items: stretch;\n }\n\n .tab-label {\n display: flex;\n align-items: center;\n font-size: 0.85em;\n font-weight: 600;\n color: var(--secondary-text-color, #999);\n user-select: none;\n }\n .tab-left { justify-content: flex-start; }\n .tab-right { justify-content: flex-end; }\n\n .circuit-slot {\n background: var(--secondary-background-color, var(--card-background-color, #2a2a2a));\n border: 1px solid var(--divider-color, #333);\n border-radius: 12px;\n padding: 14px 16px 20px;\n min-height: 140px;\n transition: opacity 0.3s;\n position: relative;\n overflow: hidden;\n }\n\n .circuit-col-span { min-height: 280px; }\n .circuit-row-span { border-left: 3px solid var(--span-accent); }\n .circuit-off .circuit-name,\n .circuit-off .breaker-badge,\n .circuit-off .power-value,\n .circuit-off .chart-container { opacity: 0.35; }\n .circuit-off .toggle-pill,\n .circuit-off .gear-icon { opacity: 1; }\n\n .circuit-empty {\n opacity: 0.2;\n min-height: 60px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-style: dashed;\n }\n .empty-label { color: var(--secondary-text-color, #999); font-size: 0.85em; }\n\n .circuit-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 6px;\n gap: 8px;\n }\n\n .circuit-info { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }\n\n .breaker-badge {\n background: color-mix(in srgb, var(--span-accent) 15%, transparent);\n color: var(--span-accent);\n font-size: 0.7em;\n font-weight: 700;\n padding: 2px 7px;\n border-radius: 4px;\n white-space: nowrap;\n border: 1px solid color-mix(in srgb, var(--span-accent) 25%, transparent);\n flex-shrink: 0;\n }\n\n .circuit-name {\n font-size: 0.9em;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--primary-text-color, #e0e0e0);\n }\n\n .circuit-controls { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }\n\n .power-value { font-size: 0.9em; color: var(--primary-text-color, #fff); white-space: nowrap; }\n .power-value strong { font-weight: 700; font-size: 1.1em; }\n .power-unit { font-size: 0.8em; font-weight: 400; color: var(--secondary-text-color, #999); margin-left: 1px; }\n .circuit-producer .power-value strong { color: var(--info-color, #4fc3f7); }\n\n .toggle-pill {\n display: flex;\n align-items: center;\n gap: 3px;\n padding: 2px 4px;\n border-radius: 10px;\n cursor: pointer;\n font-size: 0.65em;\n font-weight: 600;\n transition: background 0.2s;\n user-select: none;\n min-width: 40px;\n }\n .toggle-on {\n padding-left: 6px;\n background: color-mix(in srgb, var(--state-active-color, var(--span-accent)) 25%, transparent);\n color: var(--state-active-color, var(--span-accent));\n }\n .toggle-off {\n padding-right: 6px;\n background: color-mix(in srgb, var(--secondary-text-color) 15%, transparent);\n color: var(--secondary-text-color, #999);\n }\n .toggle-knob {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n transition: background 0.2s, margin 0.2s;\n }\n .toggle-on .toggle-knob {\n background: var(--state-active-color, var(--span-accent));\n margin-left: auto;\n }\n .toggle-off .toggle-knob {\n background: var(--secondary-text-color, #999);\n margin-right: auto;\n order: -1;\n }\n\n .circuit-status {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-top: 4px;\n padding: 0 4px;\n }\n .shedding-icon { opacity: 0.8; cursor: default; }\n .shedding-composite {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n }\n .shedding-icon-secondary { opacity: 0.8; }\n .shedding-label {\n font-size: 10px;\n font-weight: 600;\n opacity: 0.8;\n }\n .gear-icon {\n background: none;\n border: none;\n cursor: pointer;\n padding: 2px;\n opacity: 0.6;\n transition: opacity 0.2s;\n margin-left: auto;\n }\n .gear-icon:hover { opacity: 1; }\n .utilization {\n font-size: 0.75em;\n font-weight: 600;\n }\n .utilization-normal { color: #4caf50; }\n .utilization-warning { color: #ff9800; }\n .utilization-alert { color: #f44336; }\n .circuit-alert {\n border-color: #f44336 !important;\n box-shadow: 0 0 8px rgba(244, 67, 54, 0.3);\n }\n .circuit-custom-monitoring {\n border-left: 3px solid #ff9800;\n }\n\n .chart-container {\n width: 100%;\n aspect-ratio: 4 / 1;\n margin-top: 4px;\n overflow: hidden;\n min-width: 0;\n }\n\n .sub-devices {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 12px;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 1px solid var(--divider-color, #333);\n }\n\n .sub-device {\n background: var(--secondary-background-color, var(--card-background-color, #2a2a2a));\n border: 1px solid var(--divider-color, #333);\n border-radius: 12px;\n padding: 14px 16px;\n }\n .sub-device-bess,\n .sub-device-full {\n grid-column: 1 / -1;\n }\n\n .sub-device-header { display: flex; gap: 10px; align-items: baseline; margin-bottom: 8px; }\n .sub-device-type { font-size: 0.7em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--span-accent); }\n .sub-device-name { font-size: 0.85em; color: var(--secondary-text-color, #999); flex: 1; }\n .sub-power-value { font-size: 0.9em; color: var(--primary-text-color, #fff); white-space: nowrap; }\n .sub-power-value strong { font-weight: 700; font-size: 1.1em; }\n .sub-device .chart-container { margin-bottom: 8px; aspect-ratio: auto; }\n\n .bess-charts {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(0, 1fr));\n gap: 12px;\n margin-bottom: 10px;\n }\n .bess-chart-col { min-width: 0; }\n .bess-chart-title {\n font-size: 0.75em;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--secondary-text-color, #999);\n margin-bottom: 4px;\n }\n .bess-chart-col .chart-container { aspect-ratio: auto; }\n .sub-entity { display: flex; gap: 6px; padding: 3px 0; font-size: 0.85em; }\n .sub-entity-name { color: var(--secondary-text-color, #999); }\n .sub-entity-value { font-weight: 500; color: var(--primary-text-color, #e0e0e0); }\n\n /* ── Shared tab bar ────────────────────────────────────── */\n\n .shared-tab-bar {\n display: flex;\n gap: 0;\n margin-bottom: 16px;\n border-bottom: 1px solid var(--divider-color, #333);\n }\n\n .shared-tab {\n padding: 8px 16px;\n cursor: pointer;\n font-size: 0.9em;\n font-weight: 500;\n color: var(--primary-text-color);\n opacity: 0.6;\n border: none;\n border-bottom: 2px solid transparent;\n background: none;\n transition: opacity 0.15s;\n }\n\n .shared-tab:hover {\n opacity: 0.85;\n }\n\n .shared-tab.active {\n opacity: 1;\n border-bottom-color: var(--span-accent);\n }\n\n /* ── List view search ──────────────────────────────────── */\n\n .list-search-container {\n margin-bottom: 12px;\n position: relative;\n }\n\n .list-search {\n width: 100%;\n padding: 8px 36px 8px 12px;\n border-radius: 8px;\n border: 1px solid var(--divider-color, #333);\n background: var(--secondary-background-color, #2a2a2a);\n color: var(--primary-text-color);\n font-size: 0.9em;\n box-sizing: border-box;\n outline: none;\n }\n\n .list-search:focus {\n border-color: var(--span-accent);\n }\n\n .list-search-clear {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n color: var(--secondary-text-color);\n cursor: pointer;\n padding: 2px;\n display: flex;\n align-items: center;\n opacity: 0.7;\n }\n\n .list-search-clear:hover {\n opacity: 1;\n }\n\n .list-unit-toggle {\n display: inline-flex;\n margin-bottom: 12px;\n }\n\n /* ── List rows ─────────────────────────────────────────── */\n\n .list-view {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n /* Each circuit is wrapped in a .list-cell so the row + its optional\n expanded chart stay together. In single-column flex mode the cell\n just stacks naturally. In multi-column grid mode the cell becomes\n one grid item, so the chart is always in the same column as its\n row. Area headers (rendered as siblings, not inside a cell) span\n all columns via their inline "grid-column: 1 / -1". */\n .list-cell {\n display: flex;\n flex-direction: column;\n min-width: 0;\n }\n .list-view[data-columns="2"],\n .list-view[data-columns="3"] {\n display: grid;\n grid-template-columns: repeat(var(--list-cols), minmax(0, 1fr));\n gap: 6px 8px;\n flex-direction: initial;\n }\n /* On narrow viewports a 2/3-column list would squeeze rows into an\n unreadable shape, so force stacking regardless of user preference. */\n @media (max-width: 599px) {\n .list-view[data-columns="2"],\n .list-view[data-columns="3"] {\n display: flex;\n flex-direction: column;\n }\n }\n\n .list-row {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n gap: 10px;\n background: var(--card-background-color, #1c1c1c);\n border: 1px solid var(--divider-color, #333);\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .list-row:hover {\n background: var(--secondary-background-color, #2a2a2a);\n }\n\n .list-row.circuit-off {\n opacity: 0.5;\n }\n\n .list-row.list-row-expanded {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n border-bottom-color: transparent;\n }\n\n .list-circuit-name {\n flex: 1;\n color: var(--primary-text-color);\n font-size: 0.9em;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .list-status-badge {\n font-size: 0.75em;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 4px;\n flex-shrink: 0;\n }\n\n .list-status-on {\n color: #4dd9af;\n }\n\n .list-status-off {\n color: #f44336;\n }\n\n .list-power-value {\n font-size: 0.9em;\n font-weight: 600;\n min-width: 70px;\n text-align: right;\n flex-shrink: 0;\n }\n\n .list-expand-toggle {\n background: none;\n border: none;\n color: var(--secondary-text-color);\n cursor: pointer;\n padding: 4px;\n transition: transform 0.2s;\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .list-expand-toggle.expanded {\n transform: rotate(180deg);\n }\n\n .list-row .gear-icon {\n background: transparent;\n border: none;\n padding: 2px;\n cursor: pointer;\n color: #555;\n display: inline-flex;\n align-items: center;\n }\n .list-row .gear-icon:hover {\n color: var(--primary-text-color);\n }\n\n /* ── Expanded circuit content ──────────────────────────── */\n\n .list-expanded-content {\n padding: 0;\n background: var(--card-background-color, #1c1c1c);\n border: 1px solid var(--divider-color, #333);\n border-top: none;\n border-radius: 0 0 8px 8px;\n margin-top: -6px;\n margin-bottom: 2px;\n }\n\n .circuit-slot.circuit-chart-only {\n border: none;\n margin: 0;\n background: none;\n padding: 8px 12px;\n min-height: 0;\n }\n\n /* ── Area headers ──────────────────────────────────────── */\n\n .area-header {\n padding: 16px 12px 6px;\n font-weight: 600;\n font-size: 0.85em;\n color: var(--secondary-text-color);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n /* ── No results ────────────────────────────────────────── */\n\n .list-no-results {\n padding: 24px;\n text-align: center;\n color: var(--secondary-text-color);\n }\n\n'),b([Ne({attribute:!1})],Xt.prototype,"hass",void 0),b([Me()],Xt.prototype,"_config",void 0),b([Me()],Xt.prototype,"_discovered",void 0),b([Me()],Xt.prototype,"_discovering",void 0),b([Me()],Xt.prototype,"_topology",void 0),b([Me()],Xt.prototype,"_activeTab",void 0),Xt=b([ze("span-panel-card")],Xt);class Zt extends HTMLElement{constructor(){super(...arguments),this._config={},this._hass=null,this._panels=null,this._availableRoles=null,this._built=!1,this._panelSelect=null,this._daysInput=null,this._hoursInput=null,this._minsInput=null,this._metricSelect=null,this._checkboxes={},this._entityContainers={},this._tabStyleSelect=null}setConfig(e){this._config={...e},this._updateControls()}set hass(e){this._hass=e,this._panels?this._built||this._buildEditor():this._discoverPanels()}async _discoverPanels(){if(!this._hass)return;const e=await this._hass.callWS({type:"config/device_registry/list"});this._panels=e.filter(e=>(e.identifiers??[]).some(e=>e[0]===l)&&!e.via_device_id).map(e=>{const t=(e.identifiers??[]).find(e=>e[0]===l)?.[1]??"",n=e.name_by_user??e.name??i("editor.panel_label");return{device_id:e.id,label:`${n} (${t})`}}),this._buildEditor()}_buildEditor(){this.innerHTML="",this._built=!0;const e=document.createElement("div");e.style.padding="16px";const t="\n width: 100%;\n padding: 10px 12px;\n border-radius: 8px;\n border: 1px solid var(--divider-color, #333);\n background: var(--card-background-color, var(--secondary-background-color, #1c1c1c));\n color: var(--primary-text-color, #e0e0e0);\n font-size: 1em;\n cursor: pointer;\n appearance: auto;\n box-sizing: border-box;\n ",n="display: block; font-weight: 500; margin-bottom: 8px; color: var(--primary-text-color);",i="margin-bottom: 16px;";this._buildPanelSelector(e,t,n,i),this._buildTimeWindow(e,t,n,i),this._buildMetricSelector(e,t,n,i),this._buildTabStyleSelector(e,t,n,i),this._buildSectionCheckboxes(e,n,i),this.appendChild(e),this._populateMetricSelect(),this._config.device_id&&this._discoverAvailableRoles(this._config.device_id)}_buildPanelSelector(e,t,n,s){const o=document.createElement("div");o.style.cssText=s;const r=document.createElement("label");r.textContent=i("editor.panel_label"),r.style.cssText=n;const a=document.createElement("select");a.style.cssText=t;const l=document.createElement("option");if(l.value="",l.textContent=i("editor.select_panel"),a.appendChild(l),this._panels)for(const e of this._panels){const t=document.createElement("option");t.value=e.device_id,t.textContent=e.label,e.device_id===this._config.device_id&&(t.selected=!0),a.appendChild(t)}a.addEventListener("change",()=>{this._config={...this._config,device_id:a.value},this._fireConfigChanged(),this._discoverAvailableRoles(a.value)}),o.appendChild(r),o.appendChild(a),e.appendChild(o),this._panelSelect=a}_buildTimeWindow(e,t,n,s){const o=document.createElement("div");o.style.cssText=s;const r=document.createElement("label");r.textContent=i("editor.chart_window"),r.style.cssText=n;const a=document.createElement("div");a.style.cssText="display: flex; gap: 12px; align-items: center; flex-wrap: wrap;";const l=t+"width: 70px; cursor: text;",c=(e,t,n,i)=>{const s=document.createElement("div");s.style.cssText="display: flex; align-items: center; gap: 6px;";const o=document.createElement("input");o.type="number",o.min=t,o.max=n,o.value=String(e),o.style.cssText=l;const r=document.createElement("span");return r.textContent=i,r.style.cssText="font-size: 0.9em; color: var(--secondary-text-color);",s.appendChild(o),s.appendChild(r),{wrap:s,input:o}},d=parseInt(String(this._config.history_days))||0,h=parseInt(String(this._config.history_hours))||0,p=parseInt(String(this._config.history_minutes))||0,u=c(d,"0","30",i("editor.days")),g=c(h,"0","23",i("editor.hours")),_=c(p,"0","59",i("editor.minutes")),f=()=>{this._config={...this._config,history_days:parseInt(u.input.value)||0,history_hours:parseInt(g.input.value)||0,history_minutes:parseInt(_.input.value)||0},this._fireConfigChanged()};u.input.addEventListener("change",f),g.input.addEventListener("change",f),_.input.addEventListener("change",f),a.appendChild(u.wrap),a.appendChild(g.wrap),a.appendChild(_.wrap),o.appendChild(r),o.appendChild(a),e.appendChild(o),this._daysInput=u.input,this._hoursInput=g.input,this._minsInput=_.input}_buildMetricSelector(e,t,n,s){const o=document.createElement("div");o.style.cssText=s;const r=document.createElement("label");r.textContent=i("editor.chart_metric"),r.style.cssText=n;const a=document.createElement("select");a.style.cssText=t,a.addEventListener("change",()=>{this._config={...this._config,chart_metric:a.value},this._fireConfigChanged()}),o.appendChild(r),o.appendChild(a),e.appendChild(o),this._metricSelect=a}_buildTabStyleSelector(e,t,n,s){const o=document.createElement("div");o.style.cssText=s;const r=document.createElement("label");r.textContent=i("editor.tab_style"),r.style.cssText=n;const a=document.createElement("select");a.style.cssText=t;const l=[{value:"text",text:i("editor.tab_style_text")},{value:"icon",text:i("editor.tab_style_icon")}];for(const e of l){const t=document.createElement("option");t.value=e.value,t.textContent=e.text,e.value===(this._config.tab_style??"text")&&(t.selected=!0),a.appendChild(t)}a.addEventListener("change",()=>{this._config={...this._config,tab_style:a.value},this._fireConfigChanged()}),o.appendChild(r),o.appendChild(a),e.appendChild(o),this._tabStyleSelect=a}_buildSectionCheckboxes(e,t,n){const s=document.createElement("div");s.style.cssText=n;const o=document.createElement("label");o.textContent=i("editor.visible_sections"),o.style.cssText=t,s.appendChild(o);const r=[{key:"show_panel",label:i("editor.panel_circuits"),subDeviceType:null},{key:"show_battery",label:i("editor.battery_bess"),subDeviceType:"bess"},{key:"show_evse",label:i("editor.ev_charger_evse"),subDeviceType:"evse"}];this._checkboxes={},this._entityContainers={};for(const e of r){const t=document.createElement("div");t.style.cssText="display: flex; align-items: center; gap: 8px; margin-bottom: 6px; cursor: pointer;";const n=document.createElement("input");n.type="checkbox",n.checked=!1!==this._config[e.key],n.style.cssText="width: 18px; height: 18px; cursor: pointer; accent-color: var(--primary-color);";const i=document.createElement("span");i.textContent=e.label,i.style.cssText="font-size: 0.9em; color: var(--primary-text-color); cursor: pointer;",t.appendChild(n),t.appendChild(i),s.appendChild(t),this._checkboxes[e.key]=n;let o=null;e.subDeviceType&&(o=document.createElement("div"),o.style.cssText="padding-left: 26px;",o.style.display=n.checked?"block":"none",s.appendChild(o),this._entityContainers[e.subDeviceType]=o),n.addEventListener("change",()=>{this._config={...this._config,[e.key]:n.checked},o&&(o.style.display=n.checked?"block":"none"),this._fireConfigChanged()})}e.appendChild(s)}_isChartEntity(e,t,n){const i=(t.original_name??"").toLowerCase(),s=t.unique_id??"";if("power"===i||"battery power"===i||s.endsWith("_power"))return!0;if("bess"===n){if("battery level"===i||"battery percentage"===i||s.endsWith("_battery_level")||s.endsWith("_battery_percentage"))return!0;if("state of energy"===i||s.endsWith("_soe_kwh"))return!0;if("nameplate capacity"===i||s.endsWith("_nameplate_capacity"))return!0}return!1}_populateEntityCheckboxes(e){const t=this._config.visible_sub_entities??{};for(const[,n]of Object.entries(e)){const e=n.type?this._entityContainers[n.type]:void 0;if(e&&(e.innerHTML="",n.entities))for(const[i,s]of Object.entries(n.entities)){if("sensor"===s.domain&&this._isChartEntity(i,s,n.type??""))continue;const o=document.createElement("div");o.style.cssText="display: flex; align-items: center; gap: 8px; margin-bottom: 5px; cursor: pointer;";const r=document.createElement("input");r.type="checkbox",r.checked=!0===t[i],r.style.cssText="width: 16px; height: 16px; cursor: pointer; accent-color: var(--primary-color);";const a=document.createElement("span");let l=s.original_name??i;const c=n.name??"";l.startsWith(c+" ")&&(l=l.slice(c.length+1)),a.textContent=l,a.style.cssText="font-size: 0.85em; color: var(--primary-text-color); cursor: pointer;",o.appendChild(r),o.appendChild(a),e.appendChild(o),r.addEventListener("change",()=>{const e={...this._config.visible_sub_entities??{}};r.checked?e[i]=!0:delete e[i],this._config={...this._config,visible_sub_entities:e},this._fireConfigChanged()})}}}async _discoverAvailableRoles(e){if(this._hass&&e)try{const t=await this._hass.callWS({type:`${l}/panel_topology`,device_id:e}),n=new Set;for(const e of Object.values(t.circuits??{}))for(const t of Object.keys(e.entities??{}))n.add(t);this._availableRoles=n,this._populateMetricSelect(),t.sub_devices&&this._populateEntityCheckboxes(t.sub_devices)}catch{this._availableRoles=null,this._populateMetricSelect()}}_populateMetricSelect(){const e=this._metricSelect;if(!e)return;const t=this._config.chart_metric??o;e.innerHTML="";for(const[n,i]of Object.entries(_)){if(this._availableRoles&&!this._availableRoles.has(i.entityRole))continue;const s=document.createElement("option");s.value=n,s.textContent=i.label(),n===t&&(s.selected=!0),e.appendChild(s)}}_updateControls(){if(this._panelSelect&&(this._panelSelect.value=this._config.device_id??""),this._daysInput&&(this._daysInput.value=String(parseInt(String(this._config.history_days))||0)),this._hoursInput&&(this._hoursInput.value=String(parseInt(String(this._config.history_hours))||0)),this._minsInput&&(this._minsInput.value=String(parseInt(String(this._config.history_minutes))||0)),this._metricSelect&&(this._metricSelect.value=this._config.chart_metric??o),this._checkboxes)for(const[e,t]of Object.entries(this._checkboxes))t.checked=!1!==this._config[e];this._tabStyleSelect&&(this._tabStyleSelect.value=this._config.tab_style??"text")}_fireConfigChanged(){this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}}try{customElements.get("span-panel-card-editor")||customElements.define("span-panel-card-editor",Zt)}catch{}window.customCards=window.customCards??[],window.customCards.push({type:"span-panel-card",name:"SPAN Panel",description:"Physical panel layout with live power charts matching the SPAN frontend",preview:!0}),console.warn("%c SPAN-PANEL-CARD %c v0.9.4 ","background: var(--primary-color, #4dd9af); color: var(--text-primary-color, #000); font-weight: 700; padding: 2px 6px; border-radius: 4px 0 0 4px;","background: var(--secondary-background-color, #333); color: var(--primary-text-color, #fff); padding: 2px 6px; border-radius: 0 4px 4px 0;");
+
+ `}};hT.styles=k('\n :host {\n --span-accent: var(--primary-color, #4dd9af);\n }\n\n /* Card shell — replaces