###################################################################### # @CCOSTAN - Follow Me on X # For more info visit https://www.vcloudinfo.com/click-here # Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig # ------------------------------------------------------------------- # Infrastructure Templates - custom:button-card # Related Issue: 1560 # Shared `button_card_templates` used across Infrastructure views. # ------------------------------------------------------------------- # Notes: Keep templates generic; view-specific tuning stays in the view partials. ###################################################################### bearstone_infra_base: show_icon: true show_name: true show_state: true tap_action: action: more-info styles: card: - border-radius: 18px - padding: 14px - box-shadow: none - background: var(--ha-card-background, var(--card-background-color)) - border: 1px solid var(--divider-color) - overflow: hidden grid: - grid-template-areas: "\"i n\" \"i s\"" - grid-template-columns: 40px 1fr - grid-template-rows: min-content min-content icon: - width: 22px - color: var(--primary-text-color) name: - font-weight: 700 - font-size: 14px - justify-self: start - padding-bottom: 2px state: - font-size: 12px - opacity: 0.75 - justify-self: start bearstone_infra_chip: template: bearstone_infra_base show_state: true styles: card: - border-radius: 999px - padding: 10px 12px - border: 1px solid var(--divider-color) - background: var(--ha-card-background, var(--card-background-color)) grid: - grid-template-areas: "\"i n\" \"i s\"" - grid-template-columns: 28px 1fr icon: - width: 18px name: - font-weight: 700 - font-size: 12px state: - font-size: 11px - opacity: 0.7 bearstone_infra_chip_running: template: bearstone_infra_chip state: - value: 'on' styles: card: - border-color: rgba(67,160,71,0.45) - background: rgba(232,245,233,0.85) icon: - color: rgba(46,125,50,1) - value: 'off' styles: card: - border-color: rgba(229,57,53,0.35) - background: rgba(255,235,238,0.85) icon: - color: rgba(198,40,40,1) - value: unavailable styles: card: - border-color: rgba(229,57,53,0.35) - background: rgba(255,235,238,0.85) icon: - color: rgba(198,40,40,1) bearstone_infra_tile: template: bearstone_infra_base show_label: true label: '[[[ return variables.label ? variables.label : "" ]]]' styles: grid: - grid-template-areas: "\"i n\" \"i l\"" - grid-template-rows: min-content min-content label: - font-size: 12px - opacity: 0.8 - justify-self: start state: - value: unavailable styles: card: - border-color: rgba(229,57,53,0.35) - background: rgba(255,235,238,0.85) bearstone_infra_reboot: template: bearstone_infra_tile show_state: false icon: mdi:restart label: '[[[ return variables.subtitle ? variables.subtitle : "Hold to reboot" ]]]' hold_action: action: call-service service: button.press service_data: entity_id: '[[[ return variables.button_entity ]]]' confirmation: text: '[[[ return "Reboot " + (variables.name ? variables.name : "device") + "?" ]]]' styles: icon: - color: var(--secondary-text-color) bearstone_infra_device_tile: template: bearstone_infra_tile show_state: true label: '[[[ return variables.subtitle ? variables.subtitle : "" ]]]' hold_action: action: call-service service: button.press service_data: entity_id: '[[[ return variables.button_entity ]]]' confirmation: text: '[[[ return "Restart " + (variables.name ? variables.name : "device") + "?" ]]]' styles: state: - font-weight: 700 bearstone_infra_prune_tile: template: bearstone_infra_tile show_state: true icon: mdi:image-sync label: >- [[[ return variables.subtitle ? variables.subtitle : "Hold to prune unused images"; ]]] hold_action: action: call-service service: button.press service_data: entity_id: '[[[ return variables.prune_button ]]]' confirmation: text: '[[[ return "Prune unused images on " + (variables.name ? variables.name : "host") + "?" ]]]' styles: icon: - color: var(--secondary-text-color) state: - font-weight: 700 bearstone_infra_apt_prune_tile: template: bearstone_infra_prune_tile show_state: true icon: mdi:server label: >- [[[ const lastSensor = variables.last_update_sensor ? variables.last_update_sensor : ''; const lastValue = lastSensor ? (states[lastSensor]?.state ?? 'unknown') : 'unknown'; return "Last update: " + lastValue + " | Hold to prune"; ]]] bearstone_infra_container_row: template: bearstone_infra_list_row show_label: false show_state: false tap_action: action: none hold_action: action: call-service service: button.press service_data: entity_id: > [[[ if (variables && variables.restart_button) return variables.restart_button; const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } if (!key) return ''; const restartCandidates = [ `button.${key}_restart_container`, `button.${key}_restart_container_2`, ]; for (const candidate of restartCandidates) { if (states[candidate]) return candidate; } return restartCandidates[0]; ]]] confirmation: text: > [[[ const friendly = (entity && entity.attributes && entity.attributes.friendly_name) ? String(entity.attributes.friendly_name) : ((entity && entity.entity_id) ? String(entity.entity_id) : 'container'); return "Restart container " + friendly + "?"; ]]] icon: mdi:docker name: > [[[ if (variables && variables.name) return variables.name; const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; const friendly = (entity && entity.attributes && entity.attributes.friendly_name) ? String(entity.attributes.friendly_name) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } if (friendly && friendly !== 'Container') { return friendly.replace(/\s+Container$/, ''); } return key || friendly || ent; ]]] custom_fields: image: > [[[ const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; const telemetryDegraded = states['binary_sensor.docker_container_telemetry_degraded']?.state === 'on'; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } const stateCandidates = key ? [ `binary_sensor.${key}_status`, `binary_sensor.${key}_status_2`, `sensor.${key}_state`, `sensor.${key}_state_2`, `switch.${key}_container`, `switch.${key}_container_2`, ] : []; const isUnknownLike = (v) => !v || ['unknown', 'unavailable', 'none', ''].includes(String(v).toLowerCase()); let resolvedState = String(entity && entity.state !== undefined ? entity.state : '').toLowerCase(); for (const candidate of stateCandidates) { const candidateState = states[candidate]?.state; if (!isUnknownLike(candidateState)) { resolvedState = String(candidateState).toLowerCase(); break; } } if (isUnknownLike(resolvedState)) { for (const candidate of stateCandidates) { const candidateState = states[candidate]?.state; if (candidateState !== undefined) { resolvedState = String(candidateState).toLowerCase(); break; } } } const imageCandidates = variables.image_sensor ? [variables.image_sensor] : (key ? [`sensor.${key}_image`, `sensor.${key}_image_2`] : []); let imageValue; for (const candidate of imageCandidates) { const candidateState = states[candidate]?.state; if (!isUnknownLike(candidateState)) { imageValue = candidateState; break; } } if (imageValue === undefined) { for (const candidate of imageCandidates) { const candidateState = states[candidate]?.state; if (candidateState !== undefined) { imageValue = candidateState; break; } } } if (isUnknownLike(imageValue)) { if (telemetryDegraded && ['unknown', 'unavailable', ''].includes(resolvedState)) { return 'telemetry: delayed'; } return 'image: n/a'; } return imageValue; ]]] status: > [[[ const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } const candidates = key ? [ `binary_sensor.${key}_status`, `binary_sensor.${key}_status_2`, `sensor.${key}_state`, `sensor.${key}_state_2`, `switch.${key}_container`, `switch.${key}_container_2`, ] : []; const isUnknownLike = (v) => !v || ['unknown', 'unavailable', ''].includes(String(v).toLowerCase()); let s = String(entity && entity.state !== undefined ? entity.state : '').toLowerCase(); for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (!isUnknownLike(candidateState)) { s = String(candidateState).toLowerCase(); break; } } if (isUnknownLike(s)) { for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (candidateState !== undefined) { s = String(candidateState).toLowerCase(); break; } } } const telemetryDegraded = states['binary_sensor.docker_container_telemetry_degraded']?.state === 'on'; if (s === 'on' || s === 'running') return 'RUNNING'; if (s === 'off' || s === 'stopped' || s === 'exited' || s === 'dead') return 'STOPPED'; if (s === 'unavailable') return telemetryDegraded ? 'STALE' : 'OFFLINE'; if (s === 'unknown' || s === '') return telemetryDegraded ? 'STALE' : 'UNKNOWN'; return String(s).toUpperCase(); ]]] styles: grid: - grid-template-areas: "\"i n status\" \"i image status\"" - grid-template-columns: 24px 1fr auto - grid-template-rows: min-content min-content - align-items: center - column-gap: 12px name: - min-width: 0 - overflow: hidden - text-overflow: ellipsis - white-space: nowrap icon: - color: > [[[ const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } const candidates = key ? [ `binary_sensor.${key}_status`, `binary_sensor.${key}_status_2`, `sensor.${key}_state`, `sensor.${key}_state_2`, `switch.${key}_container`, `switch.${key}_container_2`, ] : []; const isUnknownLike = (v) => !v || ['unknown', 'unavailable', ''].includes(String(v).toLowerCase()); let s = String(entity && entity.state !== undefined ? entity.state : '').toLowerCase(); for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (!isUnknownLike(candidateState)) { s = String(candidateState).toLowerCase(); break; } } if (isUnknownLike(s)) { for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (candidateState !== undefined) { s = String(candidateState).toLowerCase(); break; } } } if (s === 'on' || s === 'running') return 'rgba(46,125,50,1)'; if (s === 'off' || s === 'stopped' || s === 'exited' || s === 'dead') return 'rgba(198,40,40,1)'; return 'rgba(230,81,0,1)'; ]]] custom_fields: image: - grid-area: image - justify-self: start - align-self: start - font-size: 11px - opacity: 0.72 - line-height: 1.1 - white-space: nowrap - overflow: hidden - text-overflow: ellipsis - max-width: 100% status: - justify-self: end - align-self: center - font-weight: 900 - font-size: 12px - letter-spacing: 0.04em - padding: 4px 10px - border-radius: 999px - background: > [[[ const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } const candidates = key ? [ `binary_sensor.${key}_status`, `binary_sensor.${key}_status_2`, `sensor.${key}_state`, `sensor.${key}_state_2`, `switch.${key}_container`, `switch.${key}_container_2`, ] : []; const isUnknownLike = (v) => !v || ['unknown', 'unavailable', ''].includes(String(v).toLowerCase()); let s = String(entity && entity.state !== undefined ? entity.state : '').toLowerCase(); for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (!isUnknownLike(candidateState)) { s = String(candidateState).toLowerCase(); break; } } if (isUnknownLike(s)) { for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (candidateState !== undefined) { s = String(candidateState).toLowerCase(); break; } } } if (s === 'on' || s === 'running') return 'rgba(46,125,50,0.12)'; if (s === 'off' || s === 'stopped' || s === 'exited' || s === 'dead') return 'rgba(198,40,40,0.10)'; return 'rgba(230,81,0,0.12)'; ]]] - color: > [[[ const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } const candidates = key ? [ `binary_sensor.${key}_status`, `binary_sensor.${key}_status_2`, `sensor.${key}_state`, `sensor.${key}_state_2`, `switch.${key}_container`, `switch.${key}_container_2`, ] : []; const isUnknownLike = (v) => !v || ['unknown', 'unavailable', ''].includes(String(v).toLowerCase()); let s = String(entity && entity.state !== undefined ? entity.state : '').toLowerCase(); for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (!isUnknownLike(candidateState)) { s = String(candidateState).toLowerCase(); break; } } if (isUnknownLike(s)) { for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (candidateState !== undefined) { s = String(candidateState).toLowerCase(); break; } } } if (s === 'on' || s === 'running') return 'rgba(46,125,50,1)'; if (s === 'off' || s === 'stopped' || s === 'exited' || s === 'dead') return 'rgba(198,40,40,1)'; return 'rgba(230,81,0,1)'; ]]] card: - border-color: > [[[ const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } const candidates = key ? [ `binary_sensor.${key}_status`, `binary_sensor.${key}_status_2`, `sensor.${key}_state`, `sensor.${key}_state_2`, `switch.${key}_container`, `switch.${key}_container_2`, ] : []; const isUnknownLike = (v) => !v || ['unknown', 'unavailable', ''].includes(String(v).toLowerCase()); let s = String(entity && entity.state !== undefined ? entity.state : '').toLowerCase(); for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (!isUnknownLike(candidateState)) { s = String(candidateState).toLowerCase(); break; } } if (isUnknownLike(s)) { for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (candidateState !== undefined) { s = String(candidateState).toLowerCase(); break; } } } if (s === 'on' || s === 'running') return 'rgba(67,160,71,0.45)'; if (s === 'off' || s === 'stopped' || s === 'exited' || s === 'dead') return 'rgba(229,57,53,0.35)'; return 'rgba(245,124,0,0.35)'; ]]] - background: > [[[ const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } const candidates = key ? [ `binary_sensor.${key}_status`, `binary_sensor.${key}_status_2`, `sensor.${key}_state`, `sensor.${key}_state_2`, `switch.${key}_container`, `switch.${key}_container_2`, ] : []; const isUnknownLike = (v) => !v || ['unknown', 'unavailable', ''].includes(String(v).toLowerCase()); let s = String(entity && entity.state !== undefined ? entity.state : '').toLowerCase(); for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (!isUnknownLike(candidateState)) { s = String(candidateState).toLowerCase(); break; } } if (isUnknownLike(s)) { for (const candidate of candidates) { const candidateState = states[candidate]?.state; if (candidateState !== undefined) { s = String(candidateState).toLowerCase(); break; } } } if (s === 'on' || s === 'running') return 'rgba(232,245,233,0.85)'; if (s === 'off' || s === 'stopped' || s === 'exited' || s === 'dead') return 'rgba(255,235,238,0.85)'; return 'rgba(255,243,224,0.85)'; ]]] - display: > [[[ const ent = (entity && entity.entity_id) ? String(entity.entity_id) : ''; let key = ''; if (ent.startsWith('binary_sensor.') && ent.endsWith('_status')) { key = ent.replace('binary_sensor.', '').replace(/_status$/, ''); } else if (ent.startsWith('binary_sensor.') && ent.endsWith('_status_2')) { key = ent.replace('binary_sensor.', '').replace(/_status_2$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container')) { key = ent.replace('switch.', '').replace(/_container$/, ''); } else if (ent.startsWith('switch.') && ent.endsWith('_container_2')) { key = ent.replace('switch.', '').replace(/_container_2$/, ''); } const switchEntity = key ? `switch.${key}_container` : ''; const switchEntityAlt = key ? `switch.${key}_container_2` : ''; const monitored = states['sensor.docker_monitored_switch_inventory']?.attributes?.entity_id; const restartCandidates = key ? [ `button.${key}_restart_container`, `button.${key}_restart_container_2`, ] : []; const hasRestart = restartCandidates.some((candidate) => states[candidate]); const isMonitored = Array.isArray(monitored) ? monitored.includes(switchEntity) || monitored.includes(switchEntityAlt) : (ent.startsWith('switch.') && (ent.endsWith('_container') || ent.endsWith('_container_2'))); return (hasRestart && isMonitored) ? 'block' : 'none'; ]]] bearstone_infra_panel_header: show_icon: false show_state: false show_label: false tap_action: action: none styles: card: - background: transparent - border: none - box-shadow: none - padding: 6px 2px 10px 2px name: - font-size: 18px - font-weight: 800 - letter-spacing: 0.04em - text-transform: uppercase - justify-self: start bearstone_infra_list_row: show_icon: true show_name: true show_state: true show_label: false tap_action: action: more-info styles: card: - border-radius: 14px - padding: 12px 12px - box-shadow: none - border: 1px solid rgba(0,0,0,0.03) - background: rgba(0,0,0,0.02) - width: 100% - box-sizing: border-box grid: - grid-template-areas: "\"i n s\"" - grid-template-columns: 24px 1fr auto - align-items: center - column-gap: 10px icon: - width: 18px - color: var(--primary-color) name: - font-weight: 700 - font-size: 14px - justify-self: start - opacity: 0.95 - min-width: 0 - overflow: hidden - text-overflow: ellipsis - white-space: nowrap state: - justify-self: end - font-weight: 700 - font-size: 13px - opacity: 0.8 - padding-left: 8px - white-space: nowrap bearstone_infra_alert_row: template: bearstone_infra_list_row # Home view only. Uses JS visibility checks to keep Home "exceptions-only". styles: card: - border-color: rgba(229,57,53,0.25) - background: rgba(255,235,238,0.65) - display: > [[[ const kind = (variables && variables.alert_kind) ? String(variables.alert_kind) : ''; const minAge = (variables && variables.min_age_s !== undefined) ? Number(variables.min_age_s) : 0; const thr = (variables && variables.threshold !== undefined) ? Number(variables.threshold) : null; const stateStr = String(entity && entity.state !== undefined ? entity.state : ''); const lastChanged = entity && entity.last_changed ? new Date(entity.last_changed) : null; // If we can't determine age, do not surface time-gated alerts. const ageS = lastChanged ? ((Date.now() - lastChanged.getTime()) / 1000) : 0; const num = (entId) => { const v = parseFloat(states[entId] ? states[entId].state : ''); return Number.isFinite(v) ? v : null; }; let show = false; if (kind === 'binary_on') show = (stateStr === 'on'); else if (kind === 'binary_off') show = (stateStr === 'off'); else if (kind === 'ap_zero') show = (stateStr === '0' && ageS >= minAge); else if (kind === 'disk_high') { const v = parseFloat(stateStr); show = Number.isFinite(v) && (thr !== null ? (v > thr) : (v > 80)); } else if (kind === 'speedtest_slow') { const dl = num('sensor.speedtest_download'); const ul = num('sensor.speedtest_upload'); const t = (thr !== null) ? thr : 300; show = (dl !== null && dl < t) || (ul !== null && ul < t); } return show ? 'block' : 'none'; ]]] bearstone_infra_list_row_running: template: bearstone_infra_list_row state: - value: 'on' styles: card: - border-color: rgba(67,160,71,0.45) - background: rgba(232,245,233,0.85) icon: - color: rgba(46,125,50,1) state: - color: rgba(46,125,50,1) - opacity: 1 - value: 'off' styles: card: - border-color: rgba(229,57,53,0.35) - background: rgba(255,235,238,0.85) icon: - color: rgba(198,40,40,1) state: - color: rgba(198,40,40,1) - opacity: 1 - value: Running styles: icon: - color: rgba(46,125,50,1) state: - color: rgba(46,125,50,1) - opacity: 1 - value: running styles: icon: - color: rgba(46,125,50,1) state: - color: rgba(46,125,50,1) - opacity: 1 - value: Stopped styles: icon: - color: rgba(198,40,40,1) state: - color: rgba(198,40,40,1) - opacity: 1 - value: stopped styles: icon: - color: rgba(198,40,40,1) state: - color: rgba(198,40,40,1) - opacity: 1 - value: unavailable styles: icon: - color: rgba(198,40,40,1) state: - color: rgba(198,40,40,1) - opacity: 1 bearstone_infra_kpi: show_icon: true show_name: true show_state: true show_label: false tap_action: action: more-info styles: card: - border-radius: 14px - padding: 12px - box-shadow: none - border: 1px solid rgba(0,0,0,0.03) - background: rgba(0,0,0,0.02) grid: - grid-template-areas: "\"i\" \"n\" \"s\"" - grid-template-rows: 22px min-content min-content - row-gap: 6px - justify-items: center icon: - width: 18px - color: var(--primary-color) name: - font-size: 11px - font-weight: 800 - opacity: 0.65 - text-transform: uppercase - text-align: center - letter-spacing: 0.6px state: - font-size: 16px - font-weight: 800 - opacity: 0.9