const LUMA_CURTAIN_VERSION = '0.1.0'; class LumaCurtainCard extends HTMLElement { set hass(hass) { this._hass = hass; this._render(); } setConfig(config) { if (!config.entity) throw new Error('Entity is required'); this._config = { entity: config.entity, name: config.name || '', size: config.size || '1x1', accent_color: config.accent_color || '', icon: config.icon || '', tap_action: config.tap_action || { action: 'more-info' }, hold_action: config.hold_action || { action: 'more-info' }, ...config }; this._render(); } getCardSize() { return 2; } static getStubConfig() { return { entity: '', name: '', size: '1x1' }; } connectedCallback() { if (!this.shadowRoot) this.attachShadow({ mode: 'open' }); this._render(); } _getState() { return this._hass?.states?.[this._config?.entity]; } _getPosition() { const s = this._getState(); return parseFloat(s?.attributes?.current_position) || 0; } _isOpen() { return this._getPosition() > 5; } _handleClick() { if (!this._hass || !this._config) return; const ev = new Event('hass-more-info', { composed: true }); ev.detail = { entityId: this._config.entity }; this.dispatchEvent(ev); } _render() { if (!this.shadowRoot || !this._config) return; const pos = this._getPosition(); const isOpen = this._isOpen(); const name = this._config.name || this._getState()?.attributes?.friendly_name || ''; const icon = this._config.icon || 'mdi:curtains'; const accent = isOpen ? '#dcd2b4' : 'rgba(187,187,187,0.5)'; const label = pos > 0 ? `${Math.round(pos)}%` : 'Closed'; const closedPct = 1 - Math.min(pos / 100, 1); const closedOverlay = closedPct > 0.05 ? `rgba(12,16,36,${(0.5 * closedPct).toFixed(2)})` : 'transparent'; this.shadowRoot.innerHTML = `