const LUMA_MEDIA_VERSION = '0.1.0'; class LumaMediaCard 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 || '1x2', 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 4; } static getStubConfig() { return { entity: '', name: '', size: '1x2' }; } connectedCallback() { if (!this.shadowRoot) this.attachShadow({ mode: 'open' }); this._render(); } _getState() { return this._hass?.states?.[this._config?.entity]; } _isActive() { const s = this._getState(); return s && (s.state === 'playing' || s.state === 'paused'); } _getAccent() { if (this._config?.accent_color) return this._config.accent_color; const s = this._getState(); if (!s) return '#bbbbbb'; switch (s.state) { case 'playing': return '#9b7ddb'; case 'paused': return 'rgba(125,155,219,0.7)'; default: return 'rgba(187,187,187,0.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 s = this._getState(); const isActive = this._isActive(); const accent = this._getAccent(); const icon = this._config.icon || 'mdi:music'; const title = s?.attributes?.media_title || this._config.name || s?.attributes?.friendly_name || ''; const artist = s?.attributes?.media_artist || ''; const volume = Math.round((s?.attributes?.volume_level || 0) * 100); const state = s?.state || 'off'; const statusLabel = { playing: 'Playing', paused: 'Paused', idle: 'Idle' }[state] || 'Off'; const volLabel = isActive ? `Vol ${volume}%` : 'Off'; this.shadowRoot.innerHTML = `