Take your Home Assistant dashboard to the next level with dynamic, customizable animated cards that bring your smart home dashboard to life.
See the codeCreated by: @Anasbox
Take your Home Assistant dashboard to the next level with dynamic, customizable animated cards that bring your smart home dashboard to life.
| 📂 Category | 📝 Description | 🔗 Link |
|---|---|---|
| 🏠Home | main collection | You are here |
| 🧺 Appliances | washer, dryer, dishwasher, etc | View |
| 🧺 Appliances v2 | washer, dryer, dishwasher, etc | View |
| 🔋 Battery | Battery level, charging animations | View |
| 📈 Graph Cards | Temp, humidity, etc | View |
| 📟 Badge/Button | Make custom Badge/Button | View |
| 🌡️Climate | Climate & Weather | View |
| 🗂️Batch 6 | Batch 6 Cards | View |
Those YouTube Videos Batch 1 | Batch 2 | Batch 3 | Batch 4 | Batch 5 explains how to do it.
[!NOTE] If you are using the Sections view type, you may need to set
rowsto around1.5for the card, otherwise the card may appear compressed. (USE THIS ONLY IF YOU HAVE ISSUES).grid_options: rows: 1.5
[!TIP] Want to change card and text color (useful for light-mode folks)? Add the following to
ha-cardand play with the values (rgb, hex, etc).
background: #1C1C1C !important;
--card-primary-color: white !important;
--card-secondary-color: white !important;
Loading images... please wait
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:power-plug
icon_color: green
name: Smart Plug
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{# Evaluate numeric rule #}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{# State mode #}
{% if states(state_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: ring-breathe 1.8s ease-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
}
@keyframes ring-breathe {
0% { box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9); }
70% { box-shadow: 0 0 0 14px rgba(var(--rgb-{{ config.icon_color }}), 0.0); }
100% { box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:power-socket-au
icon_color: green
name: Charger
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
{# adjust speed based on this plug's own power attribute #}
{% set p = state_attr(config.entity, 'current_power_w') | float(0) %}
{% set dur = 1.6 - (p / 800) %}
--shape-animation: ultra-plug-on {{ [0.4, dur] | max | round(2) }}s ease-in-out infinite;
--plug-glow-animation: ultra-plug-glow 1.8s ease-in-out infinite;
--plug-arcs-animation: ultra-plug-arcs 1.2s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--plug-glow-animation: none;
--plug-arcs-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -4px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--plug-glow-animation);
}
.shape::after {
animation: var(--plug-arcs-animation);
}
@keyframes ultra-plug-on {
0% { transform: scale(1); }
25% { transform: scale(1.05) translateY(-1px); }
50% { transform: scale(1.08) translateY(-2px); }
75% { transform: scale(1.04) translateY(-1px); }
100% { transform: scale(1); }
}
@keyframes ultra-plug-glow {
0% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.3);
}
50% {
box-shadow:
0 0 18px 6px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 32px 12px rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.3);
}
}
@keyframes ultra-plug-arcs {
0% {
box-shadow:
-10px -6px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
12px 4px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
25% {
box-shadow:
-10px -6px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
12px 4px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
50% {
box-shadow:
-6px 2px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.3),
10px -8px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
}
75% {
box-shadow:
-12px 4px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
8px 0 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
100% {
box-shadow:
-10px -6px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
12px 4px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fan
icon_color: blue
name: Fan
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
{# Fan speed logic based on THIS card's entity #}
{% if is_state(config.entity, 'on') %}
--shape-animation: fan-turbine 0.5s linear infinite;
opacity: 1;
{% elif is_state(config.entity, 'medium') %}
--shape-animation: fan-turbine 0.8s linear infinite;
opacity: 1;
{% elif is_state(config.entity, 'low') %}
--shape-animation: fan-turbine 1.2s linear infinite;
opacity: 1;
{% else %}
--shape-animation: fan-rock 2.4s ease-in-out infinite;
opacity: 0.7;
{% endif %}
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
position: relative;
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 0 0 6px rgba(var(--rgb-{{ config.icon_color }}), 0.08),
0 0 18px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.7);
}
@keyframes fan-turbine {
0% {
transform: rotate(0deg) scale(1);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9));
}
25% {
transform: rotate(90deg) scale(1.02);
}
50% {
transform: rotate(180deg) scale(1.04);
filter: drop-shadow(0 0 8px rgba(var(--rgb-{{ config.icon_color }}), 1));
}
75% {
transform: rotate(270deg) scale(1.02);
}
100% {
transform: rotate(360deg) scale(1);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9));
}
}
@keyframes fan-rock {
0% { transform: rotate(-4deg); }
50% { transform: rotate(4deg); }
100% { transform: rotate(-4deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fan
icon_color: cyan
name: Fan
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# -------- TRIGGER DECISION LOGIC -------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set sensor_entity = state_entity %}
{% if states(sensor_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# ------ END TRIGGER DECISION LOGIC ------ #}
{# Fan speed still based on THIS card's entity percentage #}
{% set speed = state_attr(config.entity, 'percentage') | int(0) %}
{% if trigger_active %}
{% if speed == 0 and is_state(config.entity, 'off') %}
--shape-animation: fan-ultra-idle 3s ease-in-out infinite;
{% else %}
{% set dur = 1.2 - (speed / 120) %}
--shape-animation: fan-ultra-spin {{ [0.25, dur] | max | round(2) }}s linear infinite;
{% endif %}
--fan-warp-animation: fan-warp 1.4s ease-in-out infinite;
--fan-stream-animation: fan-stream 1.6s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--fan-warp-animation: none;
--fan-stream-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--fan-warp-animation);
}
.shape::after {
mix-blend-mode: screen;
animation: var(--fan-stream-animation);
}
@keyframes fan-ultra-spin {
0% {
transform: rotate(0deg) scale(1);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.8));
}
20% { transform: rotate(72deg) scale(1.03); }
40% { transform: rotate(144deg) scale(1.05); }
60% { transform: rotate(216deg) scale(1.03); }
80% { transform: rotate(288deg) scale(1.02); }
100% {
transform: rotate(360deg) scale(1);
filter: drop-shadow(0 0 5px rgba(var(--rgb-{{ config.icon_color }}), 1));
}
}
@keyframes fan-ultra-idle {
0% { transform: rotate(-6deg); }
50% { transform: rotate(6deg); }
100% { transform: rotate(-6deg); }
}
@keyframes fan-warp {
0% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.25);
}
40% {
box-shadow:
0 0 0 8px rgba(var(--rgb-{{ config.icon_color }}), 0.4),
0 0 24px 6px rgba(var(--rgb-{{ config.icon_color }}), 0.25);
}
100% {
box-shadow:
0 0 0 18px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 40px 12px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes fan-stream {
0% {
box-shadow:
20px 0 16px -12px rgba(var(--rgb-{{ config.icon_color }}), 0),
-20px 0 16px -12px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
50% {
box-shadow:
24px 0 20px -10px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
-24px 0 20px -10px rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
box-shadow:
20px 0 16px -12px rgba(var(--rgb-{{ config.icon_color }}), 0),
-20px 0 16px -12px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-fan-card
entity: fan.living_room_fan
show_percentage_control: true
show_oscillate_control: true
show_direction_control: true
collapsible_controls: false
fill_container: false
icon_animation: false
icon_type: icon
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========= COLOR CONFIG ========= #}
{# change to 'blue', 'red', 'purple', etc. #}
{% set fan_color = 'green' %}
--fan-color-rgb: var(--rgb-{{ fan_color }});
{# ================================ #}
{# ========== USER CONFIG ========== #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'fan.living_room_fan' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# -------- TRIGGER DECISION LOGIC -------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set sensor_entity = state_entity %}
{% if states(sensor_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# ------ END TRIGGER DECISION LOGIC ------ #}
{# Fan speed still based on THIS card's entity percentage #}
{% set speed = state_attr(config.entity, 'percentage') | int(0) %}
{% if trigger_active %}
{% if speed == 0 and is_state(config.entity, 'off') %}
--shape-animation: fan-ultra-idle 3s ease-in-out infinite;
{% else %}
{% set dur = 1.2 - (speed / 120) %}
--shape-animation: fan-ultra-spin {{ [0.25, dur] | max | round(2) }}s linear infinite;
{% endif %}
--fan-warp-animation: fan-warp 1.4s ease-in-out infinite;
--fan-stream-animation: fan-stream 1.6s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--fan-warp-animation: none;
--fan-stream-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--fan-warp-animation);
}
.shape::after {
mix-blend-mode: screen;
animation: var(--fan-stream-animation);
}
@keyframes fan-ultra-spin {
0% {
transform: rotate(0deg) scale(1);
filter: drop-shadow(0 0 3px rgba(var(--fan-color-rgb), 0.8));
}
20% { transform: rotate(72deg) scale(1.03); }
40% { transform: rotate(144deg) scale(1.05); }
60% { transform: rotate(216deg) scale(1.03); }
80% { transform: rotate(288deg) scale(1.02); }
100% {
transform: rotate(360deg) scale(1);
filter: drop-shadow(0 0 5px rgba(var(--fan-color-rgb), 1));
}
}
@keyframes fan-ultra-idle {
0% { transform: rotate(-6deg); }
50% { transform: rotate(6deg); }
100% { transform: rotate(-6deg); }
}
@keyframes fan-warp {
0% {
box-shadow:
0 0 0 0 rgba(var(--fan-color-rgb), 0.7),
0 0 0 0 rgba(var(--fan-color-rgb), 0.25);
}
40% {
box-shadow:
0 0 0 8px rgba(var(--fan-color-rgb), 0.4),
0 0 24px 6px rgba(var(--fan-color-rgb), 0.25);
}
100% {
box-shadow:
0 0 0 18px rgba(var(--fan-color-rgb), 0.0),
0 0 40px 12px rgba(var(--fan-color-rgb), 0.0);
}
}
@keyframes fan-stream {
0% {
box-shadow:
20px 0 16px -12px rgba(var(--fan-color-rgb), 0),
-20px 0 16px -12px rgba(var(--fan-color-rgb), 0);
}
50% {
box-shadow:
24px 0 20px -10px rgba(var(--fan-color-rgb), 0.6),
-24px 0 20px -10px rgba(var(--fan-color-rgb), 0.4);
}
100% {
box-shadow:
20px 0 16px -12px rgba(var(--fan-color-rgb), 0),
-20px 0 16px -12px rgba(var(--fan-color-rgb), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:lock
icon_color: red
name: Lock
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ---------- TRIGGER DECISION LOGIC ---------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# ---------- END TRIGGER LOGIC ---------- #}
{% if trigger_active %}
{% if is_state(config.entity, 'locked') %}
--shape-animation: lock-secure 2.3s ease-in-out infinite;
{% elif is_state(config.entity, 'unlocking') or is_state(config.entity, 'locking') %}
--shape-animation: lock-action 0.7s ease-in-out infinite;
{% else %}
--shape-animation: lock-open 1.6s ease-in-out infinite;
{% endif %}
opacity: 1;
/* HUGE glow system */
--glow-1: 0 0 25px 8px rgba(var(--rgb-{{ config.icon_color }}), 1);
--glow-2: 0 0 55px 18px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
--glow-3: 0 0 95px 35px rgba(var(--rgb-{{ config.icon_color }}), 0.45);
--glow-anim: lock-ultraglow 2.2s ease-in-out infinite;
{% else %}
--shape-animation: none;
--glow-1: none;
--glow-2: none;
--glow-3: none;
--glow-anim: none;
opacity: 0.6;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
/* Glow layers */
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -8px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
box-shadow: var(--glow-1), var(--glow-2), var(--glow-3);
animation: var(--glow-anim);
}
.shape::after {
inset: -18px;
box-shadow: 0 0 120px 40px rgba(var(--rgb-{{ config.icon_color }}), 0.25);
opacity: 0.9;
animation: var(--glow-anim);
}
@keyframes lock-ultraglow {
0% {
opacity: 0.9;
filter: brightness(1);
}
50% {
opacity: 1;
filter: brightness(1.4);
}
100% {
opacity: 0.9;
filter: brightness(1);
}
}
@keyframes lock-secure {
0% { transform: rotate(0deg) scale(1); }
15% { transform: rotate(-12deg) scale(1.02); }
30% { transform: rotate(2deg) scale(1.03); }
40% { transform: rotate(0deg) scale(1); }
100% { transform: rotate(0deg) scale(1); }
}
@keyframes lock-action {
0% { transform: rotate(-25deg) scale(0.96); }
50% { transform: rotate(25deg) scale(1.04); }
100% { transform: rotate(-25deg) scale(0.96); }
}
@keyframes lock-open {
0% { transform: rotate(10deg); }
50% { transform: rotate(18deg); }
100% { transform: rotate(10deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:projector
icon_color: accent
name: Projector
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: proj-ultra 1.7s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.65;
{% endif %}
transform-origin: 30% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -6px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
background:
radial-gradient(circle at 20% 50%, rgba(255,255,255,0.6), transparent 55%);
transform-origin: 20% 50%;
{% if trigger_active %}
opacity: 0.8;
animation: proj-beam 1.7s ease-in-out infinite;
filter: blur(1px);
{% else %}
opacity: 0; /* hide beam completely */
animation: none;
filter: none;
{% endif %}
}
.shape::after {
{% if trigger_active %}
animation: proj-focus 1.2s ease-in-out infinite;
{% else %}
animation: none;
box-shadow: none; /* kill leftover glow */
{% endif %}
}
@keyframes proj-ultra {
0% { transform: translateX(0) scale(1); }
25% { transform: translateX(1px) scale(1.02); }
50% { transform: translateX(0) scale(1.03); }
75% { transform: translateX(-1px) scale(1.02); }
100% { transform: translateX(0) scale(1); }
}
@keyframes proj-standby {
0% { transform: scale(1); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
@keyframes proj-beam {
0% {
opacity: 0.7;
filter: blur(1px);
transform: scaleX(1) scaleY(1);
}
50% {
opacity: 1;
filter: blur(0.5px);
transform: scaleX(1.15) scaleY(1.05);
}
100% {
opacity: 0.7;
filter: blur(1px);
transform: scaleX(1) scaleY(1);
}
}
@keyframes proj-focus {
0% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
}
50% {
box-shadow:
0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 1);
}
100% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:bell
icon_color: red
name: Doorbell
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{# default: simple equality state trigger #}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: doorbell-ring 0.9s ease-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.8;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes doorbell-ring {
0% {
transform: scale(1.05);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 1),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
30% {
transform: scale(0.95);
box-shadow:
0 0 0 4px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 0 10px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 0 18px rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
60% {
transform: scale(1.02);
box-shadow:
0 0 0 10px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 18px rgba(var(--rgb-{{ config.icon_color }}), 0.2),
0 0 0 26px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes doorbell-idle {
0% { transform: scale(1); }
50% { transform: scale(1.03); }
100% { transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:sprinkler-variant
icon_color: blue
name: Sprinkler
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: irrig-ultra 2s ease-in-out infinite;
--irrig-heads-animation: irrig-heads 1.6s ease-out infinite;
--irrig-fog-animation: irrig-fog 2s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--irrig-heads-animation: none;
--irrig-fog-animation: none;
opacity: 0.75;
{% endif %}
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
border-radius: inherit;
inset: 0;
pointer-events: none;
}
.shape::before {
animation: var(--irrig-heads-animation);
}
.shape::after {
animation: var(--irrig-fog-animation);
}
@keyframes irrig-ultra {
0% { transform: translateY(0) scale(1); }
25% { transform: translateY(-2px) scale(1.02); }
50% { transform: translateY(-4px) scale(1.03); }
75% { transform: translateY(-2px) scale(1.02); }
100% { transform: translateY(0) scale(1); }
}
@keyframes irrig-idle {
0% { transform: translateY(1px); }
50% { transform: translateY(-1px); }
100% { transform: translateY(1px); }
}
@keyframes irrig-heads {
0% {
box-shadow:
-10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
20% {
box-shadow:
-10px 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
40% {
box-shadow:
-10px -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4),
0 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
60% {
box-shadow:
-10px -8px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.1),
0 -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4),
10px 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
}
80% {
box-shadow:
-10px -12px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 -8px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.1),
10px -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
box-shadow:
-10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
@keyframes irrig-fog {
0% {
filter: blur(0);
}
50% {
filter: blur(0.7px);
box-shadow: 0 -14px 18px -8px rgba(var(--rgb-{{ config.icon_color }}), 0.45);
}
100% {
filter: blur(0);
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 20pxx 0px -18px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:sprinkler-variant
icon_color: blue
name: Sprinkler
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: irrig-ultra 2s ease-in-out infinite;
--irrig-heads-animation: irrig-heads 1.6s ease-out infinite;
--irrig-fog-animation: irrig-fog 2s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--irrig-heads-animation: none;
--irrig-fog-animation: none;
opacity: 0.75;
{% endif %}
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
border-radius: inherit;
inset: 0;
pointer-events: none;
}
.shape::before {
animation: var(--irrig-heads-animation);
}
.shape::after {
animation: var(--irrig-fog-animation);
}
@keyframes irrig-ultra {
0% { transform: translateY(0) scale(1); }
25% { transform: translateY(-2px) scale(1.02); }
50% { transform: translateY(-4px) scale(1.03); }
75% { transform: translateY(-2px) scale(1.02); }
100% { transform: translateY(0) scale(1); }
}
@keyframes irrig-idle {
0% { transform: translateY(1px); }
50% { transform: translateY(-1px); }
100% { transform: translateY(1px); }
}
@keyframes irrig-heads {
0% {
box-shadow:
-10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
20% {
box-shadow:
-10px 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
40% {
box-shadow:
-10px -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4),
0 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
60% {
box-shadow:
-10px -8px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.1),
0 -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4),
10px 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
}
80% {
box-shadow:
-10px -12px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 -8px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.1),
10px -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
box-shadow:
-10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
@keyframes irrig-fog {
0% {
filter: blur(0);
}
50% {
filter: blur(0.7px);
box-shadow: 0 -14px 18px -8px rgba(var(--rgb-{{ config.icon_color }}), 0.45);
}
100% {
filter: blur(0);
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -17px 0 10px -17px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-climate-card
entity: climate.heatpump
collapsible_controls: false
show_temperature_control: true
fill_container: false
hvac_modes:
- auto
- heat_cool
- cool
- heat
- dry
- fan_only
- "off"
name: Heater
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========= FLAME COLOR CONFIG ========= #}
{% set flame_color = 'deep-orange' %} {# 'red', 'amber', 'orange', etc. #}
--flame-color-rgb: var(--rgb-{{ flame_color }});
{# ===================================== #}
{# ========== USER CONFIG ========== #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'climate.heatpump' %}
{% set active_value = 'heat' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ----------- TRIGGER LOGIC ----------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# --------- END TRIGGER LOGIC --------- #}
{% if trigger_active %}
# --shape-animation: flame-core 1.4s infinite;
--flame-layer1: flame-layers 1.8s infinite;
--flame-layer2: ember-pulse 2.4s infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--flame-layer1: none;
--flame-layer2: none;
opacity: 0.6;
{% endif %}
position: relative;
transform-origin: 50% 75%;
}
/* Flame layers */
.shape::before,
.shape::after {
content: "";
position: absolute;
inset: -8px;
border-radius: inherit;
pointer-events: none;
filter: blur(3px);
}
.shape::before {
animation: var(--flame-layer1);
}
.shape::after {
animation: var(--flame-layer2);
}
/* Core flame motion: chaotic vertical flicker + heat ripple */
@keyframes flame-core {
0% { transform: translateY(0) scale(1); filter: brightness(1.1) hue-rotate(0deg); }
12% { transform: translateY(-2px) scale(1.05); filter: brightness(1.4) hue-rotate(-10deg); }
25% { transform: translateY(1px) scale(0.98); filter: brightness(0.9) hue-rotate(8deg); }
40% { transform: translateY(-3px) scale(1.07); filter: brightness(1.5) hue-rotate(-18deg); }
55% { transform: translateY(0) scale(1.02); filter: brightness(1.2) hue-rotate(10deg); }
70% { transform: translateY(-1px) scale(1.04); filter: brightness(1.35) hue-rotate(-6deg); }
85% { transform: translateY(2px) scale(0.97); filter: brightness(0.95) hue-rotate(6deg); }
100% { transform: translateY(0) scale(1); filter: brightness(1.1) hue-rotate(0deg); }
}
/* Outer flame shape: shifting blurred glow */
@keyframes flame-layers {
0% {
box-shadow:
0 0 14px 8px rgba(var(--flame-color-rgb), 0.8),
0 -12px 24px -6px rgba(255, 200, 0, 0.4);
}
33% {
box-shadow:
0 0 20px 10px rgba(var(--flame-color-rgb), 1),
0 -16px 30px -8px rgba(255, 160, 0, 0.5);
}
66% {
box-shadow:
0 0 18px 9px rgba(var(--flame-color-rgb), 0.9),
0 -8px 20px -6px rgba(255, 220, 0, 0.35);
}
100% {
box-shadow:
0 0 14px 8px rgba(var(--flame-color-rgb), 0.8),
0 -12px 24px -6px rgba(255, 200, 0, 0.4);
}
}
/* Ember pulse: slow breathing glow */
@keyframes ember-pulse {
0% {
box-shadow:
0 0 30px 10px rgba(var(--flame-color-rgb), 0.25),
0 0 60px 20px rgba(255, 120, 0, 0.15);
}
50% {
box-shadow:
0 0 50px 18px rgba(var(--flame-color-rgb), 0.5),
0 0 90px 35px rgba(255, 150, 0, 0.25);
}
100% {
box-shadow:
0 0 30px 10px rgba(var(--flame-color-rgb), 0.25),
0 0 60px 20px rgba(255, 120, 0, 0.15);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -17px 0 20px -17px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:led-strip-variant
icon_color: blue
name: LED Strip
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: rgb-wave 2.2s linear infinite;
opacity: 1;
{% else %}
--shape-animation: rgb-off 3s ease-in-out infinite;
opacity: 0.5;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes rgb-wave {
0% {
filter: hue-rotate(0deg) brightness(1.1);
box-shadow:
0 0 12px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9);
transform: scale(1);
}
25% {
filter: hue-rotate(90deg) brightness(1.3);
box-shadow:
0 0 16px 6px rgba(var(--rgb-{{ config.icon_color }}), 1);
transform: scale(1.04);
}
50% {
filter: hue-rotate(180deg) brightness(1.15);
box-shadow:
0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.9);
transform: scale(1.02);
}
75% {
filter: hue-rotate(270deg) brightness(1.3);
box-shadow:
0 0 16px 6px rgba(var(--rgb-{{ config.icon_color }}), 1);
transform: scale(1.04);
}
100% {
filter: hue-rotate(360deg) brightness(1.1);
box-shadow:
0 0 12px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9);
transform: scale(1);
}
}
@keyframes rgb-off {
0% { filter: brightness(0.7); }
50% { filter: brightness(0.9); }
100% { filter: brightness(0.7); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:washing-machine
icon_color: blue
name: Washing Machine
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: wash-cycle 1s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.8;
{% endif %}
transform-origin: 50% 55%;
}
@keyframes wash-cycle {
0% { transform: translateY(0) rotate(-8deg) scale(1); box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.5); }
20% { transform: translateY(-3px) rotate(8deg) scale(1.02); box-shadow: 0 0 8px 4px rgba(var(--rgb-{{ config.icon_color }}), 0.3); }
40% { transform: translateY(2px) rotate(-6deg) scale(1.01); }
60% { transform: translateY(-2px) rotate(6deg) scale(1.02); }
80% { transform: translateY(1px) rotate(-4deg) scale(1.01); }
100% { transform: translateY(0) rotate(-8deg) scale(1); box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.2); }
}
@keyframes wash-idle {
0% { transform: rotate(0deg); }
50% { transform: rotate(2deg); }
100% { transform: rotate(0deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -22px 0 10px -22px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:washing-machine
icon_color: blue
name: Washing Machine
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: washer-chaos 1.1s cubic-bezier(0.25, 0.1, 0.25, 1) infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.85;
{% endif %}
transform-origin: 50% 55%;
box-shadow:
inset 0 0 0 2px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 10px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.6);
position: relative;
}
@keyframes washer-chaos {
0% {
transform: rotate(0deg) scale(1);
box-shadow:
inset 0 0 0 2px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.6);
}
15% { transform: rotate(18deg) translate(1px, -1px) scale(1.02); }
30% { transform: rotate(60deg) translate(-2px, 2px) scale(0.98); }
45% { transform: rotate(120deg) translate(3px, -2px) scale(1.03); }
60% { transform: rotate(190deg) translate(-1px, 3px) scale(0.97); }
75% { transform: rotate(260deg) translate(1px, -3px) scale(1.04); }
90% { transform: rotate(330deg) translate(-2px, 1px) scale(1.01); }
100% {
transform: rotate(360deg) translate(0, 0) scale(1);
box-shadow:
inset 0 0 0 2px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 10px 6px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes washer-idle {
0% { transform: rotate(-2deg); }
50% { transform: rotate(2deg); }
100% { transform: rotate(-2deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -22px 0 10px -22px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:dishwasher
icon_color: blue
name: Dishwasher
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: dishwasher-swash 1.5s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.8;
{% endif %}
transform-origin: 50% 55%;
}
@keyframes dishwasher-swash {
0% {
transform: scale(1) rotate(0deg);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.3);
filter: blur(0);
}
25% {
transform: scale(1.03) rotate(10deg);
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 18px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.3);
filter: blur(0.4px);
}
50% {
transform: scale(0.98) rotate(-15deg);
box-shadow:
0 0 14px 6px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 26px 12px rgba(var(--rgb-{{ config.icon_color }}), 0.2);
filter: blur(0.6px);
}
75% {
transform: scale(1.04) rotate(15deg);
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 18px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.3);
filter: blur(0.4px);
}
100% {
transform: scale(1) rotate(0deg);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0);
filter: blur(0);
}
}
@keyframes dishwasher-idle {
0% { transform: scale(1); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fire
icon_color: deep-orange
name: Fireplace
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ----------- TRIGGER LOGIC ----------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# --------- END TRIGGER LOGIC --------- #}
{% if trigger_active %}
--shape-animation: flame-core 1.4s infinite;
--flame-layer1: flame-layers 1.8s infinite;
--flame-layer2: ember-pulse 2.4s infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--flame-layer1: none;
--flame-layer2: none;
opacity: 0.6;
{% endif %}
position: relative;
transform-origin: 50% 75%;
}
/* Flame layers */
.shape::before,
.shape::after {
content: "";
position: absolute;
inset: -8px;
border-radius: inherit;
pointer-events: none;
filter: blur(3px);
}
.shape::before {
animation: var(--flame-layer1);
}
.shape::after {
animation: var(--flame-layer2);
}
/* Core flame motion: chaotic vertical flicker + heat ripple */
@keyframes flame-core {
0% { transform: translateY(0) scale(1); filter: brightness(1.1) hue-rotate(0deg); }
12% { transform: translateY(-2px) scale(1.05); filter: brightness(1.4) hue-rotate(-10deg); }
25% { transform: translateY(1px) scale(0.98); filter: brightness(0.9) hue-rotate(8deg); }
40% { transform: translateY(-3px) scale(1.07); filter: brightness(1.5) hue-rotate(-18deg); }
55% { transform: translateY(0) scale(1.02); filter: brightness(1.2) hue-rotate(10deg); }
70% { transform: translateY(-1px) scale(1.04); filter: brightness(1.35) hue-rotate(-6deg); }
85% { transform: translateY(2px) scale(0.97); filter: brightness(0.95) hue-rotate(6deg); }
100% { transform: translateY(0) scale(1); filter: brightness(1.1) hue-rotate(0deg); }
}
/* Outer flame shape: shifting blurred glow */
@keyframes flame-layers {
0% {
box-shadow:
0 0 14px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 -12px 24px -6px rgba(255, 200, 0, 0.4);
}
33% {
box-shadow:
0 0 20px 10px rgba(var(--rgb-{{ config.icon_color }}), 1),
0 -16px 30px -8px rgba(255, 160, 0, 0.5);
}
66% {
box-shadow:
0 0 18px 9px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 -8px 20px -6px rgba(255, 220, 0, 0.35);
}
100% {
box-shadow:
0 0 14px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 -12px 24px -6px rgba(255, 200, 0, 0.4);
}
}
/* Ember pulse: slow breathing glow */
@keyframes ember-pulse {
0% {
box-shadow:
0 0 30px 10px rgba(var(--rgb-{{ config.icon_color }}), 0.25),
0 0 60px 20px rgba(255, 120, 0, 0.15);
}
50% {
box-shadow:
0 0 50px 18px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 90px 35px rgba(255, 150, 0, 0.25);
}
100% {
box-shadow:
0 0 30px 10px rgba(var(--rgb-{{ config.icon_color }}), 0.25),
0 0 60px 20px rgba(255, 120, 0, 0.15);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 20px -20px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:robot-vacuum
icon_color: blue
name: Vacuum
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: robo-path 3.4s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes robo-path {
0% { transform: translate(0, 0) scale(1); }
10% { transform: translate(6px, -2px) rotate(8deg) scale(0.98); }
20% { transform: translate(10px, 4px) rotate(-6deg) scale(1); }
30% { transform: translate(4px, 8px) rotate(-14deg) scale(1.02); }
40% { transform: translate(-6px, 10px) rotate(4deg) scale(0.98); }
50% { transform: translate(-10px, 2px) rotate(16deg) scale(1.03); }
60% { transform: translate(-6px, -6px) rotate(-8deg) scale(1); }
70% { transform: translate(2px, -10px) rotate(10deg) scale(0.97); }
80% { transform: translate(8px, -6px) rotate(-6deg) scale(1.02); }
90% { transform: translate(4px, -2px) rotate(4deg) scale(1.01); }
100% { transform: translate(0, 0) rotate(0deg) scale(1); }
}
@keyframes robo-dock {
0% { transform: translateY(0); }
50% { transform: translateY(-2px); }
100% { transform: translateY(0); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 20pxx 0px -18px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:printer-3d-nozzle
icon_color: purple
name: 3d Printer
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: printer-sequence 2.3s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.8;
{% endif %}
transform-origin: 50% 80%;
box-shadow:
0 8px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 12px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8);
}
@keyframes printer-sequence {
0% { transform: translate(-5px, 4px) scale(0.96); }
15% { transform: translate(5px, 4px) scale(0.96); }
16% { transform: translate(5px, 2px) scale(0.98); }
30% { transform: translate(-5px, 2px) scale(0.98); }
31% { transform: translate(-5px, 0px) scale(1); }
45% { transform: translate(5px, 0px) scale(1); }
46% { transform: translate(5px, -2px) scale(1.02); }
60% { transform: translate(-5px, -2px) scale(1.02); }
61% { transform: translate(-5px, -4px) scale(1.04); }
80% { transform: translate(5px, -4px) scale(1.04); }
100% { transform: translate(-5px, 4px) scale(0.96); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -22px 0 10px -22px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:motion-sensor
icon_color: red
name: PIR Sensor
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: motion-active 1.4s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes motion-active {
0% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
40% {
transform: scale(1.06);
box-shadow:
0 0 0 6px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 0 12px rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 16px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 24px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes motion-scan {
0% {
transform: rotate(0deg);
box-shadow:
0 -10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
}
50% {
transform: rotate(180deg);
box-shadow:
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.6);
}
100% {
transform: rotate(360deg);
box-shadow:
0 -10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -18px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:alarm
icon_color: pink
name: Alarm
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: siren-alert 0.6s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes siren-alert {
0% {
transform: translate(0, 0) scale(1);
box-shadow: 0 0 10px 4px rgba(var(--rgb-{{ config.icon_color }}), 1);
}
10% { transform: translate(-2px, -1px) rotate(-3deg) scale(1.02); }
20% { transform: translate(3px, 1px) rotate(2deg) scale(1.03); }
30% { transform: translate(-4px, 0) rotate(-4deg) scale(1.04); }
40% { transform: translate(4px, 2px) rotate(3deg) scale(1.05); }
50% { transform: translate(-2px, -2px) rotate(-2deg) scale(1.02); }
60% { transform: translate(2px, 1px) rotate(1deg) scale(1.03); }
70% { transform: translate(-3px, 0) rotate(-3deg) scale(1.04); }
80% { transform: translate(3px, -1px) rotate(2deg) scale(1.03); }
100% {
transform: translate(0, 0) rotate(0deg) scale(1);
box-shadow: 0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
@keyframes siren-armed {
0% { box-shadow: 0 0 4px 1px rgba(var(--rgb-{{ config.icon_color }}), 0.4); }
50% { box-shadow: 0 0 10px 4px rgba(var(--rgb-{{ config.icon_color }}), 0.9); }
100% { box-shadow: 0 0 4px 1px rgba(var(--rgb-{{ config.icon_color }}), 0.4); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
icon: mdi:radiator
icon_color: amber
name: Heater
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{% set power_val = states(number_entity) | float(0) %}
{% set norm = (power_val / 1500) | float %}
{% set norm_c = [0, [norm, 1.3] | min] | max %}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% if number_operator == '>' %}
{% set trigger_active = (power_val > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (power_val < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (power_val == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (power_val >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (power_val <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: heater-waves 1.7s ease-in-out infinite;
--heater-glow-animation: heater-glow 2.1s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--heater-glow-animation: none;
opacity: 0.6;
{% endif %}
--heater-scale: {{ (1 + norm_c * 0.15) | round(3) }};
transform-origin: 50% 60%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -8px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--heater-glow-animation);
}
.shape::after {
inset: -18px;
animation: var(--heater-glow-animation);
opacity: 0.9;
}
@keyframes heater-waves {
0% { transform: translateY(0) scale(1); }
25% { transform: translateY(-1px) scale(var(--heater-scale)); }
50% { transform: translateY(-2px) scale(1.02); }
75% { transform: translateY(-1px) scale(var(--heater-scale)); }
100% { transform: translateY(0) scale(1); }
}
@keyframes heater-glow {
0% {
box-shadow:
0 -10px 18px -6px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 -20px 40px -10px rgba(255, 120, 0, 0.35);
}
50% {
box-shadow:
0 -14px 26px -4px rgba(var(--rgb-{{ config.icon_color }}), 1),
0 -26px 60px -10px rgba(255, 90, 0, 0.55);
}
100% {
box-shadow:
0 -10px 18px -6px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 -20px 40px -10px rgba(255, 120, 0, 0.35);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -15px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:led-on
icon_color: blue
name: RGB
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% if states(state_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: rainbow 3s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
}
@keyframes rainbow {
0% { filter: hue-rotate(0deg) brightness(1.1); }
50% { filter: hue-rotate(180deg) brightness(1.3); }
100% { filter: hue-rotate(360deg) brightness(1.1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:kettle-steam
icon_color: brown
name: Kettle
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: tv-glitch 1.2s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.6;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes tv-glitch {
0% { transform: scale(1) translate(0, 0); filter: brightness(1.05); box-shadow: 0 0 8px 2px rgba(var(--rgb-{{ config.icon_color }}), 0.7); }
10% { transform: scaleX(1.02) translate(-1px, 0); }
20% { transform: scaleX(0.98) translate(1px, -1px); filter: brightness(1.3); }
25% { transform: scale(1.01) translate(0, 1px); }
40% { transform: scale(1) translate(0, 0); filter: brightness(1.1); }
55% { transform: scaleX(1.03) translate(0, -1px); }
70% { transform: scale(1) translate(0, 0); box-shadow: 0 0 14px 5px rgba(var(--rgb-{{ config.icon_color }}), 0.9); }
100% { transform: scale(1) translate(0, 0); filter: brightness(1.05); box-shadow: 0 0 8px 2px rgba(var(--rgb-{{ config.icon_color }}), 0.7); }
}
@keyframes tv-standby {
0% { box-shadow: 0 0 2px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.3); }
50% { box-shadow: 0 0 6px 2px rgba(var(--rgb-{{ config.icon_color }}), 0.6); }
100% { box-shadow: 0 0 2px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.3); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -15px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-media-player-card
entity: media_player.android_tv
volume_controls:
- volume_mute
- volume_set
- volume_buttons
media_controls:
- on_off
- shuffle
- previous
- play_pause_stop
- next
- repeat
show_volume_level: true
use_media_info: false
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ======= COLOR CONFIG ======= #}
{% set icon_on_color = 'red' %}
{% set circle_on_rgb = '255, 30, 30' %} {# dark red #}
{% set circle_on_opacity = 0.1 %}
{% set icon_off_color = 'grey' %}
{% set circle_off_rgb = '80, 80, 80' %} {# dark grey #}
{% set circle_off_opacity = 0.25 %}
{# ============================ #}
{% set s = states('media_player.android_tv') %}
{% if s != 'off' %}
{% set trigger = true %}
{% else %}
{% set trigger = false %}
{% endif %}
{% if trigger %}
/* icon color */
--icon-color: rgb(var(--rgb-{{ icon_on_color }}));
--icon-color-rgb: var(--rgb-{{ icon_on_color }});
/* circle color */
--shape-color: rgba({{ circle_on_rgb }}, {{ circle_on_opacity }});
--shape-color-rgb: {{ circle_on_rgb }};
--shape-animation: tv-rgb 1.4s linear infinite;
--glow-enabled: 1;
opacity: 1;
{% else %}
/* icon color */
--icon-color: rgb(var(--rgb-{{ icon_off_color }}));
--icon-color-rgb: var(--rgb-{{ icon_off_color }});
/* circle color */
--shape-color: rgba({{ circle_off_rgb }}, {{ circle_off_opacity }});
--shape-color-rgb: {{ circle_off_rgb }};
--shape-animation: none;
--glow-enabled: 0;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
/* Remove glow when off */
.shape[style*="--glow-enabled: 0"] {
filter: none !important;
box-shadow: none !important;
}
.shape[style*="--glow-enabled: 0"]::before,
.shape[style*="--glow-enabled: 0"]::after {
animation: none !important;
filter: none !important;
box-shadow: none !important;
}
@keyframes tv-rgb {
0% {
transform: scale(1); /* no movement */
filter: brightness(1.0);
box-shadow:
0 0 6px 2px rgba(var(--icon-color-rgb), 0.4),
-4px 0 8px -4px rgba(255, 0, 0, 0.4),
4px 0 8px -4px rgba(0, 128, 255, 0.4);
}
40% {
transform: scale(1); /* still */
filter: brightness(1.25);
box-shadow:
0 0 16px 6px rgba(var(--icon-color-rgb), 0.9),
-6px 0 12px -4px rgba(255, 0, 0, 0.7),
6px 0 12px -4px rgba(0, 128, 255, 0.7);
}
100% {
transform: scale(1); /* still */
filter: brightness(1.0);
box-shadow:
0 0 6px 2px rgba(var(--icon-color-rgb), 0.4),
-4px 0 8px -4px rgba(255, 0, 0, 0.4),
4px 0 8px -4px rgba(0, 128, 255, 0.4);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0px 0px -15px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius,12px));
}
type: custom:mushroom-media-player-card
entity: media_player.living_room_speaker
volume_controls:
- volume_mute
- volume_set
- volume_buttons
media_controls:
- on_off
- shuffle
- previous
- play_pause_stop
- next
- repeat
show_volume_level: true
use_media_info: false
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ====== COLOR CONFIG ====== #}
{% set icon_on_color = 'red' %}
{% set circle_on_rgb = '255, 30, 30' %}
{% set circle_on_opacity = 0.1 %}
{% set icon_off_color = 'grey' %}
{% set circle_off_rgb = '80, 80, 80' %}
{% set circle_off_opacity = 0.25 %}
{# ========================== #}
{# ========== USER CONFIG ========== #}
{# STATE ENTITY #}
{% set state_entity = 'media_player.living_room_speaker' %}
{% set off_value = 'off' %}
{% set play_value = 'playing' %}
{% set idle_value = 'idle' %}
{# ========== END CONFIG ========== #}
{% set st = states(state_entity) %}
{# LIGHT ACTIVE = any state except off #}
{% set light_active = (st != off_value) %}
{# ANIMATION TRIGGER: default = only when playing #}
{# animation ONLY when playing #}
{% set trigger_active = (st == play_value) %}
{% set vol = state_attr(config.entity, 'volume_level') | float(0) %}
{% if light_active %}
{# ---- COLORS WHEN NOT OFF ---- #}
--icon-color: rgb(var(--rgb-{{ icon_on_color }}));
--icon-color-rgb: var(--rgb-{{ icon_on_color }});
--shape-color: rgba({{ circle_on_rgb }}, {{ circle_on_opacity }});
--shape-color-rgb: {{ circle_on_rgb }};
opacity: 1;
{# ---- ANIMATION ONLY WHEN trigger_active ---- #}
{% if trigger_active %}
--shape-animation: ultra-speaker-main 0.9s ease-in-out infinite;
--speaker-bars-animation: ultra-speaker-bars 0.55s linear infinite;
--speaker-bass-animation: ultra-speaker-bass 1s ease-out infinite;
{% else %}
--shape-animation: none;
--speaker-bars-animation: none;
--speaker-bass-animation: none;
--no-glow: 0 0 0 0 rgba(0,0,0,0);
{% endif %}
{% else %}
{# ---- OFF: DIM + NO ANIMATION ---- #}
--icon-color: rgb(var(--rgb-{{ icon_off_color }}));
--icon-color-rgb: var(--rgb-{{ icon_off_color }});
--shape-color: rgba({{ circle_off_rgb }}, {{ circle_off_opacity }});
--shape-color-rgb: {{ circle_off_rgb }};
--shape-animation: none;
--speaker-bars-animation: none;
--speaker-bass-animation: none;
--no-glow: 0 0 0 0 rgba(0,0,0,0);
opacity: 0.6;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--speaker-bars-animation);
box-shadow: var(--no-glow, none);
}
.shape::after {
animation: var(--speaker-bass-animation);
box-shadow: var(--no-glow, none);
}
@keyframes ultra-speaker-main {
0% { transform: scale(1); }
50% { transform: scale(1.06); }
100% { transform: scale(1); }
}
@keyframes ultra-speaker-bars {
0% {
box-shadow:
-10px 6px 0 -5px rgba(var(--icon-color-rgb), 0.4),
0 2px 0 -5px rgba(var(--icon-color-rgb), 0.6),
10px -4px 0 -5px rgba(var(--icon-color-rgb), 0.3);
}
33% {
box-shadow:
-10px -2px 0 -5px rgba(var(--icon-color-rgb), 0.7),
0 8px 0 -5px rgba(var(--icon-color-rgb), 0.3),
10px -8px 0 -5px rgba(var(--icon-color-rgb), 0.6);
}
66% {
box-shadow:
-10px -8px 0 -5px rgba(var(--icon-color-rgb), 0.3),
0 -4px 0 -5px rgba(var(--icon-color-rgb), 0.7),
10px 6px 0 -5px rgba(var(--icon-color-rgb), 0.5);
}
100% {
box-shadow:
-10px 6px 0 -5px rgba(var(--icon-color-rgb), 0.4),
0 2px 0 -5px rgba(var(--icon-color-rgb), 0.6),
10px -4px 0 -5px rgba(var(--icon-color-rgb), 0.3);
}
}
@keyframes ultra-speaker-bass {
0% {
{% set s0 = 1 + (vol * 0.09) %}
transform: scale({{ s0 | round(2) }});
box-shadow:
0 0 0 0 rgba(var(--icon-color-rgb), 0.9),
0 0 0 0 rgba(var(--icon-color-rgb), 0.5);
}
40% {
{% set s1 = 1.08 + vol * 0.1 %}
transform: scale({{ s1 | round(2) }});
box-shadow:
0 0 0 8px rgba(var(--icon-color-rgb), 0.6),
0 0 0 14px rgba(var(--icon-color-rgb), 0.3);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 20px rgba(var(--icon-color-rgb), 0),
0 0 0 30px rgba(var(--icon-color-rgb), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0px 0px -18px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:router-wireless
icon_color: blue
name: Router
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: wifi-waves 1.7s ease-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.6;
{% endif %}
position: relative;
}
@keyframes wifi-waves {
0% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
30% {
box-shadow:
0 0 0 4px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 0 0 10px rgba(var(--rgb-{{ config.icon_color }}), 0.35),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
60% {
box-shadow:
0 0 0 8px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 18px rgba(var(--rgb-{{ config.icon_color }}), 0.25),
0 0 0 28px rgba(var(--rgb-{{ config.icon_color }}), 0.1);
}
100% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-media-player-card
entity: media_player.android_tv
volume_controls:
- volume_mute
- volume_set
- volume_buttons
media_controls:
- on_off
- shuffle
- previous
- play_pause_stop
- next
- repeat
show_volume_level: true
use_media_info: false
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ======= COLOR CONFIG ======= #}
{% set icon_on_color = 'red' %}
{% set circle_on_rgb = '255, 30, 30' %} {# dark red-ish #}
{% set circle_on_opacity = 0.15 %}
{% set icon_off_color = 'grey' %}
{% set circle_off_rgb = '80, 80, 80' %} {# dark grey #}
{% set circle_off_opacity = 0.25 %}
{# ============================ #}
{# ========== USER CONFIG ========== #}
{# STATE MODE SETTINGS: any state except 'off' will trigger #}
{% set state_entity = 'media_player.android_tv' %}
{% set off_value = 'off' %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER LOGIC ======== #}
{# any state except 'off' #}
{% set trigger_active = (states(state_entity) != off_value) %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
{# ON / ACTIVE COLORS #}
--icon-color: rgb(var(--rgb-{{ icon_on_color }}));
--icon-color-rgb: var(--rgb-{{ icon_on_color }});
--shape-color: rgba({{ circle_on_rgb }}, {{ circle_on_opacity }});
--shape-color-rgb: {{ circle_on_rgb }};
--shape-animation: bass-pulse 0.8s ease-out infinite;
opacity: 1;
{% else %}
{# OFF / IDLE COLORS #}
--icon-color: rgb(var(--rgb-{{ icon_off_color }}));
--icon-color-rgb: var(--rgb-{{ icon_off_color }});
--shape-color: rgba({{ circle_off_rgb }}, {{ circle_off_opacity }});
--shape-color-rgb: {{ circle_off_rgb }};
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes bass-pulse {
0% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--icon-color-rgb), 0.8);
}
10% {
transform: scale(1.08);
box-shadow:
0 0 10px 4px rgba(var(--icon-color-rgb), 0.8);
}
25% {
transform: scale(1.03);
box-shadow:
0 0 6px 2px rgba(var(--icon-color-rgb), 0.5);
}
50% {
transform: scale(1.06);
box-shadow:
0 0 12px 5px rgba(var(--icon-color-rgb), 0.6);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--icon-color-rgb), 0.0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0px 0px -15px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:motion-sensor
icon_color: red
name: PIR Sensor
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: ultra-motion-active 1.3s linear infinite;
--motion-cone-animation: ultra-motion-cone 1.6s linear infinite;
--motion-pulse-animation: ultra-motion-pulse 1.3s ease-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--motion-cone-animation: none;
--motion-pulse-animation: none;
opacity: 0.75;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -6px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--motion-cone-animation);
}
.shape::after {
animation: var(--motion-pulse-animation);
}
@keyframes ultra-motion-active {
0% { transform: scale(1); }
50% { transform: scale(1.06); }
100% { transform: scale(1); }
}
@keyframes ultra-motion-scan {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes ultra-motion-cone {
0% {
box-shadow:
0 -20px 14px -16px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
25% {
box-shadow:
8px -16px 14px -16px rgba(var(--rgb-{{ config.icon_color }}), 0.5);
}
50% {
box-shadow:
0 -20px 14px -12px rgba(var(--rgb-{{ config.icon_color }}), 0.8);
}
75% {
box-shadow:
-8px -16px 14px -16px rgba(var(--rgb-{{ config.icon_color }}), 0.5);
}
100% {
box-shadow:
0 -20px 14px -16px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes ultra-motion-pulse {
0% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
40% {
box-shadow:
0 0 0 8px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 0 14px rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
100% {
box-shadow:
0 0 0 22px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 30px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -18px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-light-card
entity: light.bedroom_lamp_local
use_light_color: true
show_color_temp_control: true
show_brightness_control: true
collapsible_controls: false
show_color_control: true
name: Lamp
icon_color: auto
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{% set state_entity = 'light.bedroom_lamp_local' %}
{% set active_value = 'on' %}
{# ====== TRIGGER ====== #}
{% set trigger_active = (states(state_entity) == active_value) %}
{# ====== COLOR FROM ENTITY (rgb_color) ====== #}
{% set rgb = state_attr(config.entity, 'rgb_color') %}
{% if rgb is not none %}
{% set r = (rgb[0] | int) %}
{% set g = (rgb[1] | int) %}
{% set b = (rgb[2] | int) %}
{% else %}
{# fallback if lamp has no rgb_color (ct-only, etc) #}
{% set r = 255 %}
{% set g = 240 %}
{% set b = 200 %}
{% endif %}
{% if trigger_active %}
--shape-animation: lamp-glow 1.4s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.5;
{% endif %}
}
@keyframes lamp-glow {
0% {
filter: brightness(1);
box-shadow: 0 0 6px 2px rgba({{ r }}, {{ g }}, {{ b }}, 0.6);
}
20% {
filter: brightness(1.25);
box-shadow: 0 0 14px 6px rgba({{ r }}, {{ g }}, {{ b }}, 0.9);
}
30% {
filter: brightness(0.9);
box-shadow: 0 0 3px 1px rgba({{ r }}, {{ g }}, {{ b }}, 0.4);
}
50% {
filter: brightness(1.3);
box-shadow: 0 0 16px 8px rgba({{ r }}, {{ g }}, {{ b }}, 1);
}
80% {
filter: brightness(1.05);
box-shadow: 0 0 8px 3px rgba({{ r }}, {{ g }}, {{ b }}, 0.7);
}
100% {
filter: brightness(1);
box-shadow: 0 0 6px 2px rgba({{ r }}, {{ g }}, {{ b }}, 0.6);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -22px 0px 0px -22px !important;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-cover-card
entity: cover.garage_door
show_buttons_control: true
show_position_control: true
show_tilt_position_control: true
fill_container: false
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========= COLOR CONFIG ========= #}
{% set cover_color = 'blue' %} {# change to 'red', 'blue', etc. #}
--cover-color-rgb: var(--rgb-{{ cover_color }});
{# ================================= #}
{# ========== USER CONFIG ========== #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'cover.garage_door' %}
{% set active_value = 'open' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.cover_position' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: motion-active 1.4s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes motion-active {
0% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--cover-color-rgb), 0.9),
0 0 0 0 rgba(var(--cover-color-rgb), 0.4);
}
40% {
transform: scale(1.06);
box-shadow:
0 0 0 6px rgba(var(--cover-color-rgb), 0.5),
0 0 0 12px rgba(var(--cover-color-rgb), 0.2);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 16px rgba(var(--cover-color-rgb), 0.0),
0 0 0 24px rgba(var(--cover-color-rgb), 0.0);
}
}
@keyframes motion-scan {
0% {
transform: rotate(0deg);
box-shadow:
0 -10px 0 0 rgba(var(--cover-color-rgb), 0.9);
}
50% {
transform: rotate(180deg);
box-shadow:
0 10px 0 0 rgba(var(--cover-color-rgb), 0.6);
}
100% {
transform: rotate(360deg);
box-shadow:
0 -10px 0 0 rgba(var(--cover-color-rgb), 0.9);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -18px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-light-card
entity: light.livingroom_lamp_local
use_light_color: true
show_color_temp_control: true
show_brightness_control: true
collapsible_controls: false
show_color_control: true
name: Lamp
icon_color: auto
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{% set state_entity = 'light.livingroom_lamp_local' %}
{% set active_value = 'on' %}
{# ======== TRIGGER ======== #}
{% set trigger_active = (states(state_entity) == active_value) %}
{# ======== COLOR FROM ENTITY (rgb_color) ======== #}
{% set rgb = state_attr(config.entity, 'rgb_color') %}
{% if rgb is not none %}
{% set r = (rgb[0] | int) %}
{% set g = (rgb[1] | int) %}
{% set b = (rgb[2] | int) %}
{% else %}
{# fallback for CT-only lights #}
{% set r = 255 %}
{% set g = 240 %}
{% set b = 200 %}
{% endif %}
{% if trigger_active %}
--shape-animation: lamp-sweep 1.8s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.5;
{% endif %}
position: relative;
transform-origin: 50% 60%;
}
@keyframes lamp-sweep {
0% {
filter: brightness(1.1);
box-shadow:
0 0 12px 4px rgba({{ r }}, {{ g }}, {{ b }}, 0.9),
0 30px 40px -10px rgba({{ r }}, {{ g }}, {{ b }}, 0.0);
transform: rotate(-4deg) scale(1);
}
25% {
filter: brightness(1.4);
box-shadow:
0 0 18px 8px rgba({{ r }}, {{ g }}, {{ b }}, 1),
-8px 35px 45px -12px rgba({{ r }}, {{ g }}, {{ b }}, 0.5);
transform: rotate(3deg) scale(1.02);
}
50% {
filter: brightness(1.2);
box-shadow:
0 0 24px 10px rgba({{ r }}, {{ g }}, {{ b }}, 0.9),
8px 35px 45px -12px rgba({{ r }}, {{ g }}, {{ b }}, 0.5);
transform: rotate(-2deg) scale(1.03);
}
75% {
filter: brightness(1.5);
box-shadow:
0 0 18px 8px rgba({{ r }}, {{ g }}, {{ b }}, 1),
-6px 30px 40px -12px rgba({{ r }}, {{ g }}, {{ b }}, 0.4);
transform: rotate(2deg) scale(1.01);
}
100% {
filter: brightness(1.1);
box-shadow:
0 0 12px 4px rgba({{ r }}, {{ g }}, {{ b }}, 0.8),
0 30px 40px -10px rgba({{ r }}, {{ g }}, {{ b }}, 0.0);
transform: rotate(-4deg) scale(1);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0px 0px -18px !important;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:controller
icon_color: purple
name: Console
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS (for "intensity") #}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ---------- TRIGGER DECISION LOGIC ---------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# ---------- END TRIGGER LOGIC ---------- #}
{# Optional intensity from power, just for shaping motion #}
{% set power = states(number_entity) | float(0) %}
{% set intensity = (power / 10) | float(0) %}
{% if intensity < 0.3 %}{% set intensity = 0.3 %}{% endif %}
{% if intensity > 1.6 %}{% set intensity = 1.6 %}{% endif %}
{% set px = (1.5 * intensity) | round(2) %}
{% set deg = (5.0 * intensity) | round(2) %}
{% if trigger_active %}
{# If use_number is off, it will just use this "active" path always when switch is on #}
--shape-animation: controller-rumble 0.5s ease-in-out infinite;
--controller-led-animation: controller-led 1.5s ease-in-out infinite;
--controller-trail-animation: controller-trail 1.2s ease-out infinite;
/* Huge RGB glow like your lock example */
--glow-1: 0 0 30px 10px rgba(var(--rgb-{{ config.icon_color }}), 1);
--glow-2: 0 0 70px 22px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
--glow-3: 0 0 120px 42px rgba(var(--rgb-{{ config.icon_color }}), 0.5);
--glow-anim: controller-ultraglow 2.0s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--controller-led-animation: none;
--controller-trail-animation: none;
--glow-1: none;
--glow-2: none;
--glow-3: none;
--glow-anim: none;
opacity: 0.6;
{% endif %}
transform-origin: 50% 50%;
position: relative;
animation: var(--shape-animation);
}
/* Glow layers like the lock card */
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -10px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
box-shadow: var(--glow-1), var(--glow-2), var(--glow-3);
animation: var(--glow-anim);
}
.shape::after {
inset: -22px;
box-shadow:
0 0 130px 40px rgba(var(--rgb-{{ config.icon_color }}), 0.23),
0 0 190px 70px rgba(var(--rgb-{{ config.icon_color }}), 0.15);
opacity: 0.9;
animation: var(--glow-anim);
mix-blend-mode: screen;
}
@keyframes controller-ultraglow {
0% {
opacity: 0.9;
filter: brightness(1);
}
40% {
opacity: 1;
filter: brightness(1.4);
}
70% {
opacity: 1;
filter: brightness(1.2);
}
100% {
opacity: 0.9;
filter: brightness(1);
}
}
@keyframes controller-rumble {
0% { transform: translate(0, 0) rotate(0deg); }
25% { transform: translate(-2px, 1px) rotate(-3deg); }
50% { transform: translate(2px, -1px) rotate(3deg); }
75% { transform: translate(-1px, 2px) rotate(-1deg); }
100% { transform: translate(0, 0) rotate(0deg); }
}
@keyframes controller-led {
0% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 0 16px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.8));
}
33% {
box-shadow:
0 0 0 6px rgba(0, 210, 255, 0.5),
0 0 26px 6px rgba(0, 210, 255, 0.95);
filter: drop-shadow(0 0 5px rgba(0, 210, 255, 1));
}
66% {
box-shadow:
0 0 0 10px rgba(200, 110, 255, 0.5),
0 0 34px 10px rgba(200, 110, 255, 1);
filter: drop-shadow(0 0 6px rgba(200, 110, 255, 1));
}
100% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 0 16px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.8));
}
}
@keyframes controller-trail {
0% {
box-shadow:
22px 0 22px -16px rgba(0, 255, 255, 0),
-22px 0 22px -16px rgba(255, 0, 200, 0);
}
25% {
box-shadow:
26px -4px 26px -14px rgba(0, 255, 255, 0.8),
-26px 4px 26px -14px rgba(255, 0, 200, 0.7);
}
55% {
box-shadow:
20px 4px 24px -14px rgba(0, 255, 160, 0.5),
-20px -4px 24px -14px rgba(255, 210, 0, 0.4);
}
100% {
box-shadow:
22px 0 22px -16px rgba(0, 255, 255, 0),
-22px 0 22px -16px rgba(255, 0, 200, 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 25px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:desktop-tower
icon_color: white
name: Gaming Rig
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. STATE CHECK #}
{% set is_on = states(state_entity) == active_value %}
{# 2. ANIMATION CHECK #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- STYLING --- */
{% if is_on %}
/* DEVICE IS ON */
{% if should_animate %}
/* High Power / Gaming Mode */
--fan-spin: rgb-fan 2s linear infinite;
--case-glow: neon-breathe 2s ease-in-out infinite alternate;
--shadow-layer:
0 0 15px 2px rgba(0, 255, 255, 0.6),
0 0 30px 10px rgba(255, 0, 255, 0.4);
--fan-display: block;
{% else %}
/* Idle / Low Power Mode */
--fan-spin: none;
--case-glow: none;
/* Subtle static glow indicating it is ON but idle */
--shadow-layer: 0 0 5px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
--fan-display: none;
{% endif %}
{% else %}
/* DEVICE IS OFF - RESET TO DEFAULTS */
--fan-spin: none;
--case-glow: none;
--shadow-layer: none;
--fan-display: none;
{% endif %}
/* Boxy PC Case Shape */
border-radius: 10px !important;
position: relative;
overflow: hidden;
transform: translateZ(0);
/* Apply the shadow/glow only when ON */
box-shadow: var(--shadow-layer);
animation: var(--case-glow);
}
/* THE RGB FAN (Spinning Gradient Background) */
.shape::before {
content: '';
display: var(--fan-display); /* Hidden when OFF or Idle */
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: conic-gradient(
from 0deg,
#ff0000,
#ff8000,
#ffff00,
#00ff00,
#00ffff,
#0000ff,
#ff00ff,
#ff0000
);
opacity: 0.5;
animation: var(--fan-spin);
mix-blend-mode: screen;
}
/* THE GLASS PANEL REFLECTION (Static Shine) */
.shape::after {
content: '';
display: var(--fan-display); /* Hidden when OFF */
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.4) 0%, transparent 40%, transparent 100%);
pointer-events: none;
}
/* --- ANIMATIONS --- */
@keyframes rgb-fan {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes neon-breathe {
0% { box-shadow: 0 0 15px 2px rgba(0, 255, 255, 0.6), 0 0 30px 10px rgba(255, 0, 255, 0.4); }
100% { box-shadow: 0 0 25px 5px rgba(0, 255, 255, 0.8), 0 0 50px 20px rgba(255, 0, 255, 0.6); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -15px !important;
padding-right: 10px;
z-index: 1;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:desktop-tower
icon_color: white
name: PC
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# -------- TRIGGER DECISION LOGIC -------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set sensor_entity = state_entity %}
{% if states(sensor_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# ------ END TRIGGER DECISION LOGIC ------ #}
{% if trigger_active %}
/* 1. THE RGB CYCLE: Outer glow */
--gamer-glow: rgb-cycle 5s linear infinite;
/* 2. THE POWER LED: Blinking Yellow Light */
--power-led-anim: yellow-blink 0.5s steps(2, start) infinite;
--led-opacity: 1;
/* Show colors */
filter: grayscale(0%);
opacity: 1;
{% else %}
/* Stop Animations */
--gamer-glow: none;
--power-led-anim: none;
--led-opacity: 0;
/* Turn Gray/Monochrome */
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
/* FORCE SQUARE SHAPE for PC Case look */
border-radius: 12px !important;
position: relative;
transform: translateZ(0);
}
/* The RGB LED Strip Effect (Outer Glow) */
.shape::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
z-index: -1;
animation: var(--gamer-glow);
}
/* The Yellow Power Button LED */
.shape::after {
content: '';
position: absolute;
/* Positioning the dot to match mdi:desktop-tower power button location */
top: 75%;
right: 15%;
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #ffff; /* Bright Yellow */
box-shadow: 0 0 5px #ffeb3b; /* Yellow Glow */
opacity: var(--led-opacity);
animation: var(--power-led-anim);
}
/* --- ANIMATIONS --- */
/* RGB RAINBOW CYCLE */
@keyframes rgb-cycle {
0% {
box-shadow:
0 0 10px 2px rgba(255, 0, 0, 0.6), /* Red */
inset 0 0 15px rgba(255, 0, 0, 0.2);
}
25% {
box-shadow:
0 0 10px 2px rgba(255, 0, 255, 0.6), /* Purple */
inset 0 0 15px rgba(255, 0, 255, 0.2);
}
50% {
box-shadow:
0 0 10px 2px rgba(0, 0, 255, 0.6), /* Blue */
inset 0 0 15px rgba(0, 0, 255, 0.2);
}
75% {
box-shadow:
0 0 10px 2px rgba(0, 255, 255, 0.6), /* Cyan */
inset 0 0 15px rgba(0, 255, 255, 0.2);
}
100% {
box-shadow:
0 0 10px 2px rgba(255, 0, 0, 0.6), /* Back to Red */
inset 0 0 15px rgba(255, 0, 0, 0.2);
}
}
/* YELLOW LED BLINK */
@keyframes yellow-blink {
0% { opacity: 1; transform: scale(1); }
50% { opacity: 0.3; transform: scale(0.9); }
100% { opacity: 1; transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -15px !important;
padding-right: 10px;
z-index: 1;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:server-network
icon_color: blue
name: Home Server
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- APPLY STYLES --- */
/* ANIMATION TOGGLE */
{% if should_animate %}
/* 1. DISK I/O: Chaotic blinking lights */
--disk-activity: hdd-blink 0.5s steps(2, start) infinite;
/* 2. NETWORK LOAD: Heartbeat pulsing */
--server-throb: network-pulse 1.5s ease-in-out infinite;
{% else %}
--disk-activity: none;
--server-throb: none;
{% endif %}
/* STATE COLOR TOGGLE */
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
/* SQUARE SHAPE: Servers are boxes, not circles */
border-radius: 12px !important;
transform-origin: 50% 50%;
position: relative;
animation: var(--server-throb);
}
/* Activity LEDs (The blinking lights) */
.shape::before {
content: '';
position: absolute;
bottom: 25%;
right: 25%;
width: 6px;
height: 6px;
border-radius: 50%;
/* Create 3 "LEDs" using box-shadows to avoid multiple elements */
box-shadow:
10px 0 0 0 #00ff00,
0 10px 0 0 #ffaa00,
10px 10px 0 0 #00ff00;
opacity: 0;
animation: var(--disk-activity);
z-index: 2;
}
/* Network/Heat Glow (Background) */
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: radial-gradient(circle, rgba(var(--rgb-{{ config.icon_color }}), 0.5) 0%, transparent 70%);
opacity: 0;
animation: var(--server-throb);
z-index: 1;
}
/* --- ANIMATIONS --- */
/* Simulates HDD Activity LEDs flickering rapidly */
@keyframes hdd-blink {
0% { opacity: 0; }
25% { opacity: 1; }
50% { opacity: 0; }
75% { opacity: 1; }
90% { opacity: 0; }
100% { opacity: 1; }
}
/* Simulates Network Load / "Heartbeat" */
@keyframes network-pulse {
0% { transform: scale(1); opacity: 0.3; }
50% { transform: scale(1.03); opacity: 0.6; }
100% { transform: scale(1); opacity: 0.3; }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:nintendo-switch
icon_color: white
name: Nintendo Switch
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
{% if should_animate %}
--joycon-glow: neon-split-big 0.5s ease-in-out infinite alternate;
--switch-rumble: haptic-shake 0.4s linear infinite;
{% else %}
--joycon-glow: none;
--switch-rumble: none;
{% endif %}
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
transform-origin: 50% 50%;
position: relative;
overflow: visible !important;
animation: var(--switch-rumble);
}
/* HUGE expanded glow */
.shape::before {
content: "";
position: absolute;
inset: -10px;
border-radius: inherit;
z-index: -1;
animation: var(--joycon-glow);
}
/* MASSIVE dual-color neon */
@keyframes neon-split-big {
0% {
box-shadow:
/* Left red side (3-layer bloom) */
-6px 0 12px rgba(255, 20, 20, 0.5),
-12px 0 24px rgba(255, 20, 20, 0.35),
-18px 0 36px rgba(255, 20, 20, 0.20),
/* Right blue side (3-layer bloom) */
6px 0 12px rgba(0, 200, 255, 0.5),
12px 0 24px rgba(0, 200, 255, 0.35),
18px 0 36px rgba(0, 200, 255, 0.20);
}
100% {
box-shadow:
/* Left — super intense bloom */
-12px 0 24px rgba(255, 20, 20, 0.9),
-24px 0 40px rgba(255, 20, 20, 0.65),
-32px 0 60px rgba(255, 20, 20, 0.40),
/* Right — super intense bloom */
12px 0 24px rgba(0, 200, 255, 0.9),
24px 0 40px rgba(0, 200, 255, 0.65),
32px 0 60px rgba(0, 200, 255, 0.40);
}
}
/* Rumble effect stays unchanged */
@keyframes haptic-shake {
0% { transform: translate(0, 0) rotate(0deg); }
25% { transform: translate(-1px, 1px) rotate(-1deg); }
50% { transform: translate(1px, -1px) rotate(1deg); }
75% { transform: translate(-1px, -1px) rotate(0deg); }
100% { transform: translate(0, 0) rotate(0deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display:flex;
margin: -17px 0 10px -15px !important;
padding-right: 15px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius,12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:printer
icon_color: amber
name: Printer
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- APPLY STYLES --- */
/* ANIMATION TOGGLE */
{% if should_animate %}
/* 1. SHAKE: Simulates mechanical printing vibration */
--printer-shake: printer-vibrate 0.2s linear infinite;
/* 2. SCAN: A laser/copier light bar moving down */
--scan-beam: scanner-light 1.5s ease-in-out infinite;
/* 3. LED: Status light pulsing */
--status-led: led-blink 1s infinite alternate;
{% else %}
--printer-shake: none;
--scan-beam: none;
--status-led: none;
{% endif %}
/* STATE COLOR TOGGLE */
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
transform-origin: 50% 50%;
position: relative;
overflow: hidden; /* Keeps the scan beam inside the circle shape */
/* Apply the mechanical shake to the whole icon */
animation: var(--printer-shake);
}
/* The Scanning Light Beam */
.shape::before {
content: '';
position: absolute;
left: 0;
right: 0;
height: 30%; /* Height of the beam */
background: linear-gradient(to bottom,
transparent 0%,
rgba(255, 255, 255, 0.8) 50%,
transparent 100%);
top: -50%;
animation: var(--scan-beam);
pointer-events: none;
mix-blend-mode: overlay;
}
/* The Status LED (Green/Yellow dot) */
.shape::after {
content: '';
position: absolute;
bottom: 15%;
right: 15%;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #00ff00; /* Green LED */
box-shadow: 0 0 5px #00ff00;
opacity: 0; /* Hidden by default unless animating */
animation: var(--status-led);
}
/* --- ANIMATIONS --- */
/* Mechanical Shake */
@keyframes printer-vibrate {
0% { transform: translate(0, 0); }
25% { transform: translate(-1px, 1px); }
50% { transform: translate(1px, -1px); }
75% { transform: translate(-1px, -1px); }
100% { transform: translate(0, 0); }
}
/* Scanner Bar Movement */
@keyframes scanner-light {
0% { top: -40%; opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { top: 120%; opacity: 0; }
}
/* Status LED Blinking */
@keyframes led-blink {
0% { opacity: 0; transform: scale(0.8); }
100% { opacity: 1; transform: scale(1.2); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:air-purifier
icon_color: light-blue
name: Air Purifier
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{# If not using number, animate whenever ON #}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- APPLY STYLES --- */
/* ANIMATION TOGGLE */
{% if should_animate %}
/* 1. RIPPLE: Represents clean air spreading out */
--air-flow: clean-air-ripple 2s infinite ease-out;
/* 2. BREATH: Represents the intake motor humming */
--core-breath: motor-breath 3s ease-in-out infinite;
{% else %}
--air-flow: none;
--core-breath: none;
{% endif %}
/* STATE COLOR TOGGLE */
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
transform-origin: 50% 50%;
position: relative;
/* Ensure the ripple is visible outside the shape */
overflow: visible !important;
/* Apply the breathing animation to the main shape */
animation: var(--core-breath);
}
/* Inner Ripple (Fast) */
.shape::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
animation: var(--air-flow);
z-index: -1;
}
/* Outer Ripple (Delayed, Slower) */
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: rgba(var(--rgb-{{ config.icon_color }}), 0.1);
animation: var(--air-flow);
animation-duration: 3s; /* Slower expansion */
animation-delay: 0.5s;
z-index: -2;
}
/* --- ANIMATIONS --- */
/* Expanding Rings representing Airflow */
@keyframes clean-air-ripple {
0% {
transform: scale(1);
opacity: 0.8;
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
transform: scale(2.5);
opacity: 0;
box-shadow: 0 0 20px 20px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
/* Gentle "Humming" motion of the device */
@keyframes motor-breath {
0% { transform: scale(1); }
50% { transform: scale(0.95); opacity: 0.9; }
100% { transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:clock-digital
icon_color: cyan
name: Awtrix Clock
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- APPLY STYLES --- */
/* ANIMATION TOGGLE */
{% if should_animate %}
/* 1. SCROLLER: Simulates text/rainbows scrolling across */
--matrix-scroll: pixel-scroll 1.5s linear infinite;
/* 2. REFRESH RATE: Subtle 60hz flicker simulation */
--matrix-flicker: refresh-flicker 0.1s steps(2) infinite;
{% else %}
--matrix-scroll: none;
/* Idle breathing when ON but not active */
--matrix-flicker: idle-breathe 4s ease-in-out infinite;
{% endif %}
/* STATE COLOR TOGGLE */
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
--matrix-flicker: none; /* No breathing when off */
{% endif %}
/* THE MATRIX SHAPE */
border-radius: 8px !important; /* Slightly rounded corners like Ulanzi case */
transform-origin: 50% 50%;
position: relative;
overflow: hidden;
/* Apply the grid pattern directly to the shape background */
background-image:
linear-gradient(rgba(0,0,0,0.2) 1px, transparent 1px),
linear-gradient(90deg, rgba(0,0,0,0.2) 1px, transparent 1px) !important;
background-size: 4px 4px !important; /* Creates the "Pixel" look */
animation: var(--matrix-flicker);
}
/* The Scrolling Marquee / Notification Light */
.shape::before {
content: '';
position: absolute;
top: 0;
left: -100%; /* Start off screen */
width: 100%;
height: 100%;
/* Rainbow Gradient Bar */
background: linear-gradient(90deg,
transparent 0%,
rgba(255, 0, 0, 0.6) 20%,
rgba(255, 255, 0, 0.6) 40%,
rgba(0, 255, 0, 0.6) 60%,
rgba(0, 255, 255, 0.6) 80%,
transparent 100%
);
mix-blend-mode: color-dodge;
animation: var(--matrix-scroll);
}
/* CRT/LED Scanline Glare */
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: linear-gradient(rgba(255,255,255,0.1) 50%, rgba(0,0,0,0.1) 50%);
background-size: 100% 4px;
pointer-events: none;
z-index: 2;
}
/* --- ANIMATIONS --- */
/* Simulates text/colors scrolling left to right */
@keyframes pixel-scroll {
0% { left: -100%; }
100% { left: 100%; }
}
/* Simulates the subtle refresh rate of LED matrices */
@keyframes refresh-flicker {
0% { opacity: 1; }
100% { opacity: 0.95; }
}
/* Standby breathing */
@keyframes idle-breathe {
0% { filter: brightness(1); }
50% { filter: brightness(1.2); }
100% { filter: brightness(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -15px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fridge-industrial
icon_color: white
name: Freezer / Refrigerator
card_mod:
style:
.: |
ha-card {
/* ================= USER CONFIGURATION ================= */
{% set use_number = false %}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
/* ====================================================== */
/* --- LOGIC ENGINE (Do not edit) --- */
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %} {% set active = (num > threshold) %}
{% elif number_operator == '<' %} {% set active = (num < threshold) %}
{% elif number_operator == '=' %} {% set active = (num == threshold) %}
{% elif number_operator == '>=' %} {% set active = (num >= threshold) %}
{% elif number_operator == '<=' %} {% set active = (num <= threshold) %}
{% else %} {% set active = false %} {% endif %}
{% else %}
{% set active = states(state_entity) == active_value %}
{% endif %}
/* --- DEFINE VARIABLES BASED ON STATE --- */
/* These variables are passed down to the icon and used here */
/* Card Styles */
--card-bg: {{ 'linear-gradient(to bottom, #2C5364, #203A43, #0F2027)' if active else 'var(--ha-card-background, var(--card-background-color, white))' }};
--card-shadow: {{ 'inset 0 0 30px rgba(200, 255, 255, 0.6)' if active else 'var(--ha-card-box-shadow, none)' }};
/* Snow Visibility */
--snow-display: {{ 'block' if active else 'none' }};
/* Text Colors */
--primary-text-color: {{ '#e0f7fa' if active else 'var(--primary-text-color)' }};
--secondary-text-color: {{ '#b2ebf2' if active else 'var(--secondary-text-color)' }};
/* Icon Animations (Passed to Shadow DOM) */
--custom-icon-anim: {{ 'compressor-rumble 0.2s linear infinite' if active else 'none' }};
--custom-icon-shadow: {{ '0 0 25px 5px rgba(255, 255, 255, 0.6)' if active else 'none' }};
/* --- APPLY STYLES --- */
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius,12px));
background: var(--card-bg) !important;
box-shadow: var(--card-shadow) !important;
border-radius: 12px;
position: relative;
overflow: hidden;
transition: all 0.5s ease;
}
/* --- LAYER 1: HEAVY FLAKES (Slow) --- */
ha-card::before {
content: '';
display: var(--snow-display);
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 20px 30px, white 2px, transparent 3px),
radial-gradient(circle at 50px 160px, white 2px, transparent 3px),
radial-gradient(circle at 90px 40px, white 2px, transparent 3px),
radial-gradient(circle at 130px 80px, white 2px, transparent 3px),
radial-gradient(circle at 160px 120px, white 2px, transparent 3px),
radial-gradient(circle at 240px 300px, white 2px, transparent 3px),
radial-gradient(circle at 280px 100px, white 2px, transparent 3px);
background-size: 300px 400px;
background-repeat: repeat;
animation: snow-fall-layer1 10s linear infinite;
opacity: 0.9;
pointer-events: none;
z-index: 0;
}
/* --- LAYER 2: FINE BLIZZARD (Fast) --- */
ha-card::after {
content: '';
display: var(--snow-display);
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 10px 10px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 30px 90px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 80px 50px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 110px 190px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 150px 100px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 220px 250px, rgba(255,255,255,0.7) 1px, transparent 2px);
background-size: 300px 300px;
animation: snow-fall-layer2 5s linear infinite;
opacity: 0.6;
pointer-events: none;
z-index: 0;
}
/* Fix icon z-index */
mushroom-shape-icon {
--icon-size: 65px;
display:flex;
margin: -18px 0 10px -18px !important;
padding-right: 15px;
}
.mushroom-state-info {
position: relative;
z-index: 1;
}
/* --- SEAMLESS FALLING ANIMATIONS --- */
@keyframes snow-fall-layer1 {
from { background-position: 0 0; }
to { background-position: 0 400px; }
}
@keyframes snow-fall-layer2 {
from { background-position: 0 0; }
to { background-position: 0 300px; }
}
mushroom-shape-icon$: |
.shape {
--shape-animation: var(--custom-icon-anim) !important;
##box-shadow: var(--custom-icon-shadow) !important;
opacity: 1;
overflow: visible !important;
}
/* Define the Keyframe for the icon here */
@keyframes compressor-rumble {
0% { transform: translate(0, 0); }
25% { transform: translate(-1px, 0.5px); }
50% { transform: translate(1px, -0.5px); }
75% { transform: translate(-0.5px, 0.5px); }
100% { transform: translate(0, 0); }
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fridge-industrial
icon_color: white
name: Freezer / Refrigerator
card_mod:
style:
.: |
ha-card {
/* ================= USER CONFIGURATION ================= */
{% set use_number = false %}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
/* ====================================================== */
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %} {% set active = (num > threshold) %}
{% elif number_operator == '<' %} {% set active = (num < threshold) %}
{% elif number_operator == '=' %} {% set active = (num == threshold) %}
{% elif number_operator == '>=' %} {% set active = (num >= threshold) %}
{% elif number_operator == '<=' %} {% set active = (num <= threshold) %}
{% else %} {% set active = false %} {% endif %}
{% else %}
{% set active = states(state_entity) == active_value %}
{% endif %}
--card-bg: var(--ha-card-background, var(--card-background-color, transparent));
--card-shadow: {{ 'inset 0 0 30px rgba(200, 255, 255, 0.6)' if active else 'var(--ha-card-box-shadow, none)' }};
--snow-display: {{ 'block' if active else 'none' }};
--primary-text-color: {{ '#e0f7fa' if active else 'var(--primary-text-color)' }};
--secondary-text-color: {{ '#b2ebf2' if active else 'var(--secondary-text-color)' }};
--custom-icon-anim: {{ 'compressor-rumble 0.2s linear infinite' if active else 'none' }};
--custom-icon-shadow: {{ '0 0 25px 5px rgba(255, 255, 255, 0.6)' if active else 'none' }};
background: transparent !important;
box-shadow: var(--card-shadow) !important;
border-radius: var(--ha-card-border-radius, 12px);
position: relative;
overflow: hidden;
transition: all 0.5s ease;
isolation: isolate;
}
ha-card::before {
content: '';
display: var(--snow-display);
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 20px 30px, white 2px, transparent 3px),
radial-gradient(circle at 50px 160px, white 2px, transparent 3px),
radial-gradient(circle at 90px 40px, white 2px, transparent 3px),
radial-gradient(circle at 130px 80px, white 2px, transparent 3px),
radial-gradient(circle at 160px 120px, white 2px, transparent 3px),
radial-gradient(circle at 240px 300px, white 2px, transparent 3px),
radial-gradient(circle at 280px 100px, white 2px, transparent 3px);
background-size: 300px 400px;
background-repeat: repeat;
animation: snow-fall-layer1 10s linear infinite;
opacity: 0.9;
pointer-events: none;
z-index: -1;
}
ha-card::after {
content: '';
display: var(--snow-display);
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 10px 10px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 30px 90px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 80px 50px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 110px 190px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 150px 100px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 220px 250px, rgba(255,255,255,0.7) 1px, transparent 2px);
background-size: 300px 300px;
animation: snow-fall-layer2 5s linear infinite;
opacity: 0.6;
pointer-events: none;
z-index: -1;
}
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -18px !important;
padding-right: 15px;
}
.mushroom-state-info {
position: relative;
z-index: 1;
}
@keyframes snow-fall-layer1 {
from { background-position: 0 0; }
to { background-position: 0 400px; }
}
@keyframes snow-fall-layer2 {
from { background-position: 0 0; }
to { background-position: 0 300px; }
}
mushroom-shape-icon$: |
.shape {
--shape-animation: var(--custom-icon-anim) !important;
box-shadow: var(--custom-icon-shadow) !important;
opacity: 1;
overflow: visible !important;
}
@keyframes compressor-rumble {
0% { transform: translate(0, 0); }
25% { transform: translate(-1px, 0.5px); }
50% { transform: translate(1px, -0.5px); }
75% { transform: translate(-0.5px, 0.5px); }
100% { transform: translate(0, 0); }
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:vibrate
icon_color: red
name: Vibration
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# -------- TRIGGER DECISION LOGIC -------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set sensor_entity = state_entity %}
{% if states(sensor_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# ------ END TRIGGER DECISION LOGIC ------ #}
{% if trigger_active %}
--shape-animation: disposal-shake 0.5s linear infinite;
--warp-animation: disposal-shockwave 0.8s ease-out infinite;
--stream-animation: disposal-pulse 1.5s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--warp-animation: none;
--stream-animation: none;
opacity: 1;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--warp-animation);
}
.shape::after {
mix-blend-mode: overlay;
animation: var(--stream-animation);
}
/* THE SHAKE: Rapid movement to simulate heavy grinding motor */
@keyframes disposal-shake {
0% { transform: translate(1px, 1px) rotate(0deg); }
10% { transform: translate(-1px, -2px) rotate(-1deg); }
20% { transform: translate(-3px, 0px) rotate(1deg); }
30% { transform: translate(3px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(1deg); }
50% { transform: translate(-1px, 2px) rotate(-1deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(3px, 1px) rotate(-1deg); }
80% { transform: translate(-1px, -1px) rotate(1deg); }
90% { transform: translate(1px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-1deg); }
}
/* THE SHOCKWAVE: Fast, aggressive expansion */
@keyframes disposal-shockwave {
0% {
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8);
}
70% {
box-shadow: 0 0 0 15px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
100% {
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
/* THE PULSE: Secondary glow to add "heat" to the look */
@keyframes disposal-pulse {
0% {
box-shadow: inset 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
50% {
box-shadow: inset 0 0 10px 4px rgba(var(--rgb-{{ config.icon_color }}), 0.1);
}
100% {
box-shadow: inset 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -18px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:pump
icon_color: blue
name: Water Pump
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. STATE CHECK #}
{% set is_on = states(state_entity) == active_value %}
{# 2. ANIMATION CHECK #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- STYLING --- */
{% if is_on %}
/* DEVICE IS ON */
{% if should_animate %}
/* ACTIVELY PUMPING */
/* 1. Internal Impeller Spin */
--impeller-spin: hydro-spin 0.8s linear infinite;
/* 2. Motor Vibration */
--pump-rumble: motor-shake 0.1s ease-in-out infinite alternate;
/* 3. Water Pressure Waves */
--pressure-flow: flow-ripple 1.5s ease-out infinite;
--effect-display: block;
{% else %}
/* IDLE (Water present but not moving) */
--impeller-spin: none;
--pump-rumble: none;
--pressure-flow: none;
--effect-display: none;
{% endif %}
{% else %}
/* DEVICE IS OFF */
--impeller-spin: none;
--pump-rumble: none;
--pressure-flow: none;
--effect-display: none;
{% endif %}
border-radius: 50%;
position: relative;
overflow: visible !important;
transform: translateZ(0);
/* Shake the housing */
animation: var(--pump-rumble);
}
/* THE INTERNAL IMPELLER (Spinning Gradient) */
.shape::before {
content: '';
display: var(--effect-display);
position: absolute;
inset: 0;
border-radius: 50%;
/* Creates a spinning "fan blade" look inside the color */
background: conic-gradient(
from 0deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.4) 25%,
rgba(255, 255, 255, 0) 50%,
rgba(255, 255, 255, 0.4) 75%,
rgba(255, 255, 255, 0) 100%
);
animation: var(--impeller-spin);
mix-blend-mode: overlay;
z-index: 1; /* Inside the shape */
}
/* THE PRESSURE WAVES (Outer flow) */
.shape::after {
content: '';
display: var(--effect-display);
position: absolute;
inset: 0;
border-radius: 50%;
border: 2px solid rgba(var(--rgb-{{ config.icon_color }}), 0.6);
opacity: 0;
animation: var(--pressure-flow);
z-index: -1; /* Outside the shape */
}
/* --- ANIMATIONS --- */
/* Rapid Impeller Rotation */
@keyframes hydro-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* High-frequency mechanical vibration */
@keyframes motor-shake {
0% { transform: translate(0.5px, 0.5px); }
100% { transform: translate(-0.5px, -0.5px); }
}
/* Expanding Water Ripples */
@keyframes flow-ripple {
0% {
transform: scale(1);
opacity: 0.8;
border-width: 4px;
}
100% {
transform: scale(1.6);
opacity: 0;
border-width: 0px;
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -17px 0 10px -17px !important;
padding-right: 10px;
z-index: 1;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:washing-machine
icon_color: blue
name: Washing Machine
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{% set use_number = false %}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# Logic for Animations #}
{% if trigger_active %}
opacity: 1;
--wash-glow: ultra-wash-glow 1.8s ease-in-out infinite;
--wash-drum: spin-laundry 0.6s cubic-bezier(0.4, 0.0, 0.2, 1) infinite;
/* Added the 'thump' to match the intense style of the plug example */
animation: ultra-wash-thump 1.8s ease-in-out infinite;
{% else %}
opacity: 0.8;
--wash-glow: none;
--wash-drum: none;
animation: none;
{% endif %}
isolation: isolate;
position: relative;
}
/* LAYER 3 (Top): The Icon Frame */
.shape ha-icon {
z-index: 10;
position: relative;
display: block;
}
/* LAYER 2 (Middle): The Spinning Drum Illusion */
.shape::after {
content: "";
position: absolute;
top: 58%;
left: 50%;
width: 24px;
height: 24px;
border-radius: 50%;
z-index: 2;
/* The "Wet Clothes" Texture */
background: conic-gradient(
from 0deg,
transparent 0deg,
var(--icon-color) 40deg,
transparent 100deg,
var(--icon-color) 160deg,
var(--icon-color) 200deg,
transparent 280deg,
var(--icon-color) 320deg
);
filter: blur(0.8px);
opacity: 0.7;
/* Apply Animation */
animation: var(--wash-drum);
/* Hide if not active */
{% if not trigger_active %}
display: none;
{% endif %}
}
/* LAYER 1 (Bottom): The ULTRA Glow */
.shape::before {
content: '';
position: absolute;
inset: -4px; /* Expand glow slightly outside */
border-radius: 50%;
z-index: 1;
animation: var(--wash-glow);
}
/* === ANIMATIONS === */
@keyframes spin-laundry {
0% { transform: translate(-50%, -50%) rotate(0deg); }
100% { transform: translate(-50%, -50%) rotate(360deg); }
}
/* THE REQUESTED ULTRA GLOW (Double Shadow Layer) */
@keyframes ultra-wash-glow {
0% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-blue), 0.6),
0 0 20px 8px rgba(var(--rgb-blue), 0.3);
}
50% {
box-shadow:
0 0 18px 6px rgba(var(--rgb-blue), 0.9),
0 0 32px 12px rgba(var(--rgb-blue), 0.4);
}
100% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-blue), 0.6),
0 0 20px 8px rgba(var(--rgb-blue), 0.3);
}
}
/* THUMP ANIMATION (Matches the plug scale effect) */
@keyframes ultra-wash-thump {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -16px 0 10px -16px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: sensor.3d_printer_progress
tap_action:
action: more-info
icon: mdi:printer-3d-nozzle
icon_color: purple
name: 3D Printer
hold_action:
action: none
double_tap_action:
action: none
card_mod:
style:
.: |
ha-card {
/* ================= USER SETTINGS ================= */
{% set max_val = 100 %}
/* ================================================= */
/* --- LOGIC --- */
{% set val = states(config.entity) | float(0) %}
{% set active = val > 0 and val < max_val %}
{% set is_done = val >= max_val %}
/* Calculate Percentage Width */
{% set width_pct = (val / max_val * 100) | round(2) %}
{% if width_pct > 100 %}{% set width_pct = 100 %}{% endif %}
/* --- CSS VARIABLES --- */
--bar-width: {{ width_pct }}%;
--bar-opacity: {{ 1 if active else 0 }};
--done-opacity: {{ 1 if is_done else 0 }};
/* Icon Variables */
--custom-icon-anim: {{ 'printer-sequence 2.3s linear infinite' if active else 'none' }};
--custom-icon-shadow: {{ '0 0 10px 5px rgba(var(--rgb-' ~ config.icon_color ~ '), 0.6)' if active else 'none' }};
--custom-icon-opacity: {{ '1' if active else '1' }};
/* --- CARD STYLING LOGIC --- */
/* Only apply the dark custom background if ACTIVE. Otherwise, use default theme. */
{% if active %}
background-color: #1c1c1c !important;
border: none !important;
/* Ambient Glow */
background-image: radial-gradient(circle at 24px 24px, rgba(var(--rgb-{{ config.icon_color }}), 0.35) 0%, rgba(var(--rgb-{{ config.icon_color }}), 0.1) 40%, transparent 80%),
linear-gradient(to right, rgba(255,255,255,0.1), rgba(255,255,255,0.1)) !important;
{% else %}
/* When Done/Idle: Reset to defaults (no custom BG color, standard border behavior if any) */
background-image: none !important;
box-shadow: none !important;
/* We don't set background-color here, letting the theme take over */
{% endif %}
border-radius: 12px;
position: relative;
overflow: hidden;
transition: all 0.5s ease;
background-size: 100% 100%, 100% 6px !important;
background-position: top left, bottom left !important;
background-repeat: no-repeat !important;
}
/* --- THE "DONE" BADGE --- */
ha-card::before {
content: 'DONE';
position: absolute;
top: 12px;
right: 12px;
font-size: 10px;
font-weight: 900;
letter-spacing: 1px;
color: #00ff00;
background: rgba(0, 255, 0, 0.15);
border: 1px solid rgba(0, 255, 0, 0.5);
padding: 2px 6px;
border-radius: 4px;
box-shadow: 0 0 10px rgba(0, 255, 0, 0.2);
opacity: var(--done-opacity);
transform: scale(var(--done-opacity));
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
pointer-events: none; /* Let clicks pass through */
}
/* --- ACTIVE PROGRESS BAR (BEAM) --- */
ha-card::after {
content: '';
position: absolute;
bottom: 0; left: 0;
height: 6px;
width: var(--bar-width);
background: linear-gradient(90deg,
rgba(var(--rgb-{{ config.icon_color }}), 0.4) 0%,
rgba(var(--rgb-{{ config.icon_color }}), 1) 100%
);
box-shadow: 0 -2px 10px rgba(var(--rgb-{{ config.icon_color }}), 0.8);
opacity: var(--bar-opacity);
transition: width 0.5s ease-out, opacity 0.5s ease;
animation: bar-flow 2s infinite linear;
pointer-events: none;
}
@keyframes bar-flow {
0% { filter: brightness(1); }
50% { filter: brightness(1.3); }
100% { filter: brightness(1); }
}
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -20px 0 10px -20px !important;
padding-right: 15px;
padding-bottom: 15px;
}
mushroom-shape-icon$: |
.shape {
--shape-animation: var(--custom-icon-anim) !important;
box-shadow: var(--custom-icon-shadow) !important;
opacity: var(--custom-icon-opacity) !important;
transform-origin: 50% 80%;
}
@keyframes printer-sequence {
0% { transform: translate(-5px, 4px) scale(0.96); }
15% { transform: translate(5px, 4px) scale(0.96); }
16% { transform: translate(5px, 2px) scale(0.98); }
30% { transform: translate(-5px, 2px) scale(0.98); }
31% { transform: translate(-5px, 0px) scale(1); }
45% { transform: translate(5px, 0px) scale(1); }
46% { transform: translate(5px, -2px) scale(1.02); }
60% { transform: translate(-5px, -2px) scale(1.02); }
61% { transform: translate(-5px, -4px) scale(1.04); }
80% { transform: translate(5px, -4px) scale(1.04); }
100% { transform: translate(-5px, 4px) scale(0.96); }
}
type: custom:mushroom-entity-card
entity: binary_sensor.contact_front_door_contact
tap_action:
action: more-info
icon: mdi:door
name: Contact (Door)
icon_color: red
primary_info: state
secondary_info: name
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{% set is_open = is_state(config.entity, 'on') %}
/* LOGIC: Define colors and animations based on state */
{% if is_open %}
/* OPEN: Red, Dark Red Shape, Animated */
--icon-color-set: rgb(244, 67, 54);
--shape-color-set: rgba(160, 0, 0, 0.15);
--shape-animation: door-soft-open 1.7s ease-in-out infinite;
/* Increased duration slightly for smoother persistent glow */
--glow-animation: door-soft-glow 2.5s ease-in-out infinite;
--beam-animation: door-soft-beam 2.5s ease-in-out infinite;
--icon-filter: drop-shadow(0 0 6px rgba(160, 0, 0, 0.95));
{% else %}
/* CLOSED: Green, Dark Green Shape, Static */
--icon-color-set: rgb(76, 175, 80);
--shape-color-set: rgba(0, 80, 0, 0.4);
--shape-animation: none;
--glow-animation: none;
--beam-animation: none;
--icon-filter: none;
{% endif %}
/* Apply the variable colors defined above */
background-color: var(--shape-color-set) !important;
/* Standard positioning */
position: relative;
transform-origin: 25% 50%;
animation: var(--shape-animation);
}
/* Color and Filter for the Icon itself */
.shape ha-icon {
color: var(--icon-color-set) !important;
filter: var(--icon-filter);
}
/* --- ANIMATION LAYERS --- */
.shape::before,
.shape::after {
content: '';
position: absolu
Truncated — view the full README on GitHub.
82 followers · starred Jul 2026
218 followers · starred Mar 2026
Take your Home Assistant dashboard to the next level with dynamic, customizable animated cards that bring your smart home dashboard to life.
See the codeCreated by: @Anasbox
Take your Home Assistant dashboard to the next level with dynamic, customizable animated cards that bring your smart home dashboard to life.
| 📂 Category | 📝 Description | 🔗 Link |
|---|---|---|
| 🏠Home | main collection | You are here |
| 🧺 Appliances | washer, dryer, dishwasher, etc | View |
| 🧺 Appliances v2 | washer, dryer, dishwasher, etc | View |
| 🔋 Battery | Battery level, charging animations | View |
| 📈 Graph Cards | Temp, humidity, etc | View |
| 📟 Badge/Button | Make custom Badge/Button | View |
| 🌡️Climate | Climate & Weather | View |
| 🗂️Batch 6 | Batch 6 Cards | View |
Those YouTube Videos Batch 1 | Batch 2 | Batch 3 | Batch 4 | Batch 5 explains how to do it.
[!NOTE] If you are using the Sections view type, you may need to set
rowsto around1.5for the card, otherwise the card may appear compressed. (USE THIS ONLY IF YOU HAVE ISSUES).grid_options: rows: 1.5
[!TIP] Want to change card and text color (useful for light-mode folks)? Add the following to
ha-cardand play with the values (rgb, hex, etc).
background: #1C1C1C !important;
--card-primary-color: white !important;
--card-secondary-color: white !important;
Loading images... please wait
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:power-plug
icon_color: green
name: Smart Plug
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{# Evaluate numeric rule #}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{# State mode #}
{% if states(state_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: ring-breathe 1.8s ease-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
}
@keyframes ring-breathe {
0% { box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9); }
70% { box-shadow: 0 0 0 14px rgba(var(--rgb-{{ config.icon_color }}), 0.0); }
100% { box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:power-socket-au
icon_color: green
name: Charger
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
{# adjust speed based on this plug's own power attribute #}
{% set p = state_attr(config.entity, 'current_power_w') | float(0) %}
{% set dur = 1.6 - (p / 800) %}
--shape-animation: ultra-plug-on {{ [0.4, dur] | max | round(2) }}s ease-in-out infinite;
--plug-glow-animation: ultra-plug-glow 1.8s ease-in-out infinite;
--plug-arcs-animation: ultra-plug-arcs 1.2s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--plug-glow-animation: none;
--plug-arcs-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -4px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--plug-glow-animation);
}
.shape::after {
animation: var(--plug-arcs-animation);
}
@keyframes ultra-plug-on {
0% { transform: scale(1); }
25% { transform: scale(1.05) translateY(-1px); }
50% { transform: scale(1.08) translateY(-2px); }
75% { transform: scale(1.04) translateY(-1px); }
100% { transform: scale(1); }
}
@keyframes ultra-plug-glow {
0% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.3);
}
50% {
box-shadow:
0 0 18px 6px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 32px 12px rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.3);
}
}
@keyframes ultra-plug-arcs {
0% {
box-shadow:
-10px -6px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
12px 4px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
25% {
box-shadow:
-10px -6px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
12px 4px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
50% {
box-shadow:
-6px 2px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.3),
10px -8px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
}
75% {
box-shadow:
-12px 4px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
8px 0 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
100% {
box-shadow:
-10px -6px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
12px 4px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fan
icon_color: blue
name: Fan
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
{# Fan speed logic based on THIS card's entity #}
{% if is_state(config.entity, 'on') %}
--shape-animation: fan-turbine 0.5s linear infinite;
opacity: 1;
{% elif is_state(config.entity, 'medium') %}
--shape-animation: fan-turbine 0.8s linear infinite;
opacity: 1;
{% elif is_state(config.entity, 'low') %}
--shape-animation: fan-turbine 1.2s linear infinite;
opacity: 1;
{% else %}
--shape-animation: fan-rock 2.4s ease-in-out infinite;
opacity: 0.7;
{% endif %}
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
position: relative;
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 0 0 6px rgba(var(--rgb-{{ config.icon_color }}), 0.08),
0 0 18px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.7);
}
@keyframes fan-turbine {
0% {
transform: rotate(0deg) scale(1);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9));
}
25% {
transform: rotate(90deg) scale(1.02);
}
50% {
transform: rotate(180deg) scale(1.04);
filter: drop-shadow(0 0 8px rgba(var(--rgb-{{ config.icon_color }}), 1));
}
75% {
transform: rotate(270deg) scale(1.02);
}
100% {
transform: rotate(360deg) scale(1);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9));
}
}
@keyframes fan-rock {
0% { transform: rotate(-4deg); }
50% { transform: rotate(4deg); }
100% { transform: rotate(-4deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fan
icon_color: cyan
name: Fan
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# -------- TRIGGER DECISION LOGIC -------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set sensor_entity = state_entity %}
{% if states(sensor_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# ------ END TRIGGER DECISION LOGIC ------ #}
{# Fan speed still based on THIS card's entity percentage #}
{% set speed = state_attr(config.entity, 'percentage') | int(0) %}
{% if trigger_active %}
{% if speed == 0 and is_state(config.entity, 'off') %}
--shape-animation: fan-ultra-idle 3s ease-in-out infinite;
{% else %}
{% set dur = 1.2 - (speed / 120) %}
--shape-animation: fan-ultra-spin {{ [0.25, dur] | max | round(2) }}s linear infinite;
{% endif %}
--fan-warp-animation: fan-warp 1.4s ease-in-out infinite;
--fan-stream-animation: fan-stream 1.6s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--fan-warp-animation: none;
--fan-stream-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--fan-warp-animation);
}
.shape::after {
mix-blend-mode: screen;
animation: var(--fan-stream-animation);
}
@keyframes fan-ultra-spin {
0% {
transform: rotate(0deg) scale(1);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.8));
}
20% { transform: rotate(72deg) scale(1.03); }
40% { transform: rotate(144deg) scale(1.05); }
60% { transform: rotate(216deg) scale(1.03); }
80% { transform: rotate(288deg) scale(1.02); }
100% {
transform: rotate(360deg) scale(1);
filter: drop-shadow(0 0 5px rgba(var(--rgb-{{ config.icon_color }}), 1));
}
}
@keyframes fan-ultra-idle {
0% { transform: rotate(-6deg); }
50% { transform: rotate(6deg); }
100% { transform: rotate(-6deg); }
}
@keyframes fan-warp {
0% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.25);
}
40% {
box-shadow:
0 0 0 8px rgba(var(--rgb-{{ config.icon_color }}), 0.4),
0 0 24px 6px rgba(var(--rgb-{{ config.icon_color }}), 0.25);
}
100% {
box-shadow:
0 0 0 18px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 40px 12px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes fan-stream {
0% {
box-shadow:
20px 0 16px -12px rgba(var(--rgb-{{ config.icon_color }}), 0),
-20px 0 16px -12px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
50% {
box-shadow:
24px 0 20px -10px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
-24px 0 20px -10px rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
box-shadow:
20px 0 16px -12px rgba(var(--rgb-{{ config.icon_color }}), 0),
-20px 0 16px -12px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-fan-card
entity: fan.living_room_fan
show_percentage_control: true
show_oscillate_control: true
show_direction_control: true
collapsible_controls: false
fill_container: false
icon_animation: false
icon_type: icon
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========= COLOR CONFIG ========= #}
{# change to 'blue', 'red', 'purple', etc. #}
{% set fan_color = 'green' %}
--fan-color-rgb: var(--rgb-{{ fan_color }});
{# ================================ #}
{# ========== USER CONFIG ========== #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'fan.living_room_fan' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# -------- TRIGGER DECISION LOGIC -------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set sensor_entity = state_entity %}
{% if states(sensor_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# ------ END TRIGGER DECISION LOGIC ------ #}
{# Fan speed still based on THIS card's entity percentage #}
{% set speed = state_attr(config.entity, 'percentage') | int(0) %}
{% if trigger_active %}
{% if speed == 0 and is_state(config.entity, 'off') %}
--shape-animation: fan-ultra-idle 3s ease-in-out infinite;
{% else %}
{% set dur = 1.2 - (speed / 120) %}
--shape-animation: fan-ultra-spin {{ [0.25, dur] | max | round(2) }}s linear infinite;
{% endif %}
--fan-warp-animation: fan-warp 1.4s ease-in-out infinite;
--fan-stream-animation: fan-stream 1.6s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--fan-warp-animation: none;
--fan-stream-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--fan-warp-animation);
}
.shape::after {
mix-blend-mode: screen;
animation: var(--fan-stream-animation);
}
@keyframes fan-ultra-spin {
0% {
transform: rotate(0deg) scale(1);
filter: drop-shadow(0 0 3px rgba(var(--fan-color-rgb), 0.8));
}
20% { transform: rotate(72deg) scale(1.03); }
40% { transform: rotate(144deg) scale(1.05); }
60% { transform: rotate(216deg) scale(1.03); }
80% { transform: rotate(288deg) scale(1.02); }
100% {
transform: rotate(360deg) scale(1);
filter: drop-shadow(0 0 5px rgba(var(--fan-color-rgb), 1));
}
}
@keyframes fan-ultra-idle {
0% { transform: rotate(-6deg); }
50% { transform: rotate(6deg); }
100% { transform: rotate(-6deg); }
}
@keyframes fan-warp {
0% {
box-shadow:
0 0 0 0 rgba(var(--fan-color-rgb), 0.7),
0 0 0 0 rgba(var(--fan-color-rgb), 0.25);
}
40% {
box-shadow:
0 0 0 8px rgba(var(--fan-color-rgb), 0.4),
0 0 24px 6px rgba(var(--fan-color-rgb), 0.25);
}
100% {
box-shadow:
0 0 0 18px rgba(var(--fan-color-rgb), 0.0),
0 0 40px 12px rgba(var(--fan-color-rgb), 0.0);
}
}
@keyframes fan-stream {
0% {
box-shadow:
20px 0 16px -12px rgba(var(--fan-color-rgb), 0),
-20px 0 16px -12px rgba(var(--fan-color-rgb), 0);
}
50% {
box-shadow:
24px 0 20px -10px rgba(var(--fan-color-rgb), 0.6),
-24px 0 20px -10px rgba(var(--fan-color-rgb), 0.4);
}
100% {
box-shadow:
20px 0 16px -12px rgba(var(--fan-color-rgb), 0),
-20px 0 16px -12px rgba(var(--fan-color-rgb), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:lock
icon_color: red
name: Lock
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ---------- TRIGGER DECISION LOGIC ---------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# ---------- END TRIGGER LOGIC ---------- #}
{% if trigger_active %}
{% if is_state(config.entity, 'locked') %}
--shape-animation: lock-secure 2.3s ease-in-out infinite;
{% elif is_state(config.entity, 'unlocking') or is_state(config.entity, 'locking') %}
--shape-animation: lock-action 0.7s ease-in-out infinite;
{% else %}
--shape-animation: lock-open 1.6s ease-in-out infinite;
{% endif %}
opacity: 1;
/* HUGE glow system */
--glow-1: 0 0 25px 8px rgba(var(--rgb-{{ config.icon_color }}), 1);
--glow-2: 0 0 55px 18px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
--glow-3: 0 0 95px 35px rgba(var(--rgb-{{ config.icon_color }}), 0.45);
--glow-anim: lock-ultraglow 2.2s ease-in-out infinite;
{% else %}
--shape-animation: none;
--glow-1: none;
--glow-2: none;
--glow-3: none;
--glow-anim: none;
opacity: 0.6;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
/* Glow layers */
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -8px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
box-shadow: var(--glow-1), var(--glow-2), var(--glow-3);
animation: var(--glow-anim);
}
.shape::after {
inset: -18px;
box-shadow: 0 0 120px 40px rgba(var(--rgb-{{ config.icon_color }}), 0.25);
opacity: 0.9;
animation: var(--glow-anim);
}
@keyframes lock-ultraglow {
0% {
opacity: 0.9;
filter: brightness(1);
}
50% {
opacity: 1;
filter: brightness(1.4);
}
100% {
opacity: 0.9;
filter: brightness(1);
}
}
@keyframes lock-secure {
0% { transform: rotate(0deg) scale(1); }
15% { transform: rotate(-12deg) scale(1.02); }
30% { transform: rotate(2deg) scale(1.03); }
40% { transform: rotate(0deg) scale(1); }
100% { transform: rotate(0deg) scale(1); }
}
@keyframes lock-action {
0% { transform: rotate(-25deg) scale(0.96); }
50% { transform: rotate(25deg) scale(1.04); }
100% { transform: rotate(-25deg) scale(0.96); }
}
@keyframes lock-open {
0% { transform: rotate(10deg); }
50% { transform: rotate(18deg); }
100% { transform: rotate(10deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:projector
icon_color: accent
name: Projector
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: proj-ultra 1.7s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.65;
{% endif %}
transform-origin: 30% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -6px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
background:
radial-gradient(circle at 20% 50%, rgba(255,255,255,0.6), transparent 55%);
transform-origin: 20% 50%;
{% if trigger_active %}
opacity: 0.8;
animation: proj-beam 1.7s ease-in-out infinite;
filter: blur(1px);
{% else %}
opacity: 0; /* hide beam completely */
animation: none;
filter: none;
{% endif %}
}
.shape::after {
{% if trigger_active %}
animation: proj-focus 1.2s ease-in-out infinite;
{% else %}
animation: none;
box-shadow: none; /* kill leftover glow */
{% endif %}
}
@keyframes proj-ultra {
0% { transform: translateX(0) scale(1); }
25% { transform: translateX(1px) scale(1.02); }
50% { transform: translateX(0) scale(1.03); }
75% { transform: translateX(-1px) scale(1.02); }
100% { transform: translateX(0) scale(1); }
}
@keyframes proj-standby {
0% { transform: scale(1); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
@keyframes proj-beam {
0% {
opacity: 0.7;
filter: blur(1px);
transform: scaleX(1) scaleY(1);
}
50% {
opacity: 1;
filter: blur(0.5px);
transform: scaleX(1.15) scaleY(1.05);
}
100% {
opacity: 0.7;
filter: blur(1px);
transform: scaleX(1) scaleY(1);
}
}
@keyframes proj-focus {
0% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
}
50% {
box-shadow:
0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 1);
}
100% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:bell
icon_color: red
name: Doorbell
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{# default: simple equality state trigger #}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: doorbell-ring 0.9s ease-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.8;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes doorbell-ring {
0% {
transform: scale(1.05);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 1),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
30% {
transform: scale(0.95);
box-shadow:
0 0 0 4px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 0 10px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 0 18px rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
60% {
transform: scale(1.02);
box-shadow:
0 0 0 10px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 18px rgba(var(--rgb-{{ config.icon_color }}), 0.2),
0 0 0 26px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes doorbell-idle {
0% { transform: scale(1); }
50% { transform: scale(1.03); }
100% { transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:sprinkler-variant
icon_color: blue
name: Sprinkler
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: irrig-ultra 2s ease-in-out infinite;
--irrig-heads-animation: irrig-heads 1.6s ease-out infinite;
--irrig-fog-animation: irrig-fog 2s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--irrig-heads-animation: none;
--irrig-fog-animation: none;
opacity: 0.75;
{% endif %}
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
border-radius: inherit;
inset: 0;
pointer-events: none;
}
.shape::before {
animation: var(--irrig-heads-animation);
}
.shape::after {
animation: var(--irrig-fog-animation);
}
@keyframes irrig-ultra {
0% { transform: translateY(0) scale(1); }
25% { transform: translateY(-2px) scale(1.02); }
50% { transform: translateY(-4px) scale(1.03); }
75% { transform: translateY(-2px) scale(1.02); }
100% { transform: translateY(0) scale(1); }
}
@keyframes irrig-idle {
0% { transform: translateY(1px); }
50% { transform: translateY(-1px); }
100% { transform: translateY(1px); }
}
@keyframes irrig-heads {
0% {
box-shadow:
-10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
20% {
box-shadow:
-10px 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
40% {
box-shadow:
-10px -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4),
0 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
60% {
box-shadow:
-10px -8px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.1),
0 -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4),
10px 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
}
80% {
box-shadow:
-10px -12px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 -8px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.1),
10px -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
box-shadow:
-10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
@keyframes irrig-fog {
0% {
filter: blur(0);
}
50% {
filter: blur(0.7px);
box-shadow: 0 -14px 18px -8px rgba(var(--rgb-{{ config.icon_color }}), 0.45);
}
100% {
filter: blur(0);
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 20pxx 0px -18px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:sprinkler-variant
icon_color: blue
name: Sprinkler
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: irrig-ultra 2s ease-in-out infinite;
--irrig-heads-animation: irrig-heads 1.6s ease-out infinite;
--irrig-fog-animation: irrig-fog 2s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--irrig-heads-animation: none;
--irrig-fog-animation: none;
opacity: 0.75;
{% endif %}
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
border-radius: inherit;
inset: 0;
pointer-events: none;
}
.shape::before {
animation: var(--irrig-heads-animation);
}
.shape::after {
animation: var(--irrig-fog-animation);
}
@keyframes irrig-ultra {
0% { transform: translateY(0) scale(1); }
25% { transform: translateY(-2px) scale(1.02); }
50% { transform: translateY(-4px) scale(1.03); }
75% { transform: translateY(-2px) scale(1.02); }
100% { transform: translateY(0) scale(1); }
}
@keyframes irrig-idle {
0% { transform: translateY(1px); }
50% { transform: translateY(-1px); }
100% { transform: translateY(1px); }
}
@keyframes irrig-heads {
0% {
box-shadow:
-10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
20% {
box-shadow:
-10px 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
40% {
box-shadow:
-10px -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4),
0 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
60% {
box-shadow:
-10px -8px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.1),
0 -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4),
10px 4px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
}
80% {
box-shadow:
-10px -12px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 -8px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.1),
10px -2px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
box-shadow:
-10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0),
10px 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
@keyframes irrig-fog {
0% {
filter: blur(0);
}
50% {
filter: blur(0.7px);
box-shadow: 0 -14px 18px -8px rgba(var(--rgb-{{ config.icon_color }}), 0.45);
}
100% {
filter: blur(0);
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -17px 0 10px -17px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-climate-card
entity: climate.heatpump
collapsible_controls: false
show_temperature_control: true
fill_container: false
hvac_modes:
- auto
- heat_cool
- cool
- heat
- dry
- fan_only
- "off"
name: Heater
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========= FLAME COLOR CONFIG ========= #}
{% set flame_color = 'deep-orange' %} {# 'red', 'amber', 'orange', etc. #}
--flame-color-rgb: var(--rgb-{{ flame_color }});
{# ===================================== #}
{# ========== USER CONFIG ========== #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'climate.heatpump' %}
{% set active_value = 'heat' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ----------- TRIGGER LOGIC ----------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# --------- END TRIGGER LOGIC --------- #}
{% if trigger_active %}
# --shape-animation: flame-core 1.4s infinite;
--flame-layer1: flame-layers 1.8s infinite;
--flame-layer2: ember-pulse 2.4s infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--flame-layer1: none;
--flame-layer2: none;
opacity: 0.6;
{% endif %}
position: relative;
transform-origin: 50% 75%;
}
/* Flame layers */
.shape::before,
.shape::after {
content: "";
position: absolute;
inset: -8px;
border-radius: inherit;
pointer-events: none;
filter: blur(3px);
}
.shape::before {
animation: var(--flame-layer1);
}
.shape::after {
animation: var(--flame-layer2);
}
/* Core flame motion: chaotic vertical flicker + heat ripple */
@keyframes flame-core {
0% { transform: translateY(0) scale(1); filter: brightness(1.1) hue-rotate(0deg); }
12% { transform: translateY(-2px) scale(1.05); filter: brightness(1.4) hue-rotate(-10deg); }
25% { transform: translateY(1px) scale(0.98); filter: brightness(0.9) hue-rotate(8deg); }
40% { transform: translateY(-3px) scale(1.07); filter: brightness(1.5) hue-rotate(-18deg); }
55% { transform: translateY(0) scale(1.02); filter: brightness(1.2) hue-rotate(10deg); }
70% { transform: translateY(-1px) scale(1.04); filter: brightness(1.35) hue-rotate(-6deg); }
85% { transform: translateY(2px) scale(0.97); filter: brightness(0.95) hue-rotate(6deg); }
100% { transform: translateY(0) scale(1); filter: brightness(1.1) hue-rotate(0deg); }
}
/* Outer flame shape: shifting blurred glow */
@keyframes flame-layers {
0% {
box-shadow:
0 0 14px 8px rgba(var(--flame-color-rgb), 0.8),
0 -12px 24px -6px rgba(255, 200, 0, 0.4);
}
33% {
box-shadow:
0 0 20px 10px rgba(var(--flame-color-rgb), 1),
0 -16px 30px -8px rgba(255, 160, 0, 0.5);
}
66% {
box-shadow:
0 0 18px 9px rgba(var(--flame-color-rgb), 0.9),
0 -8px 20px -6px rgba(255, 220, 0, 0.35);
}
100% {
box-shadow:
0 0 14px 8px rgba(var(--flame-color-rgb), 0.8),
0 -12px 24px -6px rgba(255, 200, 0, 0.4);
}
}
/* Ember pulse: slow breathing glow */
@keyframes ember-pulse {
0% {
box-shadow:
0 0 30px 10px rgba(var(--flame-color-rgb), 0.25),
0 0 60px 20px rgba(255, 120, 0, 0.15);
}
50% {
box-shadow:
0 0 50px 18px rgba(var(--flame-color-rgb), 0.5),
0 0 90px 35px rgba(255, 150, 0, 0.25);
}
100% {
box-shadow:
0 0 30px 10px rgba(var(--flame-color-rgb), 0.25),
0 0 60px 20px rgba(255, 120, 0, 0.15);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -17px 0 20px -17px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:led-strip-variant
icon_color: blue
name: LED Strip
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: rgb-wave 2.2s linear infinite;
opacity: 1;
{% else %}
--shape-animation: rgb-off 3s ease-in-out infinite;
opacity: 0.5;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes rgb-wave {
0% {
filter: hue-rotate(0deg) brightness(1.1);
box-shadow:
0 0 12px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9);
transform: scale(1);
}
25% {
filter: hue-rotate(90deg) brightness(1.3);
box-shadow:
0 0 16px 6px rgba(var(--rgb-{{ config.icon_color }}), 1);
transform: scale(1.04);
}
50% {
filter: hue-rotate(180deg) brightness(1.15);
box-shadow:
0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.9);
transform: scale(1.02);
}
75% {
filter: hue-rotate(270deg) brightness(1.3);
box-shadow:
0 0 16px 6px rgba(var(--rgb-{{ config.icon_color }}), 1);
transform: scale(1.04);
}
100% {
filter: hue-rotate(360deg) brightness(1.1);
box-shadow:
0 0 12px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9);
transform: scale(1);
}
}
@keyframes rgb-off {
0% { filter: brightness(0.7); }
50% { filter: brightness(0.9); }
100% { filter: brightness(0.7); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:washing-machine
icon_color: blue
name: Washing Machine
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: wash-cycle 1s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.8;
{% endif %}
transform-origin: 50% 55%;
}
@keyframes wash-cycle {
0% { transform: translateY(0) rotate(-8deg) scale(1); box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.5); }
20% { transform: translateY(-3px) rotate(8deg) scale(1.02); box-shadow: 0 0 8px 4px rgba(var(--rgb-{{ config.icon_color }}), 0.3); }
40% { transform: translateY(2px) rotate(-6deg) scale(1.01); }
60% { transform: translateY(-2px) rotate(6deg) scale(1.02); }
80% { transform: translateY(1px) rotate(-4deg) scale(1.01); }
100% { transform: translateY(0) rotate(-8deg) scale(1); box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.2); }
}
@keyframes wash-idle {
0% { transform: rotate(0deg); }
50% { transform: rotate(2deg); }
100% { transform: rotate(0deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -22px 0 10px -22px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:washing-machine
icon_color: blue
name: Washing Machine
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: washer-chaos 1.1s cubic-bezier(0.25, 0.1, 0.25, 1) infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.85;
{% endif %}
transform-origin: 50% 55%;
box-shadow:
inset 0 0 0 2px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 10px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.6);
position: relative;
}
@keyframes washer-chaos {
0% {
transform: rotate(0deg) scale(1);
box-shadow:
inset 0 0 0 2px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.6);
}
15% { transform: rotate(18deg) translate(1px, -1px) scale(1.02); }
30% { transform: rotate(60deg) translate(-2px, 2px) scale(0.98); }
45% { transform: rotate(120deg) translate(3px, -2px) scale(1.03); }
60% { transform: rotate(190deg) translate(-1px, 3px) scale(0.97); }
75% { transform: rotate(260deg) translate(1px, -3px) scale(1.04); }
90% { transform: rotate(330deg) translate(-2px, 1px) scale(1.01); }
100% {
transform: rotate(360deg) translate(0, 0) scale(1);
box-shadow:
inset 0 0 0 2px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 10px 6px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes washer-idle {
0% { transform: rotate(-2deg); }
50% { transform: rotate(2deg); }
100% { transform: rotate(-2deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -22px 0 10px -22px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:dishwasher
icon_color: blue
name: Dishwasher
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: dishwasher-swash 1.5s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.8;
{% endif %}
transform-origin: 50% 55%;
}
@keyframes dishwasher-swash {
0% {
transform: scale(1) rotate(0deg);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.3);
filter: blur(0);
}
25% {
transform: scale(1.03) rotate(10deg);
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 18px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.3);
filter: blur(0.4px);
}
50% {
transform: scale(0.98) rotate(-15deg);
box-shadow:
0 0 14px 6px rgba(var(--rgb-{{ config.icon_color }}), 0.7),
0 0 26px 12px rgba(var(--rgb-{{ config.icon_color }}), 0.2);
filter: blur(0.6px);
}
75% {
transform: scale(1.04) rotate(15deg);
box-shadow:
0 0 10px 3px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 18px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.3);
filter: blur(0.4px);
}
100% {
transform: scale(1) rotate(0deg);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0);
filter: blur(0);
}
}
@keyframes dishwasher-idle {
0% { transform: scale(1); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fire
icon_color: deep-orange
name: Fireplace
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ----------- TRIGGER LOGIC ----------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# --------- END TRIGGER LOGIC --------- #}
{% if trigger_active %}
--shape-animation: flame-core 1.4s infinite;
--flame-layer1: flame-layers 1.8s infinite;
--flame-layer2: ember-pulse 2.4s infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--flame-layer1: none;
--flame-layer2: none;
opacity: 0.6;
{% endif %}
position: relative;
transform-origin: 50% 75%;
}
/* Flame layers */
.shape::before,
.shape::after {
content: "";
position: absolute;
inset: -8px;
border-radius: inherit;
pointer-events: none;
filter: blur(3px);
}
.shape::before {
animation: var(--flame-layer1);
}
.shape::after {
animation: var(--flame-layer2);
}
/* Core flame motion: chaotic vertical flicker + heat ripple */
@keyframes flame-core {
0% { transform: translateY(0) scale(1); filter: brightness(1.1) hue-rotate(0deg); }
12% { transform: translateY(-2px) scale(1.05); filter: brightness(1.4) hue-rotate(-10deg); }
25% { transform: translateY(1px) scale(0.98); filter: brightness(0.9) hue-rotate(8deg); }
40% { transform: translateY(-3px) scale(1.07); filter: brightness(1.5) hue-rotate(-18deg); }
55% { transform: translateY(0) scale(1.02); filter: brightness(1.2) hue-rotate(10deg); }
70% { transform: translateY(-1px) scale(1.04); filter: brightness(1.35) hue-rotate(-6deg); }
85% { transform: translateY(2px) scale(0.97); filter: brightness(0.95) hue-rotate(6deg); }
100% { transform: translateY(0) scale(1); filter: brightness(1.1) hue-rotate(0deg); }
}
/* Outer flame shape: shifting blurred glow */
@keyframes flame-layers {
0% {
box-shadow:
0 0 14px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 -12px 24px -6px rgba(255, 200, 0, 0.4);
}
33% {
box-shadow:
0 0 20px 10px rgba(var(--rgb-{{ config.icon_color }}), 1),
0 -16px 30px -8px rgba(255, 160, 0, 0.5);
}
66% {
box-shadow:
0 0 18px 9px rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 -8px 20px -6px rgba(255, 220, 0, 0.35);
}
100% {
box-shadow:
0 0 14px 8px rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 -12px 24px -6px rgba(255, 200, 0, 0.4);
}
}
/* Ember pulse: slow breathing glow */
@keyframes ember-pulse {
0% {
box-shadow:
0 0 30px 10px rgba(var(--rgb-{{ config.icon_color }}), 0.25),
0 0 60px 20px rgba(255, 120, 0, 0.15);
}
50% {
box-shadow:
0 0 50px 18px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 90px 35px rgba(255, 150, 0, 0.25);
}
100% {
box-shadow:
0 0 30px 10px rgba(var(--rgb-{{ config.icon_color }}), 0.25),
0 0 60px 20px rgba(255, 120, 0, 0.15);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 20px -20px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:robot-vacuum
icon_color: blue
name: Vacuum
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: robo-path 3.4s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes robo-path {
0% { transform: translate(0, 0) scale(1); }
10% { transform: translate(6px, -2px) rotate(8deg) scale(0.98); }
20% { transform: translate(10px, 4px) rotate(-6deg) scale(1); }
30% { transform: translate(4px, 8px) rotate(-14deg) scale(1.02); }
40% { transform: translate(-6px, 10px) rotate(4deg) scale(0.98); }
50% { transform: translate(-10px, 2px) rotate(16deg) scale(1.03); }
60% { transform: translate(-6px, -6px) rotate(-8deg) scale(1); }
70% { transform: translate(2px, -10px) rotate(10deg) scale(0.97); }
80% { transform: translate(8px, -6px) rotate(-6deg) scale(1.02); }
90% { transform: translate(4px, -2px) rotate(4deg) scale(1.01); }
100% { transform: translate(0, 0) rotate(0deg) scale(1); }
}
@keyframes robo-dock {
0% { transform: translateY(0); }
50% { transform: translateY(-2px); }
100% { transform: translateY(0); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 20pxx 0px -18px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:printer-3d-nozzle
icon_color: purple
name: 3d Printer
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: printer-sequence 2.3s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.8;
{% endif %}
transform-origin: 50% 80%;
box-shadow:
0 8px 0 -4px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 12px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8);
}
@keyframes printer-sequence {
0% { transform: translate(-5px, 4px) scale(0.96); }
15% { transform: translate(5px, 4px) scale(0.96); }
16% { transform: translate(5px, 2px) scale(0.98); }
30% { transform: translate(-5px, 2px) scale(0.98); }
31% { transform: translate(-5px, 0px) scale(1); }
45% { transform: translate(5px, 0px) scale(1); }
46% { transform: translate(5px, -2px) scale(1.02); }
60% { transform: translate(-5px, -2px) scale(1.02); }
61% { transform: translate(-5px, -4px) scale(1.04); }
80% { transform: translate(5px, -4px) scale(1.04); }
100% { transform: translate(-5px, 4px) scale(0.96); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -22px 0 10px -22px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:motion-sensor
icon_color: red
name: PIR Sensor
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: motion-active 1.4s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes motion-active {
0% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
40% {
transform: scale(1.06);
box-shadow:
0 0 0 6px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 0 12px rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 16px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 24px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes motion-scan {
0% {
transform: rotate(0deg);
box-shadow:
0 -10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
}
50% {
transform: rotate(180deg);
box-shadow:
0 10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.6);
}
100% {
transform: rotate(360deg);
box-shadow:
0 -10px 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -18px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:alarm
icon_color: pink
name: Alarm
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: siren-alert 0.6s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes siren-alert {
0% {
transform: translate(0, 0) scale(1);
box-shadow: 0 0 10px 4px rgba(var(--rgb-{{ config.icon_color }}), 1);
}
10% { transform: translate(-2px, -1px) rotate(-3deg) scale(1.02); }
20% { transform: translate(3px, 1px) rotate(2deg) scale(1.03); }
30% { transform: translate(-4px, 0) rotate(-4deg) scale(1.04); }
40% { transform: translate(4px, 2px) rotate(3deg) scale(1.05); }
50% { transform: translate(-2px, -2px) rotate(-2deg) scale(1.02); }
60% { transform: translate(2px, 1px) rotate(1deg) scale(1.03); }
70% { transform: translate(-3px, 0) rotate(-3deg) scale(1.04); }
80% { transform: translate(3px, -1px) rotate(2deg) scale(1.03); }
100% {
transform: translate(0, 0) rotate(0deg) scale(1);
box-shadow: 0 0 20px 8px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
@keyframes siren-armed {
0% { box-shadow: 0 0 4px 1px rgba(var(--rgb-{{ config.icon_color }}), 0.4); }
50% { box-shadow: 0 0 10px 4px rgba(var(--rgb-{{ config.icon_color }}), 0.9); }
100% { box-shadow: 0 0 4px 1px rgba(var(--rgb-{{ config.icon_color }}), 0.4); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
icon: mdi:radiator
icon_color: amber
name: Heater
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{% set power_val = states(number_entity) | float(0) %}
{% set norm = (power_val / 1500) | float %}
{% set norm_c = [0, [norm, 1.3] | min] | max %}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% if number_operator == '>' %}
{% set trigger_active = (power_val > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (power_val < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (power_val == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (power_val >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (power_val <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: heater-waves 1.7s ease-in-out infinite;
--heater-glow-animation: heater-glow 2.1s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--heater-glow-animation: none;
opacity: 0.6;
{% endif %}
--heater-scale: {{ (1 + norm_c * 0.15) | round(3) }};
transform-origin: 50% 60%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -8px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--heater-glow-animation);
}
.shape::after {
inset: -18px;
animation: var(--heater-glow-animation);
opacity: 0.9;
}
@keyframes heater-waves {
0% { transform: translateY(0) scale(1); }
25% { transform: translateY(-1px) scale(var(--heater-scale)); }
50% { transform: translateY(-2px) scale(1.02); }
75% { transform: translateY(-1px) scale(var(--heater-scale)); }
100% { transform: translateY(0) scale(1); }
}
@keyframes heater-glow {
0% {
box-shadow:
0 -10px 18px -6px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 -20px 40px -10px rgba(255, 120, 0, 0.35);
}
50% {
box-shadow:
0 -14px 26px -4px rgba(var(--rgb-{{ config.icon_color }}), 1),
0 -26px 60px -10px rgba(255, 90, 0, 0.55);
}
100% {
box-shadow:
0 -10px 18px -6px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 -20px 40px -10px rgba(255, 120, 0, 0.35);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -15px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:led-on
icon_color: blue
name: RGB
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% if states(state_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: rainbow 3s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
}
@keyframes rainbow {
0% { filter: hue-rotate(0deg) brightness(1.1); }
50% { filter: hue-rotate(180deg) brightness(1.3); }
100% { filter: hue-rotate(360deg) brightness(1.1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:kettle-steam
icon_color: brown
name: Kettle
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: tv-glitch 1.2s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.6;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes tv-glitch {
0% { transform: scale(1) translate(0, 0); filter: brightness(1.05); box-shadow: 0 0 8px 2px rgba(var(--rgb-{{ config.icon_color }}), 0.7); }
10% { transform: scaleX(1.02) translate(-1px, 0); }
20% { transform: scaleX(0.98) translate(1px, -1px); filter: brightness(1.3); }
25% { transform: scale(1.01) translate(0, 1px); }
40% { transform: scale(1) translate(0, 0); filter: brightness(1.1); }
55% { transform: scaleX(1.03) translate(0, -1px); }
70% { transform: scale(1) translate(0, 0); box-shadow: 0 0 14px 5px rgba(var(--rgb-{{ config.icon_color }}), 0.9); }
100% { transform: scale(1) translate(0, 0); filter: brightness(1.05); box-shadow: 0 0 8px 2px rgba(var(--rgb-{{ config.icon_color }}), 0.7); }
}
@keyframes tv-standby {
0% { box-shadow: 0 0 2px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.3); }
50% { box-shadow: 0 0 6px 2px rgba(var(--rgb-{{ config.icon_color }}), 0.6); }
100% { box-shadow: 0 0 2px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.3); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -15px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-media-player-card
entity: media_player.android_tv
volume_controls:
- volume_mute
- volume_set
- volume_buttons
media_controls:
- on_off
- shuffle
- previous
- play_pause_stop
- next
- repeat
show_volume_level: true
use_media_info: false
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ======= COLOR CONFIG ======= #}
{% set icon_on_color = 'red' %}
{% set circle_on_rgb = '255, 30, 30' %} {# dark red #}
{% set circle_on_opacity = 0.1 %}
{% set icon_off_color = 'grey' %}
{% set circle_off_rgb = '80, 80, 80' %} {# dark grey #}
{% set circle_off_opacity = 0.25 %}
{# ============================ #}
{% set s = states('media_player.android_tv') %}
{% if s != 'off' %}
{% set trigger = true %}
{% else %}
{% set trigger = false %}
{% endif %}
{% if trigger %}
/* icon color */
--icon-color: rgb(var(--rgb-{{ icon_on_color }}));
--icon-color-rgb: var(--rgb-{{ icon_on_color }});
/* circle color */
--shape-color: rgba({{ circle_on_rgb }}, {{ circle_on_opacity }});
--shape-color-rgb: {{ circle_on_rgb }};
--shape-animation: tv-rgb 1.4s linear infinite;
--glow-enabled: 1;
opacity: 1;
{% else %}
/* icon color */
--icon-color: rgb(var(--rgb-{{ icon_off_color }}));
--icon-color-rgb: var(--rgb-{{ icon_off_color }});
/* circle color */
--shape-color: rgba({{ circle_off_rgb }}, {{ circle_off_opacity }});
--shape-color-rgb: {{ circle_off_rgb }};
--shape-animation: none;
--glow-enabled: 0;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
/* Remove glow when off */
.shape[style*="--glow-enabled: 0"] {
filter: none !important;
box-shadow: none !important;
}
.shape[style*="--glow-enabled: 0"]::before,
.shape[style*="--glow-enabled: 0"]::after {
animation: none !important;
filter: none !important;
box-shadow: none !important;
}
@keyframes tv-rgb {
0% {
transform: scale(1); /* no movement */
filter: brightness(1.0);
box-shadow:
0 0 6px 2px rgba(var(--icon-color-rgb), 0.4),
-4px 0 8px -4px rgba(255, 0, 0, 0.4),
4px 0 8px -4px rgba(0, 128, 255, 0.4);
}
40% {
transform: scale(1); /* still */
filter: brightness(1.25);
box-shadow:
0 0 16px 6px rgba(var(--icon-color-rgb), 0.9),
-6px 0 12px -4px rgba(255, 0, 0, 0.7),
6px 0 12px -4px rgba(0, 128, 255, 0.7);
}
100% {
transform: scale(1); /* still */
filter: brightness(1.0);
box-shadow:
0 0 6px 2px rgba(var(--icon-color-rgb), 0.4),
-4px 0 8px -4px rgba(255, 0, 0, 0.4),
4px 0 8px -4px rgba(0, 128, 255, 0.4);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0px 0px -15px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius,12px));
}
type: custom:mushroom-media-player-card
entity: media_player.living_room_speaker
volume_controls:
- volume_mute
- volume_set
- volume_buttons
media_controls:
- on_off
- shuffle
- previous
- play_pause_stop
- next
- repeat
show_volume_level: true
use_media_info: false
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ====== COLOR CONFIG ====== #}
{% set icon_on_color = 'red' %}
{% set circle_on_rgb = '255, 30, 30' %}
{% set circle_on_opacity = 0.1 %}
{% set icon_off_color = 'grey' %}
{% set circle_off_rgb = '80, 80, 80' %}
{% set circle_off_opacity = 0.25 %}
{# ========================== #}
{# ========== USER CONFIG ========== #}
{# STATE ENTITY #}
{% set state_entity = 'media_player.living_room_speaker' %}
{% set off_value = 'off' %}
{% set play_value = 'playing' %}
{% set idle_value = 'idle' %}
{# ========== END CONFIG ========== #}
{% set st = states(state_entity) %}
{# LIGHT ACTIVE = any state except off #}
{% set light_active = (st != off_value) %}
{# ANIMATION TRIGGER: default = only when playing #}
{# animation ONLY when playing #}
{% set trigger_active = (st == play_value) %}
{% set vol = state_attr(config.entity, 'volume_level') | float(0) %}
{% if light_active %}
{# ---- COLORS WHEN NOT OFF ---- #}
--icon-color: rgb(var(--rgb-{{ icon_on_color }}));
--icon-color-rgb: var(--rgb-{{ icon_on_color }});
--shape-color: rgba({{ circle_on_rgb }}, {{ circle_on_opacity }});
--shape-color-rgb: {{ circle_on_rgb }};
opacity: 1;
{# ---- ANIMATION ONLY WHEN trigger_active ---- #}
{% if trigger_active %}
--shape-animation: ultra-speaker-main 0.9s ease-in-out infinite;
--speaker-bars-animation: ultra-speaker-bars 0.55s linear infinite;
--speaker-bass-animation: ultra-speaker-bass 1s ease-out infinite;
{% else %}
--shape-animation: none;
--speaker-bars-animation: none;
--speaker-bass-animation: none;
--no-glow: 0 0 0 0 rgba(0,0,0,0);
{% endif %}
{% else %}
{# ---- OFF: DIM + NO ANIMATION ---- #}
--icon-color: rgb(var(--rgb-{{ icon_off_color }}));
--icon-color-rgb: var(--rgb-{{ icon_off_color }});
--shape-color: rgba({{ circle_off_rgb }}, {{ circle_off_opacity }});
--shape-color-rgb: {{ circle_off_rgb }};
--shape-animation: none;
--speaker-bars-animation: none;
--speaker-bass-animation: none;
--no-glow: 0 0 0 0 rgba(0,0,0,0);
opacity: 0.6;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--speaker-bars-animation);
box-shadow: var(--no-glow, none);
}
.shape::after {
animation: var(--speaker-bass-animation);
box-shadow: var(--no-glow, none);
}
@keyframes ultra-speaker-main {
0% { transform: scale(1); }
50% { transform: scale(1.06); }
100% { transform: scale(1); }
}
@keyframes ultra-speaker-bars {
0% {
box-shadow:
-10px 6px 0 -5px rgba(var(--icon-color-rgb), 0.4),
0 2px 0 -5px rgba(var(--icon-color-rgb), 0.6),
10px -4px 0 -5px rgba(var(--icon-color-rgb), 0.3);
}
33% {
box-shadow:
-10px -2px 0 -5px rgba(var(--icon-color-rgb), 0.7),
0 8px 0 -5px rgba(var(--icon-color-rgb), 0.3),
10px -8px 0 -5px rgba(var(--icon-color-rgb), 0.6);
}
66% {
box-shadow:
-10px -8px 0 -5px rgba(var(--icon-color-rgb), 0.3),
0 -4px 0 -5px rgba(var(--icon-color-rgb), 0.7),
10px 6px 0 -5px rgba(var(--icon-color-rgb), 0.5);
}
100% {
box-shadow:
-10px 6px 0 -5px rgba(var(--icon-color-rgb), 0.4),
0 2px 0 -5px rgba(var(--icon-color-rgb), 0.6),
10px -4px 0 -5px rgba(var(--icon-color-rgb), 0.3);
}
}
@keyframes ultra-speaker-bass {
0% {
{% set s0 = 1 + (vol * 0.09) %}
transform: scale({{ s0 | round(2) }});
box-shadow:
0 0 0 0 rgba(var(--icon-color-rgb), 0.9),
0 0 0 0 rgba(var(--icon-color-rgb), 0.5);
}
40% {
{% set s1 = 1.08 + vol * 0.1 %}
transform: scale({{ s1 | round(2) }});
box-shadow:
0 0 0 8px rgba(var(--icon-color-rgb), 0.6),
0 0 0 14px rgba(var(--icon-color-rgb), 0.3);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 20px rgba(var(--icon-color-rgb), 0),
0 0 0 30px rgba(var(--icon-color-rgb), 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0px 0px -18px !important;
padding-right: 20px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:router-wireless
icon_color: blue
name: Router
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: wifi-waves 1.7s ease-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.6;
{% endif %}
position: relative;
}
@keyframes wifi-waves {
0% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
30% {
box-shadow:
0 0 0 4px rgba(var(--rgb-{{ config.icon_color }}), 0.6),
0 0 0 10px rgba(var(--rgb-{{ config.icon_color }}), 0.35),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
60% {
box-shadow:
0 0 0 8px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 18px rgba(var(--rgb-{{ config.icon_color }}), 0.25),
0 0 0 28px rgba(var(--rgb-{{ config.icon_color }}), 0.1);
}
100% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-media-player-card
entity: media_player.android_tv
volume_controls:
- volume_mute
- volume_set
- volume_buttons
media_controls:
- on_off
- shuffle
- previous
- play_pause_stop
- next
- repeat
show_volume_level: true
use_media_info: false
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ======= COLOR CONFIG ======= #}
{% set icon_on_color = 'red' %}
{% set circle_on_rgb = '255, 30, 30' %} {# dark red-ish #}
{% set circle_on_opacity = 0.15 %}
{% set icon_off_color = 'grey' %}
{% set circle_off_rgb = '80, 80, 80' %} {# dark grey #}
{% set circle_off_opacity = 0.25 %}
{# ============================ #}
{# ========== USER CONFIG ========== #}
{# STATE MODE SETTINGS: any state except 'off' will trigger #}
{% set state_entity = 'media_player.android_tv' %}
{% set off_value = 'off' %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER LOGIC ======== #}
{# any state except 'off' #}
{% set trigger_active = (states(state_entity) != off_value) %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
{# ON / ACTIVE COLORS #}
--icon-color: rgb(var(--rgb-{{ icon_on_color }}));
--icon-color-rgb: var(--rgb-{{ icon_on_color }});
--shape-color: rgba({{ circle_on_rgb }}, {{ circle_on_opacity }});
--shape-color-rgb: {{ circle_on_rgb }};
--shape-animation: bass-pulse 0.8s ease-out infinite;
opacity: 1;
{% else %}
{# OFF / IDLE COLORS #}
--icon-color: rgb(var(--rgb-{{ icon_off_color }}));
--icon-color-rgb: var(--rgb-{{ icon_off_color }});
--shape-color: rgba({{ circle_off_rgb }}, {{ circle_off_opacity }});
--shape-color-rgb: {{ circle_off_rgb }};
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes bass-pulse {
0% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--icon-color-rgb), 0.8);
}
10% {
transform: scale(1.08);
box-shadow:
0 0 10px 4px rgba(var(--icon-color-rgb), 0.8);
}
25% {
transform: scale(1.03);
box-shadow:
0 0 6px 2px rgba(var(--icon-color-rgb), 0.5);
}
50% {
transform: scale(1.06);
box-shadow:
0 0 12px 5px rgba(var(--icon-color-rgb), 0.6);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--icon-color-rgb), 0.0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0px 0px -15px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:motion-sensor
icon_color: red
name: PIR Sensor
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: ultra-motion-active 1.3s linear infinite;
--motion-cone-animation: ultra-motion-cone 1.6s linear infinite;
--motion-pulse-animation: ultra-motion-pulse 1.3s ease-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--motion-cone-animation: none;
--motion-pulse-animation: none;
opacity: 0.75;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -6px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--motion-cone-animation);
}
.shape::after {
animation: var(--motion-pulse-animation);
}
@keyframes ultra-motion-active {
0% { transform: scale(1); }
50% { transform: scale(1.06); }
100% { transform: scale(1); }
}
@keyframes ultra-motion-scan {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes ultra-motion-cone {
0% {
box-shadow:
0 -20px 14px -16px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
25% {
box-shadow:
8px -16px 14px -16px rgba(var(--rgb-{{ config.icon_color }}), 0.5);
}
50% {
box-shadow:
0 -20px 14px -12px rgba(var(--rgb-{{ config.icon_color }}), 0.8);
}
75% {
box-shadow:
-8px -16px 14px -16px rgba(var(--rgb-{{ config.icon_color }}), 0.5);
}
100% {
box-shadow:
0 -20px 14px -16px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
@keyframes ultra-motion-pulse {
0% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9),
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
40% {
box-shadow:
0 0 0 8px rgba(var(--rgb-{{ config.icon_color }}), 0.5),
0 0 0 14px rgba(var(--rgb-{{ config.icon_color }}), 0.2);
}
100% {
box-shadow:
0 0 0 22px rgba(var(--rgb-{{ config.icon_color }}), 0.0),
0 0 0 30px rgba(var(--rgb-{{ config.icon_color }}), 0.0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -18px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-light-card
entity: light.bedroom_lamp_local
use_light_color: true
show_color_temp_control: true
show_brightness_control: true
collapsible_controls: false
show_color_control: true
name: Lamp
icon_color: auto
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{% set state_entity = 'light.bedroom_lamp_local' %}
{% set active_value = 'on' %}
{# ====== TRIGGER ====== #}
{% set trigger_active = (states(state_entity) == active_value) %}
{# ====== COLOR FROM ENTITY (rgb_color) ====== #}
{% set rgb = state_attr(config.entity, 'rgb_color') %}
{% if rgb is not none %}
{% set r = (rgb[0] | int) %}
{% set g = (rgb[1] | int) %}
{% set b = (rgb[2] | int) %}
{% else %}
{# fallback if lamp has no rgb_color (ct-only, etc) #}
{% set r = 255 %}
{% set g = 240 %}
{% set b = 200 %}
{% endif %}
{% if trigger_active %}
--shape-animation: lamp-glow 1.4s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.5;
{% endif %}
}
@keyframes lamp-glow {
0% {
filter: brightness(1);
box-shadow: 0 0 6px 2px rgba({{ r }}, {{ g }}, {{ b }}, 0.6);
}
20% {
filter: brightness(1.25);
box-shadow: 0 0 14px 6px rgba({{ r }}, {{ g }}, {{ b }}, 0.9);
}
30% {
filter: brightness(0.9);
box-shadow: 0 0 3px 1px rgba({{ r }}, {{ g }}, {{ b }}, 0.4);
}
50% {
filter: brightness(1.3);
box-shadow: 0 0 16px 8px rgba({{ r }}, {{ g }}, {{ b }}, 1);
}
80% {
filter: brightness(1.05);
box-shadow: 0 0 8px 3px rgba({{ r }}, {{ g }}, {{ b }}, 0.7);
}
100% {
filter: brightness(1);
box-shadow: 0 0 6px 2px rgba({{ r }}, {{ g }}, {{ b }}, 0.6);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -22px 0px 0px -22px !important;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-cover-card
entity: cover.garage_door
show_buttons_control: true
show_position_control: true
show_tilt_position_control: true
fill_container: false
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========= COLOR CONFIG ========= #}
{% set cover_color = 'blue' %} {# change to 'red', 'blue', etc. #}
--cover-color-rgb: var(--rgb-{{ cover_color }});
{# ================================= #}
{# ========== USER CONFIG ========== #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'cover.garage_door' %}
{% set active_value = 'open' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.cover_position' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# =========== END TRIGGER LOGIC =========== #}
{% if trigger_active %}
--shape-animation: motion-active 1.4s linear infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.7;
{% endif %}
transform-origin: 50% 50%;
}
@keyframes motion-active {
0% {
transform: scale(1);
box-shadow:
0 0 0 0 rgba(var(--cover-color-rgb), 0.9),
0 0 0 0 rgba(var(--cover-color-rgb), 0.4);
}
40% {
transform: scale(1.06);
box-shadow:
0 0 0 6px rgba(var(--cover-color-rgb), 0.5),
0 0 0 12px rgba(var(--cover-color-rgb), 0.2);
}
100% {
transform: scale(1);
box-shadow:
0 0 0 16px rgba(var(--cover-color-rgb), 0.0),
0 0 0 24px rgba(var(--cover-color-rgb), 0.0);
}
}
@keyframes motion-scan {
0% {
transform: rotate(0deg);
box-shadow:
0 -10px 0 0 rgba(var(--cover-color-rgb), 0.9);
}
50% {
transform: rotate(180deg);
box-shadow:
0 10px 0 0 rgba(var(--cover-color-rgb), 0.6);
}
100% {
transform: rotate(360deg);
box-shadow:
0 -10px 0 0 rgba(var(--cover-color-rgb), 0.9);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -18px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-light-card
entity: light.livingroom_lamp_local
use_light_color: true
show_color_temp_control: true
show_brightness_control: true
collapsible_controls: false
show_color_control: true
name: Lamp
icon_color: auto
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{% set state_entity = 'light.livingroom_lamp_local' %}
{% set active_value = 'on' %}
{# ======== TRIGGER ======== #}
{% set trigger_active = (states(state_entity) == active_value) %}
{# ======== COLOR FROM ENTITY (rgb_color) ======== #}
{% set rgb = state_attr(config.entity, 'rgb_color') %}
{% if rgb is not none %}
{% set r = (rgb[0] | int) %}
{% set g = (rgb[1] | int) %}
{% set b = (rgb[2] | int) %}
{% else %}
{# fallback for CT-only lights #}
{% set r = 255 %}
{% set g = 240 %}
{% set b = 200 %}
{% endif %}
{% if trigger_active %}
--shape-animation: lamp-sweep 1.8s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
opacity: 0.5;
{% endif %}
position: relative;
transform-origin: 50% 60%;
}
@keyframes lamp-sweep {
0% {
filter: brightness(1.1);
box-shadow:
0 0 12px 4px rgba({{ r }}, {{ g }}, {{ b }}, 0.9),
0 30px 40px -10px rgba({{ r }}, {{ g }}, {{ b }}, 0.0);
transform: rotate(-4deg) scale(1);
}
25% {
filter: brightness(1.4);
box-shadow:
0 0 18px 8px rgba({{ r }}, {{ g }}, {{ b }}, 1),
-8px 35px 45px -12px rgba({{ r }}, {{ g }}, {{ b }}, 0.5);
transform: rotate(3deg) scale(1.02);
}
50% {
filter: brightness(1.2);
box-shadow:
0 0 24px 10px rgba({{ r }}, {{ g }}, {{ b }}, 0.9),
8px 35px 45px -12px rgba({{ r }}, {{ g }}, {{ b }}, 0.5);
transform: rotate(-2deg) scale(1.03);
}
75% {
filter: brightness(1.5);
box-shadow:
0 0 18px 8px rgba({{ r }}, {{ g }}, {{ b }}, 1),
-6px 30px 40px -12px rgba({{ r }}, {{ g }}, {{ b }}, 0.4);
transform: rotate(2deg) scale(1.01);
}
100% {
filter: brightness(1.1);
box-shadow:
0 0 12px 4px rgba({{ r }}, {{ g }}, {{ b }}, 0.8),
0 30px 40px -10px rgba({{ r }}, {{ g }}, {{ b }}, 0.0);
transform: rotate(-4deg) scale(1);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0px 0px -18px !important;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:controller
icon_color: purple
name: Console
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS (for "intensity") #}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ---------- TRIGGER DECISION LOGIC ---------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# ---------- END TRIGGER LOGIC ---------- #}
{# Optional intensity from power, just for shaping motion #}
{% set power = states(number_entity) | float(0) %}
{% set intensity = (power / 10) | float(0) %}
{% if intensity < 0.3 %}{% set intensity = 0.3 %}{% endif %}
{% if intensity > 1.6 %}{% set intensity = 1.6 %}{% endif %}
{% set px = (1.5 * intensity) | round(2) %}
{% set deg = (5.0 * intensity) | round(2) %}
{% if trigger_active %}
{# If use_number is off, it will just use this "active" path always when switch is on #}
--shape-animation: controller-rumble 0.5s ease-in-out infinite;
--controller-led-animation: controller-led 1.5s ease-in-out infinite;
--controller-trail-animation: controller-trail 1.2s ease-out infinite;
/* Huge RGB glow like your lock example */
--glow-1: 0 0 30px 10px rgba(var(--rgb-{{ config.icon_color }}), 1);
--glow-2: 0 0 70px 22px rgba(var(--rgb-{{ config.icon_color }}), 0.7);
--glow-3: 0 0 120px 42px rgba(var(--rgb-{{ config.icon_color }}), 0.5);
--glow-anim: controller-ultraglow 2.0s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--controller-led-animation: none;
--controller-trail-animation: none;
--glow-1: none;
--glow-2: none;
--glow-3: none;
--glow-anim: none;
opacity: 0.6;
{% endif %}
transform-origin: 50% 50%;
position: relative;
animation: var(--shape-animation);
}
/* Glow layers like the lock card */
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: -10px;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
box-shadow: var(--glow-1), var(--glow-2), var(--glow-3);
animation: var(--glow-anim);
}
.shape::after {
inset: -22px;
box-shadow:
0 0 130px 40px rgba(var(--rgb-{{ config.icon_color }}), 0.23),
0 0 190px 70px rgba(var(--rgb-{{ config.icon_color }}), 0.15);
opacity: 0.9;
animation: var(--glow-anim);
mix-blend-mode: screen;
}
@keyframes controller-ultraglow {
0% {
opacity: 0.9;
filter: brightness(1);
}
40% {
opacity: 1;
filter: brightness(1.4);
}
70% {
opacity: 1;
filter: brightness(1.2);
}
100% {
opacity: 0.9;
filter: brightness(1);
}
}
@keyframes controller-rumble {
0% { transform: translate(0, 0) rotate(0deg); }
25% { transform: translate(-2px, 1px) rotate(-3deg); }
50% { transform: translate(2px, -1px) rotate(3deg); }
75% { transform: translate(-1px, 2px) rotate(-1deg); }
100% { transform: translate(0, 0) rotate(0deg); }
}
@keyframes controller-led {
0% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 0 16px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.8));
}
33% {
box-shadow:
0 0 0 6px rgba(0, 210, 255, 0.5),
0 0 26px 6px rgba(0, 210, 255, 0.95);
filter: drop-shadow(0 0 5px rgba(0, 210, 255, 1));
}
66% {
box-shadow:
0 0 0 10px rgba(200, 110, 255, 0.5),
0 0 34px 10px rgba(200, 110, 255, 1);
filter: drop-shadow(0 0 6px rgba(200, 110, 255, 1));
}
100% {
box-shadow:
0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8),
0 0 16px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.9);
filter: drop-shadow(0 0 3px rgba(var(--rgb-{{ config.icon_color }}), 0.8));
}
}
@keyframes controller-trail {
0% {
box-shadow:
22px 0 22px -16px rgba(0, 255, 255, 0),
-22px 0 22px -16px rgba(255, 0, 200, 0);
}
25% {
box-shadow:
26px -4px 26px -14px rgba(0, 255, 255, 0.8),
-26px 4px 26px -14px rgba(255, 0, 200, 0.7);
}
55% {
box-shadow:
20px 4px 24px -14px rgba(0, 255, 160, 0.5),
-20px -4px 24px -14px rgba(255, 210, 0, 0.4);
}
100% {
box-shadow:
22px 0 22px -16px rgba(0, 255, 255, 0),
-22px 0 22px -16px rgba(255, 0, 200, 0);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 25px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:desktop-tower
icon_color: white
name: Gaming Rig
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. STATE CHECK #}
{% set is_on = states(state_entity) == active_value %}
{# 2. ANIMATION CHECK #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- STYLING --- */
{% if is_on %}
/* DEVICE IS ON */
{% if should_animate %}
/* High Power / Gaming Mode */
--fan-spin: rgb-fan 2s linear infinite;
--case-glow: neon-breathe 2s ease-in-out infinite alternate;
--shadow-layer:
0 0 15px 2px rgba(0, 255, 255, 0.6),
0 0 30px 10px rgba(255, 0, 255, 0.4);
--fan-display: block;
{% else %}
/* Idle / Low Power Mode */
--fan-spin: none;
--case-glow: none;
/* Subtle static glow indicating it is ON but idle */
--shadow-layer: 0 0 5px 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
--fan-display: none;
{% endif %}
{% else %}
/* DEVICE IS OFF - RESET TO DEFAULTS */
--fan-spin: none;
--case-glow: none;
--shadow-layer: none;
--fan-display: none;
{% endif %}
/* Boxy PC Case Shape */
border-radius: 10px !important;
position: relative;
overflow: hidden;
transform: translateZ(0);
/* Apply the shadow/glow only when ON */
box-shadow: var(--shadow-layer);
animation: var(--case-glow);
}
/* THE RGB FAN (Spinning Gradient Background) */
.shape::before {
content: '';
display: var(--fan-display); /* Hidden when OFF or Idle */
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: conic-gradient(
from 0deg,
#ff0000,
#ff8000,
#ffff00,
#00ff00,
#00ffff,
#0000ff,
#ff00ff,
#ff0000
);
opacity: 0.5;
animation: var(--fan-spin);
mix-blend-mode: screen;
}
/* THE GLASS PANEL REFLECTION (Static Shine) */
.shape::after {
content: '';
display: var(--fan-display); /* Hidden when OFF */
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.4) 0%, transparent 40%, transparent 100%);
pointer-events: none;
}
/* --- ANIMATIONS --- */
@keyframes rgb-fan {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes neon-breathe {
0% { box-shadow: 0 0 15px 2px rgba(0, 255, 255, 0.6), 0 0 30px 10px rgba(255, 0, 255, 0.4); }
100% { box-shadow: 0 0 25px 5px rgba(0, 255, 255, 0.8), 0 0 50px 20px rgba(255, 0, 255, 0.6); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -15px !important;
padding-right: 10px;
z-index: 1;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:desktop-tower
icon_color: white
name: PC
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# -------- TRIGGER DECISION LOGIC -------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set sensor_entity = state_entity %}
{% if states(sensor_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# ------ END TRIGGER DECISION LOGIC ------ #}
{% if trigger_active %}
/* 1. THE RGB CYCLE: Outer glow */
--gamer-glow: rgb-cycle 5s linear infinite;
/* 2. THE POWER LED: Blinking Yellow Light */
--power-led-anim: yellow-blink 0.5s steps(2, start) infinite;
--led-opacity: 1;
/* Show colors */
filter: grayscale(0%);
opacity: 1;
{% else %}
/* Stop Animations */
--gamer-glow: none;
--power-led-anim: none;
--led-opacity: 0;
/* Turn Gray/Monochrome */
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
/* FORCE SQUARE SHAPE for PC Case look */
border-radius: 12px !important;
position: relative;
transform: translateZ(0);
}
/* The RGB LED Strip Effect (Outer Glow) */
.shape::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
z-index: -1;
animation: var(--gamer-glow);
}
/* The Yellow Power Button LED */
.shape::after {
content: '';
position: absolute;
/* Positioning the dot to match mdi:desktop-tower power button location */
top: 75%;
right: 15%;
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #ffff; /* Bright Yellow */
box-shadow: 0 0 5px #ffeb3b; /* Yellow Glow */
opacity: var(--led-opacity);
animation: var(--power-led-anim);
}
/* --- ANIMATIONS --- */
/* RGB RAINBOW CYCLE */
@keyframes rgb-cycle {
0% {
box-shadow:
0 0 10px 2px rgba(255, 0, 0, 0.6), /* Red */
inset 0 0 15px rgba(255, 0, 0, 0.2);
}
25% {
box-shadow:
0 0 10px 2px rgba(255, 0, 255, 0.6), /* Purple */
inset 0 0 15px rgba(255, 0, 255, 0.2);
}
50% {
box-shadow:
0 0 10px 2px rgba(0, 0, 255, 0.6), /* Blue */
inset 0 0 15px rgba(0, 0, 255, 0.2);
}
75% {
box-shadow:
0 0 10px 2px rgba(0, 255, 255, 0.6), /* Cyan */
inset 0 0 15px rgba(0, 255, 255, 0.2);
}
100% {
box-shadow:
0 0 10px 2px rgba(255, 0, 0, 0.6), /* Back to Red */
inset 0 0 15px rgba(255, 0, 0, 0.2);
}
}
/* YELLOW LED BLINK */
@keyframes yellow-blink {
0% { opacity: 1; transform: scale(1); }
50% { opacity: 0.3; transform: scale(0.9); }
100% { opacity: 1; transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -15px !important;
padding-right: 10px;
z-index: 1;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:server-network
icon_color: blue
name: Home Server
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- APPLY STYLES --- */
/* ANIMATION TOGGLE */
{% if should_animate %}
/* 1. DISK I/O: Chaotic blinking lights */
--disk-activity: hdd-blink 0.5s steps(2, start) infinite;
/* 2. NETWORK LOAD: Heartbeat pulsing */
--server-throb: network-pulse 1.5s ease-in-out infinite;
{% else %}
--disk-activity: none;
--server-throb: none;
{% endif %}
/* STATE COLOR TOGGLE */
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
/* SQUARE SHAPE: Servers are boxes, not circles */
border-radius: 12px !important;
transform-origin: 50% 50%;
position: relative;
animation: var(--server-throb);
}
/* Activity LEDs (The blinking lights) */
.shape::before {
content: '';
position: absolute;
bottom: 25%;
right: 25%;
width: 6px;
height: 6px;
border-radius: 50%;
/* Create 3 "LEDs" using box-shadows to avoid multiple elements */
box-shadow:
10px 0 0 0 #00ff00,
0 10px 0 0 #ffaa00,
10px 10px 0 0 #00ff00;
opacity: 0;
animation: var(--disk-activity);
z-index: 2;
}
/* Network/Heat Glow (Background) */
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: radial-gradient(circle, rgba(var(--rgb-{{ config.icon_color }}), 0.5) 0%, transparent 70%);
opacity: 0;
animation: var(--server-throb);
z-index: 1;
}
/* --- ANIMATIONS --- */
/* Simulates HDD Activity LEDs flickering rapidly */
@keyframes hdd-blink {
0% { opacity: 0; }
25% { opacity: 1; }
50% { opacity: 0; }
75% { opacity: 1; }
90% { opacity: 0; }
100% { opacity: 1; }
}
/* Simulates Network Load / "Heartbeat" */
@keyframes network-pulse {
0% { transform: scale(1); opacity: 0.3; }
50% { transform: scale(1.03); opacity: 0.6; }
100% { transform: scale(1); opacity: 0.3; }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:nintendo-switch
icon_color: white
name: Nintendo Switch
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
{% if should_animate %}
--joycon-glow: neon-split-big 0.5s ease-in-out infinite alternate;
--switch-rumble: haptic-shake 0.4s linear infinite;
{% else %}
--joycon-glow: none;
--switch-rumble: none;
{% endif %}
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
transform-origin: 50% 50%;
position: relative;
overflow: visible !important;
animation: var(--switch-rumble);
}
/* HUGE expanded glow */
.shape::before {
content: "";
position: absolute;
inset: -10px;
border-radius: inherit;
z-index: -1;
animation: var(--joycon-glow);
}
/* MASSIVE dual-color neon */
@keyframes neon-split-big {
0% {
box-shadow:
/* Left red side (3-layer bloom) */
-6px 0 12px rgba(255, 20, 20, 0.5),
-12px 0 24px rgba(255, 20, 20, 0.35),
-18px 0 36px rgba(255, 20, 20, 0.20),
/* Right blue side (3-layer bloom) */
6px 0 12px rgba(0, 200, 255, 0.5),
12px 0 24px rgba(0, 200, 255, 0.35),
18px 0 36px rgba(0, 200, 255, 0.20);
}
100% {
box-shadow:
/* Left — super intense bloom */
-12px 0 24px rgba(255, 20, 20, 0.9),
-24px 0 40px rgba(255, 20, 20, 0.65),
-32px 0 60px rgba(255, 20, 20, 0.40),
/* Right — super intense bloom */
12px 0 24px rgba(0, 200, 255, 0.9),
24px 0 40px rgba(0, 200, 255, 0.65),
32px 0 60px rgba(0, 200, 255, 0.40);
}
}
/* Rumble effect stays unchanged */
@keyframes haptic-shake {
0% { transform: translate(0, 0) rotate(0deg); }
25% { transform: translate(-1px, 1px) rotate(-1deg); }
50% { transform: translate(1px, -1px) rotate(1deg); }
75% { transform: translate(-1px, -1px) rotate(0deg); }
100% { transform: translate(0, 0) rotate(0deg); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display:flex;
margin: -17px 0 10px -15px !important;
padding-right: 15px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius,12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:printer
icon_color: amber
name: Printer
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- APPLY STYLES --- */
/* ANIMATION TOGGLE */
{% if should_animate %}
/* 1. SHAKE: Simulates mechanical printing vibration */
--printer-shake: printer-vibrate 0.2s linear infinite;
/* 2. SCAN: A laser/copier light bar moving down */
--scan-beam: scanner-light 1.5s ease-in-out infinite;
/* 3. LED: Status light pulsing */
--status-led: led-blink 1s infinite alternate;
{% else %}
--printer-shake: none;
--scan-beam: none;
--status-led: none;
{% endif %}
/* STATE COLOR TOGGLE */
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
transform-origin: 50% 50%;
position: relative;
overflow: hidden; /* Keeps the scan beam inside the circle shape */
/* Apply the mechanical shake to the whole icon */
animation: var(--printer-shake);
}
/* The Scanning Light Beam */
.shape::before {
content: '';
position: absolute;
left: 0;
right: 0;
height: 30%; /* Height of the beam */
background: linear-gradient(to bottom,
transparent 0%,
rgba(255, 255, 255, 0.8) 50%,
transparent 100%);
top: -50%;
animation: var(--scan-beam);
pointer-events: none;
mix-blend-mode: overlay;
}
/* The Status LED (Green/Yellow dot) */
.shape::after {
content: '';
position: absolute;
bottom: 15%;
right: 15%;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #00ff00; /* Green LED */
box-shadow: 0 0 5px #00ff00;
opacity: 0; /* Hidden by default unless animating */
animation: var(--status-led);
}
/* --- ANIMATIONS --- */
/* Mechanical Shake */
@keyframes printer-vibrate {
0% { transform: translate(0, 0); }
25% { transform: translate(-1px, 1px); }
50% { transform: translate(1px, -1px); }
75% { transform: translate(-1px, -1px); }
100% { transform: translate(0, 0); }
}
/* Scanner Bar Movement */
@keyframes scanner-light {
0% { top: -40%; opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { top: 120%; opacity: 0; }
}
/* Status LED Blinking */
@keyframes led-blink {
0% { opacity: 0; transform: scale(0.8); }
100% { opacity: 1; transform: scale(1.2); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:air-purifier
icon_color: light-blue
name: Air Purifier
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{# If not using number, animate whenever ON #}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- APPLY STYLES --- */
/* ANIMATION TOGGLE */
{% if should_animate %}
/* 1. RIPPLE: Represents clean air spreading out */
--air-flow: clean-air-ripple 2s infinite ease-out;
/* 2. BREATH: Represents the intake motor humming */
--core-breath: motor-breath 3s ease-in-out infinite;
{% else %}
--air-flow: none;
--core-breath: none;
{% endif %}
/* STATE COLOR TOGGLE */
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
{% endif %}
transform-origin: 50% 50%;
position: relative;
/* Ensure the ripple is visible outside the shape */
overflow: visible !important;
/* Apply the breathing animation to the main shape */
animation: var(--core-breath);
}
/* Inner Ripple (Fast) */
.shape::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
animation: var(--air-flow);
z-index: -1;
}
/* Outer Ripple (Delayed, Slower) */
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: rgba(var(--rgb-{{ config.icon_color }}), 0.1);
animation: var(--air-flow);
animation-duration: 3s; /* Slower expansion */
animation-delay: 0.5s;
z-index: -2;
}
/* --- ANIMATIONS --- */
/* Expanding Rings representing Airflow */
@keyframes clean-air-ripple {
0% {
transform: scale(1);
opacity: 0.8;
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
100% {
transform: scale(2.5);
opacity: 0;
box-shadow: 0 0 20px 20px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
/* Gentle "Humming" motion of the device */
@keyframes motor-breath {
0% { transform: scale(1); }
50% { transform: scale(0.95); opacity: 0.9; }
100% { transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -20px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:clock-digital
icon_color: cyan
name: Awtrix Clock
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. CHECK STATE (For Color) #}
{% set is_on = states(state_entity) == active_value %}
{# 2. CHECK ANIMATION LOGIC #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- APPLY STYLES --- */
/* ANIMATION TOGGLE */
{% if should_animate %}
/* 1. SCROLLER: Simulates text/rainbows scrolling across */
--matrix-scroll: pixel-scroll 1.5s linear infinite;
/* 2. REFRESH RATE: Subtle 60hz flicker simulation */
--matrix-flicker: refresh-flicker 0.1s steps(2) infinite;
{% else %}
--matrix-scroll: none;
/* Idle breathing when ON but not active */
--matrix-flicker: idle-breathe 4s ease-in-out infinite;
{% endif %}
/* STATE COLOR TOGGLE */
{% if is_on %}
filter: grayscale(0%);
opacity: 1;
{% else %}
filter: grayscale(100%);
opacity: 0.4;
--matrix-flicker: none; /* No breathing when off */
{% endif %}
/* THE MATRIX SHAPE */
border-radius: 8px !important; /* Slightly rounded corners like Ulanzi case */
transform-origin: 50% 50%;
position: relative;
overflow: hidden;
/* Apply the grid pattern directly to the shape background */
background-image:
linear-gradient(rgba(0,0,0,0.2) 1px, transparent 1px),
linear-gradient(90deg, rgba(0,0,0,0.2) 1px, transparent 1px) !important;
background-size: 4px 4px !important; /* Creates the "Pixel" look */
animation: var(--matrix-flicker);
}
/* The Scrolling Marquee / Notification Light */
.shape::before {
content: '';
position: absolute;
top: 0;
left: -100%; /* Start off screen */
width: 100%;
height: 100%;
/* Rainbow Gradient Bar */
background: linear-gradient(90deg,
transparent 0%,
rgba(255, 0, 0, 0.6) 20%,
rgba(255, 255, 0, 0.6) 40%,
rgba(0, 255, 0, 0.6) 60%,
rgba(0, 255, 255, 0.6) 80%,
transparent 100%
);
mix-blend-mode: color-dodge;
animation: var(--matrix-scroll);
}
/* CRT/LED Scanline Glare */
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: linear-gradient(rgba(255,255,255,0.1) 50%, rgba(0,0,0,0.1) 50%);
background-size: 100% 4px;
pointer-events: none;
z-index: 2;
}
/* --- ANIMATIONS --- */
/* Simulates text/colors scrolling left to right */
@keyframes pixel-scroll {
0% { left: -100%; }
100% { left: 100%; }
}
/* Simulates the subtle refresh rate of LED matrices */
@keyframes refresh-flicker {
0% { opacity: 1; }
100% { opacity: 0.95; }
}
/* Standby breathing */
@keyframes idle-breathe {
0% { filter: brightness(1); }
50% { filter: brightness(1.2); }
100% { filter: brightness(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -15px 0 10px -15px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fridge-industrial
icon_color: white
name: Freezer / Refrigerator
card_mod:
style:
.: |
ha-card {
/* ================= USER CONFIGURATION ================= */
{% set use_number = false %}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
/* ====================================================== */
/* --- LOGIC ENGINE (Do not edit) --- */
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %} {% set active = (num > threshold) %}
{% elif number_operator == '<' %} {% set active = (num < threshold) %}
{% elif number_operator == '=' %} {% set active = (num == threshold) %}
{% elif number_operator == '>=' %} {% set active = (num >= threshold) %}
{% elif number_operator == '<=' %} {% set active = (num <= threshold) %}
{% else %} {% set active = false %} {% endif %}
{% else %}
{% set active = states(state_entity) == active_value %}
{% endif %}
/* --- DEFINE VARIABLES BASED ON STATE --- */
/* These variables are passed down to the icon and used here */
/* Card Styles */
--card-bg: {{ 'linear-gradient(to bottom, #2C5364, #203A43, #0F2027)' if active else 'var(--ha-card-background, var(--card-background-color, white))' }};
--card-shadow: {{ 'inset 0 0 30px rgba(200, 255, 255, 0.6)' if active else 'var(--ha-card-box-shadow, none)' }};
/* Snow Visibility */
--snow-display: {{ 'block' if active else 'none' }};
/* Text Colors */
--primary-text-color: {{ '#e0f7fa' if active else 'var(--primary-text-color)' }};
--secondary-text-color: {{ '#b2ebf2' if active else 'var(--secondary-text-color)' }};
/* Icon Animations (Passed to Shadow DOM) */
--custom-icon-anim: {{ 'compressor-rumble 0.2s linear infinite' if active else 'none' }};
--custom-icon-shadow: {{ '0 0 25px 5px rgba(255, 255, 255, 0.6)' if active else 'none' }};
/* --- APPLY STYLES --- */
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius,12px));
background: var(--card-bg) !important;
box-shadow: var(--card-shadow) !important;
border-radius: 12px;
position: relative;
overflow: hidden;
transition: all 0.5s ease;
}
/* --- LAYER 1: HEAVY FLAKES (Slow) --- */
ha-card::before {
content: '';
display: var(--snow-display);
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 20px 30px, white 2px, transparent 3px),
radial-gradient(circle at 50px 160px, white 2px, transparent 3px),
radial-gradient(circle at 90px 40px, white 2px, transparent 3px),
radial-gradient(circle at 130px 80px, white 2px, transparent 3px),
radial-gradient(circle at 160px 120px, white 2px, transparent 3px),
radial-gradient(circle at 240px 300px, white 2px, transparent 3px),
radial-gradient(circle at 280px 100px, white 2px, transparent 3px);
background-size: 300px 400px;
background-repeat: repeat;
animation: snow-fall-layer1 10s linear infinite;
opacity: 0.9;
pointer-events: none;
z-index: 0;
}
/* --- LAYER 2: FINE BLIZZARD (Fast) --- */
ha-card::after {
content: '';
display: var(--snow-display);
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 10px 10px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 30px 90px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 80px 50px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 110px 190px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 150px 100px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 220px 250px, rgba(255,255,255,0.7) 1px, transparent 2px);
background-size: 300px 300px;
animation: snow-fall-layer2 5s linear infinite;
opacity: 0.6;
pointer-events: none;
z-index: 0;
}
/* Fix icon z-index */
mushroom-shape-icon {
--icon-size: 65px;
display:flex;
margin: -18px 0 10px -18px !important;
padding-right: 15px;
}
.mushroom-state-info {
position: relative;
z-index: 1;
}
/* --- SEAMLESS FALLING ANIMATIONS --- */
@keyframes snow-fall-layer1 {
from { background-position: 0 0; }
to { background-position: 0 400px; }
}
@keyframes snow-fall-layer2 {
from { background-position: 0 0; }
to { background-position: 0 300px; }
}
mushroom-shape-icon$: |
.shape {
--shape-animation: var(--custom-icon-anim) !important;
##box-shadow: var(--custom-icon-shadow) !important;
opacity: 1;
overflow: visible !important;
}
/* Define the Keyframe for the icon here */
@keyframes compressor-rumble {
0% { transform: translate(0, 0); }
25% { transform: translate(-1px, 0.5px); }
50% { transform: translate(1px, -0.5px); }
75% { transform: translate(-0.5px, 0.5px); }
100% { transform: translate(0, 0); }
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:fridge-industrial
icon_color: white
name: Freezer / Refrigerator
card_mod:
style:
.: |
ha-card {
/* ================= USER CONFIGURATION ================= */
{% set use_number = false %}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{% set number_entity = 'sensor.plug_power' %}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
/* ====================================================== */
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %} {% set active = (num > threshold) %}
{% elif number_operator == '<' %} {% set active = (num < threshold) %}
{% elif number_operator == '=' %} {% set active = (num == threshold) %}
{% elif number_operator == '>=' %} {% set active = (num >= threshold) %}
{% elif number_operator == '<=' %} {% set active = (num <= threshold) %}
{% else %} {% set active = false %} {% endif %}
{% else %}
{% set active = states(state_entity) == active_value %}
{% endif %}
--card-bg: var(--ha-card-background, var(--card-background-color, transparent));
--card-shadow: {{ 'inset 0 0 30px rgba(200, 255, 255, 0.6)' if active else 'var(--ha-card-box-shadow, none)' }};
--snow-display: {{ 'block' if active else 'none' }};
--primary-text-color: {{ '#e0f7fa' if active else 'var(--primary-text-color)' }};
--secondary-text-color: {{ '#b2ebf2' if active else 'var(--secondary-text-color)' }};
--custom-icon-anim: {{ 'compressor-rumble 0.2s linear infinite' if active else 'none' }};
--custom-icon-shadow: {{ '0 0 25px 5px rgba(255, 255, 255, 0.6)' if active else 'none' }};
background: transparent !important;
box-shadow: var(--card-shadow) !important;
border-radius: var(--ha-card-border-radius, 12px);
position: relative;
overflow: hidden;
transition: all 0.5s ease;
isolation: isolate;
}
ha-card::before {
content: '';
display: var(--snow-display);
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 20px 30px, white 2px, transparent 3px),
radial-gradient(circle at 50px 160px, white 2px, transparent 3px),
radial-gradient(circle at 90px 40px, white 2px, transparent 3px),
radial-gradient(circle at 130px 80px, white 2px, transparent 3px),
radial-gradient(circle at 160px 120px, white 2px, transparent 3px),
radial-gradient(circle at 240px 300px, white 2px, transparent 3px),
radial-gradient(circle at 280px 100px, white 2px, transparent 3px);
background-size: 300px 400px;
background-repeat: repeat;
animation: snow-fall-layer1 10s linear infinite;
opacity: 0.9;
pointer-events: none;
z-index: -1;
}
ha-card::after {
content: '';
display: var(--snow-display);
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 10px 10px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 30px 90px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 80px 50px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 110px 190px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 150px 100px, rgba(255,255,255,0.7) 1px, transparent 2px),
radial-gradient(circle at 220px 250px, rgba(255,255,255,0.7) 1px, transparent 2px);
background-size: 300px 300px;
animation: snow-fall-layer2 5s linear infinite;
opacity: 0.6;
pointer-events: none;
z-index: -1;
}
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -18px !important;
padding-right: 15px;
}
.mushroom-state-info {
position: relative;
z-index: 1;
}
@keyframes snow-fall-layer1 {
from { background-position: 0 0; }
to { background-position: 0 400px; }
}
@keyframes snow-fall-layer2 {
from { background-position: 0 0; }
to { background-position: 0 300px; }
}
mushroom-shape-icon$: |
.shape {
--shape-animation: var(--custom-icon-anim) !important;
box-shadow: var(--custom-icon-shadow) !important;
opacity: 1;
overflow: visible !important;
}
@keyframes compressor-rumble {
0% { transform: translate(0, 0); }
25% { transform: translate(-1px, 0.5px); }
50% { transform: translate(1px, -0.5px); }
75% { transform: translate(-0.5px, 0.5px); }
100% { transform: translate(0, 0); }
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:vibrate
icon_color: red
name: Vibration
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# -------- TRIGGER DECISION LOGIC -------- #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set sensor_entity = state_entity %}
{% if states(sensor_entity) == active_value %}
{% set trigger_active = true %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% endif %}
{# ------ END TRIGGER DECISION LOGIC ------ #}
{% if trigger_active %}
--shape-animation: disposal-shake 0.5s linear infinite;
--warp-animation: disposal-shockwave 0.8s ease-out infinite;
--stream-animation: disposal-pulse 1.5s ease-in-out infinite;
opacity: 1;
{% else %}
--shape-animation: none;
--warp-animation: none;
--stream-animation: none;
opacity: 1;
{% endif %}
transform-origin: 50% 50%;
position: relative;
}
.shape::before,
.shape::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.shape::before {
animation: var(--warp-animation);
}
.shape::after {
mix-blend-mode: overlay;
animation: var(--stream-animation);
}
/* THE SHAKE: Rapid movement to simulate heavy grinding motor */
@keyframes disposal-shake {
0% { transform: translate(1px, 1px) rotate(0deg); }
10% { transform: translate(-1px, -2px) rotate(-1deg); }
20% { transform: translate(-3px, 0px) rotate(1deg); }
30% { transform: translate(3px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(1deg); }
50% { transform: translate(-1px, 2px) rotate(-1deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(3px, 1px) rotate(-1deg); }
80% { transform: translate(-1px, -1px) rotate(1deg); }
90% { transform: translate(1px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-1deg); }
}
/* THE SHOCKWAVE: Fast, aggressive expansion */
@keyframes disposal-shockwave {
0% {
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.8);
}
70% {
box-shadow: 0 0 0 15px rgba(var(--rgb-{{ config.icon_color }}), 0);
}
100% {
box-shadow: 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0);
}
}
/* THE PULSE: Secondary glow to add "heat" to the look */
@keyframes disposal-pulse {
0% {
box-shadow: inset 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
50% {
box-shadow: inset 0 0 10px 4px rgba(var(--rgb-{{ config.icon_color }}), 0.1);
}
100% {
box-shadow: inset 0 0 0 0 rgba(var(--rgb-{{ config.icon_color }}), 0.4);
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -18px 0 10px -18px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:pump
icon_color: blue
name: Water Pump
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{# true = number mode, false = state mode #}
{% set use_number = false %}
{# STATE MODE SETTINGS #}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{# OPTIONAL: NUMBER MODE SETTINGS #}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# 1. STATE CHECK #}
{% set is_on = states(state_entity) == active_value %}
{# 2. ANIMATION CHECK #}
{% set should_animate = false %}
{% if is_on %}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set should_animate = (num > threshold) %}
{% elif number_operator == '<' %}
{% set should_animate = (num < threshold) %}
{% elif number_operator == '=' %}
{% set should_animate = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set should_animate = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set should_animate = (num <= threshold) %}
{% endif %}
{% else %}
{% set should_animate = true %}
{% endif %}
{% endif %}
/* --- STYLING --- */
{% if is_on %}
/* DEVICE IS ON */
{% if should_animate %}
/* ACTIVELY PUMPING */
/* 1. Internal Impeller Spin */
--impeller-spin: hydro-spin 0.8s linear infinite;
/* 2. Motor Vibration */
--pump-rumble: motor-shake 0.1s ease-in-out infinite alternate;
/* 3. Water Pressure Waves */
--pressure-flow: flow-ripple 1.5s ease-out infinite;
--effect-display: block;
{% else %}
/* IDLE (Water present but not moving) */
--impeller-spin: none;
--pump-rumble: none;
--pressure-flow: none;
--effect-display: none;
{% endif %}
{% else %}
/* DEVICE IS OFF */
--impeller-spin: none;
--pump-rumble: none;
--pressure-flow: none;
--effect-display: none;
{% endif %}
border-radius: 50%;
position: relative;
overflow: visible !important;
transform: translateZ(0);
/* Shake the housing */
animation: var(--pump-rumble);
}
/* THE INTERNAL IMPELLER (Spinning Gradient) */
.shape::before {
content: '';
display: var(--effect-display);
position: absolute;
inset: 0;
border-radius: 50%;
/* Creates a spinning "fan blade" look inside the color */
background: conic-gradient(
from 0deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.4) 25%,
rgba(255, 255, 255, 0) 50%,
rgba(255, 255, 255, 0.4) 75%,
rgba(255, 255, 255, 0) 100%
);
animation: var(--impeller-spin);
mix-blend-mode: overlay;
z-index: 1; /* Inside the shape */
}
/* THE PRESSURE WAVES (Outer flow) */
.shape::after {
content: '';
display: var(--effect-display);
position: absolute;
inset: 0;
border-radius: 50%;
border: 2px solid rgba(var(--rgb-{{ config.icon_color }}), 0.6);
opacity: 0;
animation: var(--pressure-flow);
z-index: -1; /* Outside the shape */
}
/* --- ANIMATIONS --- */
/* Rapid Impeller Rotation */
@keyframes hydro-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* High-frequency mechanical vibration */
@keyframes motor-shake {
0% { transform: translate(0.5px, 0.5px); }
100% { transform: translate(-0.5px, -0.5px); }
}
/* Expanding Water Ripples */
@keyframes flow-ripple {
0% {
transform: scale(1);
opacity: 0.8;
border-width: 4px;
}
100% {
transform: scale(1.6);
opacity: 0;
border-width: 0px;
}
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -17px 0 10px -17px !important;
padding-right: 10px;
z-index: 1;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: switch.plug_6_local
tap_action:
action: toggle
icon: mdi:washing-machine
icon_color: blue
name: Washing Machine
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{# ========== USER CONFIG ========== #}
{% set use_number = false %}
{% set state_entity = 'switch.plug_6_local' %}
{% set active_value = 'on' %}
{% set number_entity = 'sensor.plug_power' %}
{# '>' '<' '=' '>=' '<=' #}
{% set number_operator = '>' %}
{% set threshold = 0.0 %}
{# ========== END USER CONFIG ====== #}
{# ======== TRIGGER DECISION LOGIC ======== #}
{% if use_number %}
{% set num = states(number_entity) | float(0) %}
{% if number_operator == '>' %}
{% set trigger_active = (num > threshold) %}
{% elif number_operator == '<' %}
{% set trigger_active = (num < threshold) %}
{% elif number_operator == '=' %}
{% set trigger_active = (num == threshold) %}
{% elif number_operator == '>=' %}
{% set trigger_active = (num >= threshold) %}
{% elif number_operator == '<=' %}
{% set trigger_active = (num <= threshold) %}
{% else %}
{% set trigger_active = false %}
{% endif %}
{% else %}
{% set trigger_active = (states(state_entity) == active_value) %}
{% endif %}
{# Logic for Animations #}
{% if trigger_active %}
opacity: 1;
--wash-glow: ultra-wash-glow 1.8s ease-in-out infinite;
--wash-drum: spin-laundry 0.6s cubic-bezier(0.4, 0.0, 0.2, 1) infinite;
/* Added the 'thump' to match the intense style of the plug example */
animation: ultra-wash-thump 1.8s ease-in-out infinite;
{% else %}
opacity: 0.8;
--wash-glow: none;
--wash-drum: none;
animation: none;
{% endif %}
isolation: isolate;
position: relative;
}
/* LAYER 3 (Top): The Icon Frame */
.shape ha-icon {
z-index: 10;
position: relative;
display: block;
}
/* LAYER 2 (Middle): The Spinning Drum Illusion */
.shape::after {
content: "";
position: absolute;
top: 58%;
left: 50%;
width: 24px;
height: 24px;
border-radius: 50%;
z-index: 2;
/* The "Wet Clothes" Texture */
background: conic-gradient(
from 0deg,
transparent 0deg,
var(--icon-color) 40deg,
transparent 100deg,
var(--icon-color) 160deg,
var(--icon-color) 200deg,
transparent 280deg,
var(--icon-color) 320deg
);
filter: blur(0.8px);
opacity: 0.7;
/* Apply Animation */
animation: var(--wash-drum);
/* Hide if not active */
{% if not trigger_active %}
display: none;
{% endif %}
}
/* LAYER 1 (Bottom): The ULTRA Glow */
.shape::before {
content: '';
position: absolute;
inset: -4px; /* Expand glow slightly outside */
border-radius: 50%;
z-index: 1;
animation: var(--wash-glow);
}
/* === ANIMATIONS === */
@keyframes spin-laundry {
0% { transform: translate(-50%, -50%) rotate(0deg); }
100% { transform: translate(-50%, -50%) rotate(360deg); }
}
/* THE REQUESTED ULTRA GLOW (Double Shadow Layer) */
@keyframes ultra-wash-glow {
0% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-blue), 0.6),
0 0 20px 8px rgba(var(--rgb-blue), 0.3);
}
50% {
box-shadow:
0 0 18px 6px rgba(var(--rgb-blue), 0.9),
0 0 32px 12px rgba(var(--rgb-blue), 0.4);
}
100% {
box-shadow:
0 0 10px 3px rgba(var(--rgb-blue), 0.6),
0 0 20px 8px rgba(var(--rgb-blue), 0.3);
}
}
/* THUMP ANIMATION (Matches the plug scale effect) */
@keyframes ultra-wash-thump {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.: |
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -16px 0 10px -16px !important;
padding-right: 10px;
}
ha-card {
clip-path: inset(0 0 0 0 round var(--ha-card-border-radius, 12px));
}
type: custom:mushroom-entity-card
entity: sensor.3d_printer_progress
tap_action:
action: more-info
icon: mdi:printer-3d-nozzle
icon_color: purple
name: 3D Printer
hold_action:
action: none
double_tap_action:
action: none
card_mod:
style:
.: |
ha-card {
/* ================= USER SETTINGS ================= */
{% set max_val = 100 %}
/* ================================================= */
/* --- LOGIC --- */
{% set val = states(config.entity) | float(0) %}
{% set active = val > 0 and val < max_val %}
{% set is_done = val >= max_val %}
/* Calculate Percentage Width */
{% set width_pct = (val / max_val * 100) | round(2) %}
{% if width_pct > 100 %}{% set width_pct = 100 %}{% endif %}
/* --- CSS VARIABLES --- */
--bar-width: {{ width_pct }}%;
--bar-opacity: {{ 1 if active else 0 }};
--done-opacity: {{ 1 if is_done else 0 }};
/* Icon Variables */
--custom-icon-anim: {{ 'printer-sequence 2.3s linear infinite' if active else 'none' }};
--custom-icon-shadow: {{ '0 0 10px 5px rgba(var(--rgb-' ~ config.icon_color ~ '), 0.6)' if active else 'none' }};
--custom-icon-opacity: {{ '1' if active else '1' }};
/* --- CARD STYLING LOGIC --- */
/* Only apply the dark custom background if ACTIVE. Otherwise, use default theme. */
{% if active %}
background-color: #1c1c1c !important;
border: none !important;
/* Ambient Glow */
background-image: radial-gradient(circle at 24px 24px, rgba(var(--rgb-{{ config.icon_color }}), 0.35) 0%, rgba(var(--rgb-{{ config.icon_color }}), 0.1) 40%, transparent 80%),
linear-gradient(to right, rgba(255,255,255,0.1), rgba(255,255,255,0.1)) !important;
{% else %}
/* When Done/Idle: Reset to defaults (no custom BG color, standard border behavior if any) */
background-image: none !important;
box-shadow: none !important;
/* We don't set background-color here, letting the theme take over */
{% endif %}
border-radius: 12px;
position: relative;
overflow: hidden;
transition: all 0.5s ease;
background-size: 100% 100%, 100% 6px !important;
background-position: top left, bottom left !important;
background-repeat: no-repeat !important;
}
/* --- THE "DONE" BADGE --- */
ha-card::before {
content: 'DONE';
position: absolute;
top: 12px;
right: 12px;
font-size: 10px;
font-weight: 900;
letter-spacing: 1px;
color: #00ff00;
background: rgba(0, 255, 0, 0.15);
border: 1px solid rgba(0, 255, 0, 0.5);
padding: 2px 6px;
border-radius: 4px;
box-shadow: 0 0 10px rgba(0, 255, 0, 0.2);
opacity: var(--done-opacity);
transform: scale(var(--done-opacity));
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
pointer-events: none; /* Let clicks pass through */
}
/* --- ACTIVE PROGRESS BAR (BEAM) --- */
ha-card::after {
content: '';
position: absolute;
bottom: 0; left: 0;
height: 6px;
width: var(--bar-width);
background: linear-gradient(90deg,
rgba(var(--rgb-{{ config.icon_color }}), 0.4) 0%,
rgba(var(--rgb-{{ config.icon_color }}), 1) 100%
);
box-shadow: 0 -2px 10px rgba(var(--rgb-{{ config.icon_color }}), 0.8);
opacity: var(--bar-opacity);
transition: width 0.5s ease-out, opacity 0.5s ease;
animation: bar-flow 2s infinite linear;
pointer-events: none;
}
@keyframes bar-flow {
0% { filter: brightness(1); }
50% { filter: brightness(1.3); }
100% { filter: brightness(1); }
}
mushroom-shape-icon {
--icon-size: 65px;
display: flex;
margin: -20px 0 10px -20px !important;
padding-right: 15px;
padding-bottom: 15px;
}
mushroom-shape-icon$: |
.shape {
--shape-animation: var(--custom-icon-anim) !important;
box-shadow: var(--custom-icon-shadow) !important;
opacity: var(--custom-icon-opacity) !important;
transform-origin: 50% 80%;
}
@keyframes printer-sequence {
0% { transform: translate(-5px, 4px) scale(0.96); }
15% { transform: translate(5px, 4px) scale(0.96); }
16% { transform: translate(5px, 2px) scale(0.98); }
30% { transform: translate(-5px, 2px) scale(0.98); }
31% { transform: translate(-5px, 0px) scale(1); }
45% { transform: translate(5px, 0px) scale(1); }
46% { transform: translate(5px, -2px) scale(1.02); }
60% { transform: translate(-5px, -2px) scale(1.02); }
61% { transform: translate(-5px, -4px) scale(1.04); }
80% { transform: translate(5px, -4px) scale(1.04); }
100% { transform: translate(-5px, 4px) scale(0.96); }
}
type: custom:mushroom-entity-card
entity: binary_sensor.contact_front_door_contact
tap_action:
action: more-info
icon: mdi:door
name: Contact (Door)
icon_color: red
primary_info: state
secondary_info: name
card_mod:
style:
mushroom-shape-icon$: |
.shape {
{% set is_open = is_state(config.entity, 'on') %}
/* LOGIC: Define colors and animations based on state */
{% if is_open %}
/* OPEN: Red, Dark Red Shape, Animated */
--icon-color-set: rgb(244, 67, 54);
--shape-color-set: rgba(160, 0, 0, 0.15);
--shape-animation: door-soft-open 1.7s ease-in-out infinite;
/* Increased duration slightly for smoother persistent glow */
--glow-animation: door-soft-glow 2.5s ease-in-out infinite;
--beam-animation: door-soft-beam 2.5s ease-in-out infinite;
--icon-filter: drop-shadow(0 0 6px rgba(160, 0, 0, 0.95));
{% else %}
/* CLOSED: Green, Dark Green Shape, Static */
--icon-color-set: rgb(76, 175, 80);
--shape-color-set: rgba(0, 80, 0, 0.4);
--shape-animation: none;
--glow-animation: none;
--beam-animation: none;
--icon-filter: none;
{% endif %}
/* Apply the variable colors defined above */
background-color: var(--shape-color-set) !important;
/* Standard positioning */
position: relative;
transform-origin: 25% 50%;
animation: var(--shape-animation);
}
/* Color and Filter for the Icon itself */
.shape ha-icon {
color: var(--icon-color-set) !important;
filter: var(--icon-filter);
}
/* --- ANIMATION LAYERS --- */
.shape::before,
.shape::after {
content: '';
position: absolu
Truncated — view the full README on GitHub.
82 followers · starred Jul 2026
218 followers · starred Mar 2026