Files
HA-Animated-cards/appliances.md

74 KiB

Revolut.Me PayPal.Me ko_fi buymecoffee patreon

< 🏠 Back to Main Repository

Home Assistant Animated Appliances Cards

  • Dishwasher

  • Washing Machine

  • Dryer

  • Combo Washer & Dryer

This YouTube Video explains how to do it.

dish-washer2

Loading image... please wait


Cards:

1 - Smart Dishwasher
type: custom:mushroom-entity-card
entity: sensor.dishwasher_status
name: Smart Dishwasher
icon: mdi:dishwasher
primary_info: name
secondary_info: state
tap_action:
  action: more-info
icon_color: light-grey
fill_container: false
card_mod:
  style:
    .: |
      ha-card {
        /* ======================== */
        /* USER CONFIGURATION       */
        /* ======================== */
        
        /* 1. ENTITIES */
        {% set ent_progress  = 'sensor.dishwasher_progress' %}
        {% set ent_timerem   = 'sensor.dishwasher_time_remaining' %}
        {% set max_time = 120 %}
        {% set ent_power     = 'sensor.smart_plug_power' %} 
        
        /* OPTIONAL Progress Percentage Sensor (if exists) */
        {% set ent_percent   = 'sensor.dishwasher_progress_percentage' %}

        /* 2. SIZES (Px) */
        --config-icon-size:       65px;
        --config-font-primary:    15px;
        --config-font-secondary:  12px;
        --config-font-badge:      12px;
        /* ======================== */

        /* --- SENSORS & TIME --- */
        {% set status = states(ent_progress) %}
        {% set status_clean = status | replace('-', ' ') | title %}
        {% set time_rem = states(ent_timerem) | int(0) %}
        {% set raw_percent = states(ent_percent) | float(-1) %}
        
        /* --- POWER CALCULATION --- */
        {% set power_w = states(ent_power) | float(0) | round %}
        {% set power_text = ' • ' ~ power_w ~ 'W' if power_w > 0 else '' %}

        /* Format Time (min -> Xh Ym) */
        {% set hours = (time_rem / 60) | int %}
        {% set mins = time_rem % 60 %}
        {% set time_formatted = '%dh %02dm' | format(hours, mins) %}

        /* --- PROGRESS CALCULATION --- */
        {% if status | lower in ['idle', 'off', 'standby', 'unknown', 'unavailable'] %}
           {% set progress = 0 %}
           {% set badge_text = status_clean ~ power_text %}
        {% else %}
           
           /* LOGIC: Use Sensor if available, otherwise Calculate */
           {% if raw_percent >= 0 %}
              /* Use the sensor provided percentage */
              {% set progress = raw_percent | int %}
           {% else %}
              /* Fallback: Calculate based on max_time */
              {% set max_cycle_time = max_time %}
              {% set calc_prog = ((max_cycle_time - time_rem) / max_cycle_time * 100) | int %}
              {% set progress = [5, [calc_prog, 100] | min] | max %}
           {% endif %}

           /* Show Status + Time + Power */
           {% set badge_text = status_clean ~ ' • ' ~ time_formatted ~ power_text %}
        {% endif %}

        /* --- STATE DEFINITIONS --- */
        {% set s_lower = status | lower %}
        {% set is_running = s_lower in ['wash', 'washing', 'rinse', 'rinsing', 'pre-wash'] %}
        {% set is_drying  = s_lower in ['dry', 'drying'] %}
        {% set is_done    = s_lower in ['finished', 'complete', 'end'] %}

        /* --- ASSIGN ANIMATIONS --- */
        {% if is_drying %}
          {% set color = '255, 152, 0' %}  /* Orange */
          {% set anim_type = 'steam-rise 2s ease-in-out infinite' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'linear-gradient(0deg, transparent, rgba(255,255,255,0.5), transparent)' %}
        {% elif is_done %}
          {% set color = '76, 175, 80' %}   /* Green */
          {% set anim_type = 'sparkle 2s infinite' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.8) 10%, transparent 60%)' %}
        {% elif is_running %}
          {% set color = '33, 150, 243' %}  /* Blue */
          {% set anim_type = 'bubbles 1s linear infinite' %}
          {% set icon_shake = 'shake 0.8s ease-in-out infinite' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'radial-gradient(2px 2px at 20% 80%, white, transparent), radial-gradient(2px 2px at 50% 70%, white, transparent)' %}
        {% else %}
          {% set color = '158, 158, 158' %}  /* Grey */
          {% set anim_type = 'none' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'none' %}
          {% set overlay_img = 'none' %}
        {% endif %}

        /* --- OUTPUT VARIABLES --- */
        --dw-color: {{ color }};
        --dw-level: {{ progress }}%;
        --dw-anim-overlay: {{ anim_type }};
        --dw-anim-shake: {{ icon_shake }};
        --dw-anim-wave: {{ wave_anim }};
        --dw-overlay-bg: {{ overlay_img }};
        --dw-badge-content: "{{ badge_text }}";
        
        transition: all 0.5s ease;
        overflow: hidden;
      }

      /* BADGE */
      ha-card::before {
        content: var(--dw-badge-content);
        position: absolute;
        top: 10px; right: 10px;
        background: rgba(var(--dw-color), 0.15);
        color: rgb(var(--dw-color));
        border: 1px solid rgba(var(--dw-color), 0.3);
        padding: 2px 10px;
        border-radius: 12px;
        text-transform: uppercase;
        font-weight: 600;
        letter-spacing: 0.5px;
        font-size: var(--config-font-badge);
      }

      /* BAR */
      ha-card::after {
        content: '';
        position: absolute;
        bottom: 0; left: 0;
        height: 4px;
        width: var(--dw-level);
        background: rgb(var(--dw-color));
        box-shadow: 0 0 10px rgb(var(--dw-color));
        transition: width 0.5s ease;
      }
    mushroom-shape-icon$: |
      .shape {
        --icon-size: var(--config-icon-size) !important;
        background: rgba(255, 255, 255, 0.05) !important;
        overflow: hidden;
        position: relative;
        border: 1px solid rgba(255,255,255,0.1);
        
        /* Apply the animation determined by the Logic below */
        animation: var(--dw-anim-shake) !important;
        transform-origin: 50% 60%; 
      }

      /* Wave Layer */
      .shape::before {
        content: '';
        position: absolute;
        left: -50%;
        width: 200%; height: 200%;
        top: calc(100% - var(--dw-level));
        background: rgba(var(--dw-color), 0.6);
        border-radius: 40%;
        animation: var(--dw-anim-wave);
      }

      /* Overlay Layer (Bubbles/Steam) */
      .shape::after {
        content: '';
        position: absolute;
        inset: 0;
        background-image: var(--dw-overlay-bg);
        background-size: 100% 100%;
        animation: var(--dw-anim-overlay);
        z-index: 2;
      }

      /* The Icon Itself */
      ha-icon {
        z-index: 3;
        mix-blend-mode: overlay;
        color: white !important;
      }

      /* --- KEYFRAMES --- */
      @keyframes wave {
        from { transform: rotate(0deg); }
        to   { transform: rotate(360deg); }
      }
      @keyframes shake {
        0%, 100% { transform: rotate(0deg); }
        25% { transform: rotate(5deg) translateY(-1px); }
        75% { transform: rotate(-5deg) translateY(1px); }
      }
      @keyframes bubbles {
        0% { transform: translateY(10px); opacity: 0; }
        50% { opacity: 1; }
        100% { transform: translateY(-20px); opacity: 0; }
      }
      @keyframes steam-rise {
        0% { opacity: 0; transform: translateY(5px); }
        50% { opacity: 0.8; }
        100% { opacity: 0; transform: translateY(-10px); }
      }
      @keyframes sparkle {
        0%, 100% { opacity: 0.3; transform: scale(0.9); }
        50% { opacity: 1; transform: scale(1.1); }
      }
    mushroom-state-info$: |
      .container .primary {
        font-size: var(--config-font-primary) !important;
      }
      .container .secondary {
        font-size: var(--config-font-secondary) !important;
      }

2 - Smart Washing Machine
type: custom:mushroom-entity-card
entity: sensor.washing_machine_status
name: Smart Washing Machine
icon: mdi:washing-machine
primary_info: name
secondary_info: state
tap_action:
  action: more-info
icon_color: light-grey
fill_container: false
card_mod:
  style:
    .: |
      ha-card {
        /* ======================== */
        /* USER CONFIGURATION       */
        /* ======================== */
        
        /* 1. ENTITIES */
        {% set ent_status  = 'sensor.washing_machine_progress' %}
        {% set ent_timerem = 'sensor.washing_machine_time_remaining' %}
        {% set max_time = 120 %}
        {% set ent_power   = 'sensor.smart_plug_power' %}

        /* OPTIONAL Progress Percentage Sensor (if exists) */
        {% set ent_percent   = 'sensor.washing_machine_progress_percentage' %}

        /* 2. SIZES (Px) */
        --config-icon-size:       65px;
        --config-font-primary:    15px;
        --config-font-secondary:  12px;
        --config-font-badge:      12px;
        /* ======================== */

        /* --- SENSORS & TIME --- */
        {% set status = states(ent_status) %}
        {% set status_clean = status | replace('-', ' ') | title %}
        {% set time_rem = states(ent_timerem) | int(0) %}
        {% set raw_percent = states(ent_percent) | float(-1) %}

        /* --- POWER CALCULATION --- */
        {% set power_w = states(ent_power) | float(0) | round %}
        {% set power_text = ' • ' ~ power_w ~ 'W' if power_w > 0 else '' %}
        
        /* Format Time (min -> Xh Ym) */
        {% set hours = (time_rem / 60) | int %}
        {% set mins = time_rem % 60 %}
        {% set time_formatted = '%dh %02dm' | format(hours, mins) %}

        /* --- PROGRESS CALCULATION --- */
        
        {% if status | lower in ['idle', 'off', 'standby', 'unknown', 'unavailable'] %}
           {% set progress = 0 %}
           {% set badge_text = status_clean ~ power_text %}
        {% else %}
           
           /* LOGIC: Use Sensor if available, otherwise Calculate */
           {% if raw_percent >= 0 %}
              /* Use the sensor provided percentage */
              {% set progress = raw_percent | int %}
           {% else %}
              /* Fallback: Calculate based on max_time */
              {% set max_cycle_time = max_time %}
              {% set calc_prog = ((max_cycle_time - time_rem) / max_cycle_time * 100) | int %}
              {% set progress = [5, [calc_prog, 100] | min] | max %}
           {% endif %}

           {% set badge_text = status_clean ~ ' • ' ~ time_formatted ~ power_text %}
        {% endif %}

        /* --- STATE DEFINITIONS --- */
        {% set s_lower = status | lower %}
        {% set is_running  = s_lower in ['wash', 'washing', 'rinse', 'rinsing', 'pre-wash', 'soak'] %}
        {% set is_spinning = s_lower in ['spin', 'spinning'] %}
        {% set is_drying   = s_lower in ['dry', 'drying'] %}
        {% set is_done     = s_lower in ['finished', 'complete', 'end'] %}

        /* --- ASSIGN ANIMATIONS --- */
        {% if is_drying %}
          {% set color = '255, 152, 0' %}   /* Orange */
          {% set anim_type = 'steam-rise 2s ease-in-out infinite' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'linear-gradient(0deg, transparent, rgba(255,255,255,0.5), transparent)' %}
        
        {% elif is_spinning %}
          {% set color = '0, 255, 255' %}   /* cyan */
          {% set anim_type = 'none' %}
          {% set icon_shake = 'washer-spin-smooth 0.8s linear infinite' %}
          {% set wave_anim = 'wave 2s linear infinite' %}  /* Fast Wave */
          {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.3) 10%, transparent 60%)' %}

        {% elif is_done %}
          {% set color = '76, 175, 80' %}   /* Green */
          {% set anim_type = 'sparkle 2s infinite' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.8) 10%, transparent 60%)' %}

        {% elif is_running %}
          {% set color = '33, 150, 243' %}   /* Blue */
          {% set anim_type = 'bubbles 1s linear infinite' %}
          {% set icon_shake = 'shake 1.5s ease-in-out infinite' %} /* Slow Shake */
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'radial-gradient(2px 2px at 20% 80%, white, transparent), radial-gradient(2px 2px at 50% 70%, white, transparent)' %}
        
        {% else %}
          {% set color = '158, 158, 158' %}  /* Grey */
          {% set anim_type = 'none' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'none' %}
          {% set overlay_img = 'none' %}
        {% endif %}

        /* --- OUTPUT VARIABLES --- */
        --wm-color: {{ color }};
        --wm-level: {{ progress }}%;
        --wm-anim-overlay: {{ anim_type }};
        --wm-anim-shake: {{ icon_shake }};
        --wm-anim-wave: {{ wave_anim }};
        --wm-overlay-bg: {{ overlay_img }};
        --wm-badge-content: "{{ badge_text }}";
        
        transition: all 0.5s ease;
        overflow: hidden;
      }

      /* BADGE */
      ha-card::before {
        content: var(--wm-badge-content);
        position: absolute;
        top: 10px; right: 10px;
        background: rgba(var(--wm-color), 0.15);
        color: rgb(var(--wm-color));
        border: 1px solid rgba(var(--wm-color), 0.3);
        padding: 2px 10px;
        border-radius: 12px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        font-size: var(--config-font-badge);
      }

      /* BAR */
      ha-card::after {
        content: '';
        position: absolute;
        bottom: 0; left: 0;
        height: 4px;
        width: var(--wm-level);
        background: rgb(var(--wm-color));
        box-shadow: 0 0 10px rgb(var(--wm-color));
        transition: width 0.5s ease;
      }
    mushroom-shape-icon$: |
      .shape {
        --icon-size: var(--config-icon-size) !important;
        background: rgba(255, 255, 255, 0.05) !important;
        overflow: hidden;
        position: relative;
        border: 1px solid rgba(255,255,255,0.1);
        
        /* Apply the animation determined by the Logic below */
        animation: var(--wm-anim-shake) !important;
        transform-origin: center center; 
      }

      /* Wave Layer */
      .shape::before {
        content: '';
        position: absolute;
        left: -50%;
        width: 200%; height: 200%;
        top: calc(100% - var(--wm-level));
        background: rgba(var(--wm-color), 0.6);
        border-radius: 40%;
        animation: var(--wm-anim-wave);
      }

      /* Overlay Layer (Bubbles/Steam) */
      .shape::after {
        content: '';
        position: absolute;
        inset: 0;
        background-image: var(--wm-overlay-bg);
        background-size: 100% 100%;
        animation: var(--wm-anim-overlay);
        z-index: 2;
      }

      /* The Icon Itself */
      ha-icon {
        z-index: 3;
        mix-blend-mode: overlay;
        color: white !important;
      }

      /* --- KEYFRAMES --- */
      @keyframes wave {
        from { transform: rotate(0deg); }
        to   { transform: rotate(360deg); }
      }
      @keyframes shake {
        0%, 100% { transform: rotate(0deg); }
        25% { transform: rotate(5deg) translateY(-1px); }
        75% { transform: rotate(-5deg) translateY(1px); }
      }
      @keyframes bubbles {
        0% { transform: translateY(10px); opacity: 0; }
        50% { opacity: 1; }
        100% { transform: translateY(-20px); opacity: 0; }
      }
      @keyframes steam-rise {
        0% { opacity: 0; transform: translateY(5px); }
        50% { opacity: 0.8; }
        100% { opacity: 0; transform: translateY(-10px); }
      }
      @keyframes sparkle {
        0%, 100% { opacity: 0.3; transform: scale(0.9); }
        50% { opacity: 1; transform: scale(1.1); }
      }

      @keyframes washer-spin-smooth {
        0% {
          transform: rotate(0deg) translate(0,0);
          box-shadow: inset 0 0 0 2px rgba(var(--wm-color), 0.7);
        }
        25% { transform: rotate(90deg) translate(0.5px, 0.5px); }
        50% { transform: rotate(180deg) translate(0,0); }
        75% { transform: rotate(270deg) translate(-0.5px, -0.5px); }
        100% {
          transform: rotate(360deg) translate(0,0);
          box-shadow: inset 0 0 0 2px rgba(var(--wm-color), 0.7);
        }
      }
    mushroom-state-info$: |
      .container .primary {
        font-size: var(--config-font-primary) !important;
      }
      .container .secondary {
        font-size: var(--config-font-secondary) !important;
      }

3 - Smart Dryer
type: custom:mushroom-entity-card
entity: sensor.dryer_status
name: Smart Dryer
icon: mdi:tumble-dryer
primary_info: name
secondary_info: state
tap_action:
  action: more-info
icon_color: light-grey
fill_container: false
card_mod:
  style:
    .: |
      ha-card {
        /* ======================== */
        /* USER CONFIGURATION       */
        /* ======================== */
        
        /* 1. ENTITIES */
        {% set ent_progress  = 'sensor.dryer_progress' %}
        {% set ent_timerem   = 'sensor.dryer_time_remaining' %}
        {% set max_time = 160 %}
        {% set ent_power     = 'sensor.smart_plug_power' %} 
        
        /* OPTIONAL Progress Percentage Sensor (if exists) */
        {% set ent_percent   = 'sensor.dryer_progress_percentage' %}

        /* 2. SIZES (Px) */
        --config-icon-size:       65px;
        --config-font-primary:    15px;
        --config-font-secondary:  12px;
        --config-font-badge:      12px;
        /* ======================== */

        /* --- SENSORS & TIME --- */
        {% set status = states(ent_progress) %}
        {% set status_clean = status | replace('-', ' ') | title %}
        {% set time_rem = states(ent_timerem) | int(0) %}
        {% set raw_percent = states(ent_percent) | float(-1) %}
        
        /* --- POWER CALCULATION --- */
        {% set power_w = states(ent_power) | float(0) | round %}
        {% set power_text = ' • ' ~ power_w ~ 'W' if power_w > 0 else '' %}

        /* Format Time (min -> Xh Ym) */
        {% set hours = (time_rem / 60) | int %}
        {% set mins = time_rem % 60 %}
        {% set time_formatted = '%dh %02dm' | format(hours, mins) %}

        /* --- PROGRESS CALCULATION --- */
        {% if status | lower in ['idle', 'off', 'standby', 'unknown', 'unavailable'] %}
           {% set progress = 0 %}
           {% set badge_text = status_clean ~ power_text %}
        {% else %}
           
           /* LOGIC: Use Sensor if available, otherwise Calculate */
           {% if raw_percent >= 0 %}
              /* Use the sensor provided percentage */
              {% set progress = raw_percent | int %}
           {% else %}
              /* Fallback: Calculate based on max_time */
              {% set max_cycle_time = max_time %}
              {% set calc_prog = ((max_cycle_time - time_rem) / max_cycle_time * 100) | int %}
              {% set progress = [5, [calc_prog, 100] | min] | max %}
           {% endif %}

           /* Show Status + Time + Power */
           {% set badge_text = status_clean ~ ' • ' ~ time_formatted ~ power_text %}
        {% endif %}

        /* --- STATE DEFINITIONS --- */
        {% set s_lower = status | lower %}
        {% set is_drying  = s_lower in ['drying', 'tumble', 'dry', 'heat', 'drying', 'heating'] %}
        {% set is_cooling = s_lower in ['cooling', 'cool down', 'anti-crease', 'air fluff'] %}
        {% set is_done    = s_lower in ['finished', 'complete', 'end'] %}

        /* --- ASSIGN ANIMATIONS --- */
        {% if is_drying %}
          {% set color = '255, 87, 34' %}   /* Deep Orange (Heat) */
          {% set anim_type = 'steam-rise 2s ease-in-out infinite' %}
          {% set icon_shake = 'shake 0.8s ease-in-out infinite' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'linear-gradient(0deg, transparent, rgba(255,255,255,0.4), transparent)' %}
        {% elif is_cooling %}
          {% set color = '33, 150, 243' %}  /* Blue (Cooling) */
          {% set anim_type = 'breeze 3s ease-in-out infinite' %}
          {% set icon_shake = 'wobble 2s ease-in-out infinite' %}
          {% set wave_anim = 'wave 6s linear infinite' %}
          {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.5) 0%, transparent 70%)' %}
        {% elif is_done %}
          {% set color = '76, 175, 80' %}   /* Green */
          {% set anim_type = 'sparkle 2s infinite' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.8) 10%, transparent 60%)' %}
        {% else %}
          {% set color = '158, 158, 158' %} /* Grey */
          {% set anim_type = 'none' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'none' %}
          {% set overlay_img = 'none' %}
        {% endif %}

        /* --- OUTPUT VARIABLES --- */
        --dryer-color: {{ color }};
        --dryer-level: {{ progress }}%;
        --dryer-anim-overlay: {{ anim_type }};
        --dryer-anim-shake: {{ icon_shake }};
        --dryer-anim-wave: {{ wave_anim }};
        --dryer-overlay-bg: {{ overlay_img }};
        --dryer-badge-content: "{{ badge_text }}";
        
        transition: all 0.5s ease;
        overflow: hidden;
      }

      /* BADGE */
      ha-card::before {
        content: var(--dryer-badge-content);
        position: absolute;
        top: 10px; right: 10px;
        background: rgba(var(--dryer-color), 0.15);
        color: rgb(var(--dryer-color));
        border: 1px solid rgba(var(--dryer-color), 0.3);
        padding: 2px 10px;
        border-radius: 12px;
        text-transform: uppercase;
        font-weight: 600;
        letter-spacing: 0.5px;
        font-size: var(--config-font-badge);
      }

      /* BAR */
      ha-card::after {
        content: '';
        position: absolute;
        bottom: 0; left: 0;
        height: 4px;
        width: var(--dryer-level);
        background: rgb(var(--dryer-color));
        box-shadow: 0 0 10px rgb(var(--dryer-color));
        transition: width 0.5s ease;
      }
    mushroom-shape-icon$: |
      .shape {
        --icon-size: var(--config-icon-size) !important;
        background: rgba(255, 255, 255, 0.05) !important;
        overflow: hidden;
        position: relative;
        border: 1px solid rgba(255,255,255,0.1);
        
        /* Apply the animation determined by the Logic below */
        animation: var(--dryer-anim-shake) !important;
        transform-origin: 50% 60%; 
      }

      /* Wave Layer */
      .shape::before {
        content: '';
        position: absolute;
        left: -50%;
        width: 200%; height: 200%;
        top: calc(100% - var(--dryer-level));
        background: rgba(var(--dryer-color), 0.6);
        border-radius: 40%;
        animation: var(--dryer-anim-wave);
      }

      /* Overlay Layer (Bubbles/Steam) */
      .shape::after {
        content: '';
        position: absolute;
        inset: 0;
        background-image: var(--dryer-overlay-bg);
        background-size: 100% 100%;
        animation: var(--dryer-anim-overlay);
        z-index: 2;
      }

      /* The Icon Itself */
      ha-icon {
        z-index: 3;
        mix-blend-mode: overlay;
        color: white !important;
      }

      /* --- KEYFRAMES --- */
      @keyframes wave {
        from { transform: rotate(0deg); }
        to   { transform: rotate(360deg); }
      }
      @keyframes shake {
        0%, 100% { transform: rotate(0deg); }
        25% { transform: rotate(10deg) translateY(-2px); }
        50% { transform: rotate(0deg); }
        75% { transform: rotate(-10deg) translateY(2px); }
      }
      @keyframes wobble {
        0%, 100% { transform: rotate(0deg); }
        50% { transform: rotate(5deg); }
      }
      @keyframes steam-rise {
        0% { opacity: 0; transform: translateY(10px) scale(0.9); }
        50% { opacity: 0.6; }
        100% { opacity: 0; transform: translateY(-20px) scale(1.1); }
      }
      @keyframes breeze {
        0% { opacity: 0.2; transform: scale(0.95); }
        50% { opacity: 0.5; transform: scale(1.05); }
        100% { opacity: 0.2; transform: scale(0.95); }
      }
      @keyframes sparkle {
        0%, 100% { opacity: 0.3; transform: scale(0.9); }
        50% { opacity: 1; transform: scale(1.1); }
      }
    mushroom-state-info$: |
      .container .primary {
        font-size: var(--config-font-primary) !important;
      }
      .container .secondary {
        font-size: var(--config-font-secondary) !important;
      }

4 - Smart Combo Washing machine & Dryer
type: custom:mushroom-entity-card
entity: sensor.combo_machine_status
name: Smart Combo
icon: mdi:washing-machine
primary_info: name
secondary_info: state
tap_action:
  action: more-info
icon_color: light-grey
fill_container: false
card_mod:
  style:
    .: |
      ha-card {
        /* ======================== */
        /* USER CONFIGURATION       */
        /* ======================== */
        
        /* 1. ENTITIES */
        {% set ent_status  = 'sensor.combo_machine_progress' %}
        {% set ent_timerem = 'sensor.combo_machine_time_remaining' %}
        {% set max_time = 180 %}

        {% set ent_power   = 'sensor.smart_plug_power' %}
        
        /* OPTIONAL Progress Percentage Sensor (if exists) */
        {% set ent_percent = 'sensor.combo_machine_progress_percentage' %}

        /* 2. SIZES (Px) */
        --config-icon-size:       65px;
        --config-font-primary:    15px;
        --config-font-secondary:  12px;
        --config-font-badge:      12px;
        /* ======================== */

        /* --- SENSORS & DATA --- */
        {% set status = states(ent_status) %}
        {% set status_clean = status | replace('-', ' ') | title %}
        {% set time_rem = states(ent_timerem) | int(0) %}
        {% set raw_percent = states(ent_percent) | float(-1) %}
        
        /* --- POWER DISPLAY --- */
        {% set power_w = states(ent_power) | float(0) | round %}
        {% set power_text = ' • ' ~ power_w ~ 'W' if power_w > 0 else '' %}

        /* Format Time (min -> Xh Ym) */
        {% set hours = (time_rem / 60) | int %}
        {% set mins = time_rem % 60 %}
        {% set time_formatted = '%dh %02dm' | format(hours, mins) %}

        /* --- PROGRESS CALCULATION --- */
        {% if status | lower in ['idle', 'off', 'standby', 'unknown', 'unavailable'] %}
           {% set progress = 0 %}
           {% set badge_text = status_clean ~ power_text %}
        {% else %}
           
           /* LOGIC: Use Sensor if available, otherwise Calculate */
           {% if raw_percent >= 0 %}
              {% set progress = raw_percent | int %}
           {% else %}
              {% set max_cycle_time = max_time %}
              {% set calc_prog = ((max_cycle_time - time_rem) / max_cycle_time * 100) | int %}
              {% set progress = [5, [calc_prog, 100] | min] | max %}
           {% endif %}

           {% set badge_text = status_clean ~ ' • ' ~ time_formatted ~ power_text %}
        {% endif %}

        /* --- STATE LOGIC (The Core Logic) --- */
        {% set s_lower = status | lower %}
        
        /* 1. Water Phases */
        {% set is_washing  = s_lower in ['wash', 'washing', 'rinse', 'rinsing', 'pre-wash', 'soak'] %}
        {% set is_spinning = s_lower in ['spin', 'spinning', 'drain'] %}
        
        /* 2. Heat Phases (Dryer Logic) */
        {% set is_drying   = s_lower in ['dry', 'drying', 'tumble'] %}
        {% set is_cooling  = s_lower in ['cooling', 'cool down', 'anti-crease'] %}
        
        /* 3. Finished */
        {% set is_done     = s_lower in ['finished', 'complete', 'end'] %}

        /* --- ANIMATION & COLOR ASSIGNMENT --- */
        {% if is_drying %}
          /* DRYING MODE: Orange + Steam + Shake */
          {% set color = '255, 87, 34' %} 
          {% set anim_type = 'steam-rise 2s ease-in-out infinite' %}
          {% set icon_shake = 'shake 0.8s ease-in-out infinite' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'linear-gradient(0deg, transparent, rgba(255,255,255,0.4), transparent)' %}
        
        {% elif is_cooling %}
          /* COOLING MODE: Light Blue + Breeze + Wobble */
          {% set color = '33, 150, 243' %}
          {% set anim_type = 'breeze 3s ease-in-out infinite' %}
          {% set icon_shake = 'wobble 2s ease-in-out infinite' %}
          {% set wave_anim = 'wave 6s linear infinite' %}
          {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.5) 0%, transparent 70%)' %}

        {% elif is_spinning %}
          /* SPINNING MODE: Cyan + Fast Spin + Fast Wave */
          {% set color = '0, 255, 255' %}
          {% set anim_type = 'none' %}
          {% set icon_shake = 'washer-spin-smooth 0.8s linear infinite' %}
          {% set wave_anim = 'wave 2s linear infinite' %}
          {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.3) 10%, transparent 60%)' %}

        {% elif is_washing %}
          /* WASHING MODE: Blue + Bubbles + Slow Shake */
          {% set color = '33, 150, 243' %}
          {% set anim_type = 'bubbles 1s linear infinite' %}
          {% set icon_shake = 'shake 1.5s ease-in-out infinite' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'radial-gradient(2px 2px at 20% 80%, white, transparent), radial-gradient(2px 2px at 50% 70%, white, transparent)' %}

        {% elif is_done %}
          /* DONE: Green + Sparkle */
          {% set color = '76, 175, 80' %}
          {% set anim_type = 'sparkle 2s infinite' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'wave 4s linear infinite' %}
          {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.8) 10%, transparent 60%)' %}

        {% else %}
          /* IDLE/OFF: Grey */
          {% set color = '158, 158, 158' %}
          {% set anim_type = 'none' %}
          {% set icon_shake = 'none' %}
          {% set wave_anim = 'none' %}
          {% set overlay_img = 'none' %}
        {% endif %}

        /* --- OUTPUT VARIABLES --- */
        --combo-color: {{ color }};
        --combo-level: {{ progress }}%;
        --combo-anim-overlay: {{ anim_type }};
        --combo-anim-shake: {{ icon_shake }};
        --combo-anim-wave: {{ wave_anim }};
        --combo-overlay-bg: {{ overlay_img }};
        --combo-badge-content: "{{ badge_text }}";
        
        transition: all 0.5s ease;
        overflow: hidden;
      }

      /* BADGE */
      ha-card::before {
        content: var(--combo-badge-content);
        position: absolute;
        top: 10px; right: 10px;
        background: rgba(var(--combo-color), 0.15);
        color: rgb(var(--combo-color));
        border: 1px solid rgba(var(--combo-color), 0.3);
        padding: 2px 10px;
        border-radius: 12px;
        text-transform: uppercase;
        font-weight: 600;
        letter-spacing: 0.5px;
        font-size: var(--config-font-badge);
      }

      /* PROGRESS BAR */
      ha-card::after {
        content: '';
        position: absolute;
        bottom: 0; left: 0;
        height: 4px;
        width: var(--combo-level);
        background: rgb(var(--combo-color));
        box-shadow: 0 0 10px rgb(var(--combo-color));
        transition: width 0.5s ease;
      }
    mushroom-shape-icon$: |
      .shape {
        --icon-size: var(--config-icon-size) !important;
        background: rgba(255, 255, 255, 0.05) !important;
        overflow: hidden;
        position: relative;
        border: 1px solid rgba(255,255,255,0.1);
        
        /* Apply Animation */
        animation: var(--combo-anim-shake) !important;
        transform-origin: center center; 
      }

      /* Wave Layer (Liquid) */
      .shape::before {
        content: '';
        position: absolute;
        left: -50%;
        width: 200%; height: 200%;
        top: calc(100% - var(--combo-level));
        background: rgba(var(--combo-color), 0.6);
        border-radius: 40%;
        animation: var(--combo-anim-wave);
      }

      /* Overlay Layer (Bubbles/Steam/Sparkle) */
      .shape::after {
        content: '';
        position: absolute;
        inset: 0;
        background-image: var(--combo-overlay-bg);
        background-size: 100% 100%;
        animation: var(--combo-anim-overlay);
        z-index: 2;
      }

      /* Icon */
      ha-icon {
        z-index: 3;
        mix-blend-mode: overlay;
        color: white !important;
      }

      /* --- KEYFRAMES --- */
      @keyframes wave {
        from { transform: rotate(0deg); }
        to   { transform: rotate(360deg); }
      }
      @keyframes shake {
        0%, 100% { transform: rotate(0deg); }
        25% { transform: rotate(5deg) translateY(-1px); }
        75% { transform: rotate(-5deg) translateY(1px); }
      }
      @keyframes wobble {
        0%, 100% { transform: rotate(0deg); }
        50% { transform: rotate(5deg); }
      }
      @keyframes washer-spin-smooth {
        0% {
          transform: rotate(0deg);
          box-shadow: inset 0 0 0 2px rgba(var(--combo-color), 0.7);
        }
        100% {
          transform: rotate(360deg);
          box-shadow: inset 0 0 0 2px rgba(var(--combo-color), 0.7);
        }
      }
      @keyframes bubbles {
        0% { transform: translateY(10px); opacity: 0; }
        50% { opacity: 1; }
        100% { transform: translateY(-20px); opacity: 0; }
      }
      @keyframes steam-rise {
        0% { opacity: 0; transform: translateY(10px) scale(0.9); }
        50% { opacity: 0.6; }
        100% { opacity: 0; transform: translateY(-20px) scale(1.1); }
      }
      @keyframes breeze {
        0% { opacity: 0.2; transform: scale(0.95); }
        50% { opacity: 0.5; transform: scale(1.05); }
        100% { opacity: 0.2; transform: scale(0.95); }
      }
      @keyframes sparkle {
        0%, 100% { opacity: 0.3; transform: scale(0.9); }
        50% { opacity: 1; transform: scale(1.1); }
      }
    mushroom-state-info$: |
      .container .primary {
        font-size: var(--config-font-primary) !important;
      }
      .container .secondary {
        font-size: var(--config-font-secondary) !important;
      }


5 - Dumb Dishwasher (smart plug)
type: custom:mushroom-entity-card
entity: sensor.smart_plug_power
name: Dishwasher
icon: mdi:dishwasher
primary_info: name
secondary_info: state
tap_action:
  action: more-info
fill_container: false
icon_color: light-grey
card_mod:
  style:
    .: |
      ha-card {
        /* ======================== */
        /* USER CONFIGURATION       */
        /* ======================== */

        /* 1. ENTITIES */
        {% set ent_switch = 'switch.smart_plug' %} 
        {% set ent_power = 'sensor.smart_plug_power' %}
        
        /* Optional Helper (Leave as is if you don't have one) */
        /* If in-use, then you can use this entity as the main card entity above */
        /* and it will show useful secondary info like */
        /* (Not Running, Running) instead of repeating wattage */

        {% set ent_helper = 'binary_sensor.dishwasher_active_delay' %}

        /* Thresholds */
        {% set thresh_heat = 1000 %}
        {% set thresh_active = 5 %}

        /* 2. Sizes */
        --config-icon-size:      65px;
        --config-font-primary:   15px;
        --config-font-secondary: 12px;
        --config-font-badge:     11px;
        /* ======================== */

        /* --- DEFAULTS --- */
        {% set icon_shake = 'none' %}
        {% set anim_type = 'none' %}
        {% set wave_anim = 'none' %}
        {% set overlay_img = 'none' %}
        {% set level = 0 %}
        {% set badge_content = '' %}
        {% set time_str = '' %}
        {% set color = '158, 158, 158' %}

        /* --- DATA FETCHING --- */
        {% set power = states(ent_power) | float(0) | int %}
        {% set switch_state = states(ent_switch) %}
        {% set has_helper = states(ent_helper) not in ['unknown', 'unavailable', 'none'] %}
        
        /* --- SMART LOGIC --- */
        {% if has_helper %}
          /* Scenario A: Helper Exists */
          {% set status_bin = states(ent_helper) %}
        {% else %}
          /* Scenario B: Helper Missing (Fallback to Power) */
          {% set status_bin = 'on' if power > thresh_active else 'off' %}
        {% endif %}

        /* --- DURATION TIMER --- */
        {% if status_bin == 'on' and switch_state == 'on' %}
          {% if has_helper %}
             /* Precise Timer via Helper */
             {% set start_time = states[ent_helper].last_changed %}
             {% set seconds = as_timestamp(now()) - as_timestamp(start_time) %}
             {% set hours = (seconds / 3600) | int %}
             {% set mins = ((seconds % 3600) / 60) | int %}
             {% if seconds > 60 %}
                {% set time_str = '%dh %02dm' | format(hours, mins) %}
             {% else %}
                {% set time_str = 'Started' %}
             {% endif %}
          {% else %}
             /* No Helper - Just say Started */
             {% set time_str = 'Started' %}
          {% endif %}
        {% else %}
          {% set time_str = '' %}
        {% endif %}

        /* --- VISUAL STATE LOGIC --- */
        {% if switch_state == 'off' %}
           {% set status_text = 'Plug Off' %}
           {% set color = '244, 67, 54' %}       
           {% set badge_content = status_text %}

        {% elif switch_state in ['unavailable', 'unknown'] %}
           {% set status_text = 'Offline' %}
           {% set color = '158, 158, 158' %}    
           {% set badge_content = status_text %}

        {% elif status_bin == 'on' %}
           /* Machine is Active */
           {% if power > thresh_heat %}
             {% set status_text = 'Heating' %}
             {% set color = '255, 152, 0' %}       
             {% set anim_type = 'steam-rise 2s ease-in-out infinite' %}
             {% set overlay_img = 'linear-gradient(0deg, transparent, rgba(255,255,255,0.5), transparent)' %}
           {% else %}
             {% set status_text = 'Washing' %}
             {% set color = '33, 150, 243' %}      
             {% set anim_type = 'bubbles 1s linear infinite' %}
             {% set overlay_img = 'radial-gradient(2px 2px at 20% 80%, white, transparent), radial-gradient(2px 2px at 50% 70%, white, transparent)' %}
             {% set icon_shake = 'shake 0.8s ease-in-out infinite' %}
           {% endif %}
           
           {% set wave_anim = 'wave 4s linear infinite' %}
           {% set level = 60 %}
           {% set badge_content = status_text ~ " • " ~ power ~ " W" %}

        {% else %}
           /* --- IDLE STATE --- */
           {% set status_text = 'Idle' %}
           {% set color = '158, 158, 158' %}       
           {% set badge_content = status_text ~ " • " ~ power ~ " W" %}
        {% endif %}

        /* --- APPLY CSS VARIABLES --- */
        --dw-color: {{ color }};
        --dw-level: {{ level }}%;
        --dw-anim-overlay: {{ anim_type }};
        --dw-anim-shake: {{ icon_shake }};
        --dw-anim-wave: {{ wave_anim }};
        --dw-overlay-bg: {{ overlay_img }};
        --dw-badge-status: "{{ badge_content }}";
        
        /* Pass text AND display mode logic */
        --dw-time-text: "{{ time_str }}";
        --dw-time-display: {{ 'block' if time_str | length > 0 else 'none' }};
        
        transition: all 0.5s ease;
        overflow: hidden;
      }

      /* 1. STATUS BADGE (Top Right) */
      ha-card::before {
        content: var(--dw-badge-status);
        position: absolute;
        top: 8px; right: 10px;
        background: rgba(var(--dw-color), 0.15);
        color: rgb(var(--dw-color));
        border: 1px solid rgba(var(--dw-color), 0.3);
        padding: 2px 8px;
        border-radius: 10px;
        font-weight: 700;
        text-transform: uppercase;
        font-size: var(--config-font-badge);
        letter-spacing: 0.5px;
        z-index: 5;
      }

      /* 2. PROGRESS BAR */
      ha-card::after {
        content: '';
        position: absolute;
        bottom: 0; left: 0;
        height: 4px;
        width: var(--dw-level);
        background: rgb(var(--dw-color));
        box-shadow: 0 0 10px rgb(var(--dw-color));
        transition: width 0.5s ease;
        z-index: 1;
      }
    mushroom-state-info$: >
      .container .primary { font-size: var(--config-font-primary) !important; }
      .container .secondary { font-size: var(--config-font-secondary)
      !important; }

      .container::after {
        content: var(--dw-time-text);
        position: absolute;
        top: 40px; 
        right: 10px;
        color: var(--primary-text-color);
        background: rgba(var(--rgb-primary-text-color), 0.05);
        border: 1px solid rgba(var(--rgb-primary-text-color), 0.1);
        padding: 2px 8px;
        border-radius: 10px;
        font-weight: 700;
        font-size: var(--config-font-badge);
        letter-spacing: 0.5px;
        display: var(--dw-time-display);
      }
    mushroom-shape-icon$: >
      .shape {
        --icon-size: var(--config-icon-size) !important;
        background: rgba(255, 255, 255, 0.05) !important;
        overflow: hidden;
        position: relative;
        border: 1px solid rgba(255,255,255,0.1);
        animation: var(--dw-anim-shake) !important;
        transform-origin: 50% 60%; 
      } 

      .shape::before {
        content: '';
        position: absolute;
        left: -50%;
        width: 200%; height: 200%;
        top: calc(100% - var(--dw-level));
        background: rgba(var(--dw-color), 0.6);
        border-radius: 40%;
        animation: var(--dw-anim-wave);
      } 

      .shape::after {
        content: '';
        position: absolute;
        inset: 0;
        background-image: var(--dw-overlay-bg);
        background-size: 100% 100%;
        animation: var(--dw-anim-overlay);
        z-index: 2;
      } 

      ha-icon {
        z-index: 3;
        mix-blend-mode: overlay;
        color: white !important;
      }

      @keyframes wave { from { transform: rotate(0deg); } to { transform:
      rotate(360deg); } } @keyframes shake {
        0%, 100% { transform: rotate(0deg); }
        25% { transform: rotate(5deg) translateY(-1px); }
        75% { transform: rotate(-5deg) translateY(1px); }
      } @keyframes bubbles {
        0% { transform: translateY(10px); opacity: 0; }
        50% { opacity: 1; }
        100% { transform: translateY(-20px); opacity: 0; }
      } @keyframes steam-rise {
        0% { opacity: 0; transform: translateY(5px); }
        50% { opacity: 0.8; }
        100% { opacity: 0; transform: translateY(-10px); }
      }

Dumb Dishwasher (Helper/Template)
  - binary_sensor:
      - name: "Dishwasher Active delay"
        unique_id: dishwasher_active_delay
        # Change the entity_id below to match your actual smart plug
        state: >
          {{ states('sensor.smart_plug_power')|float(0) > 5 }}
        delay_off: "00:05:00"
        device_class: running
        icon: mdi:dishwasher

6 - Dumb Washing Machine (smart plug)
type: custom:mushroom-entity-card
entity: sensor.smart_plug_power
name: Washing Machine
icon: mdi:washing-machine
primary_info: name
secondary_info: state
tap_action:
  action: more-info
fill_container: false
icon_color: white
card_mod:
  style:
    .: |
      ha-card {
        /* ======================== */
        /* USER CONFIGURATION       */
        /* ======================== */

        /* 1. ENTITIES */
        {% set ent_switch = 'switch.smart_plug' %} 
        {% set ent_power = 'sensor.smart_plug_power' %}
        
        /* Optional Helper (Leave as is if you don't have one) */
        /* If in-use, then you can use this entity as the main card entity above */
        /* and it will show useful secondary info like */
        /* (Not Running, Running) instead of repeating wattage */

        {% set ent_helper = 'binary_sensor.washing_machine_active_delay' %}

        /* Thresholds */
        {% set thresh_spin = 300 %}
        {% set thresh_active = 5 %}

        /* 2. Sizes */
        --config-icon-size:       65px;
        --config-font-primary:    15px;
        --config-font-secondary:  12px;
        --config-font-badge:      11px;
        /* ======================== */

        /* --- DEFAULTS --- */
        {% set icon_shake = 'none' %}
        {% set anim_type = 'none' %}
        {% set wave_anim = 'none' %}
        {% set overlay_img = 'none' %}
        {% set level = 0 %}
        {% set badge_content = '' %}
        {% set time_str = '' %}
        {% set color = '158, 158, 158' %}

        /* --- DATA FETCHING --- */
        {% set power = states(ent_power) | float(0) | int %}
        {% set switch_state = states(ent_switch) %}
        {% set has_helper = states(ent_helper) not in ['unknown', 'unavailable', 'none'] %}
        
        /* --- SMART LOGIC --- */
        {% if has_helper %}
          {% set status_bin = states(ent_helper) %}
        {% else %}
          /* Fallback: Active if power > 5W */
          {% set status_bin = 'on' if power > thresh_active else 'off' %}
        {% endif %}
        
        /* --- DURATION TIMER --- */
        {% if status_bin == 'on' and switch_state == 'on' %}
          {% if has_helper %}
             /* Scenario A: Precise Timer via Helper */
             {% set start_time = states[ent_helper].last_changed %}
             {% set seconds = as_timestamp(now()) - as_timestamp(start_time) %}
             {% set hours = (seconds / 3600) | int %}
             {% set mins = ((seconds % 3600) / 60) | int %}
             {% if seconds > 60 %}
                {% set time_str = '%dh %02dm' | format(hours, mins) %}
             {% else %}
                {% set time_str = 'Started' %}
             {% endif %}
          {% else %}
             /* Scenario B: No Helper - Just say Started */
             {% set time_str = 'Started' %}
          {% endif %}
        {% else %}
          {% set time_str = '' %}
        {% endif %}

        /* --- STATE LOGIC --- */
        {% if switch_state == 'off' %}
           {% set status_text = 'Plug Off' %}
           {% set color = '244, 67, 54' %}       
           {% set badge_content = status_text %}

        {% elif switch_state in ['unavailable', 'unknown'] %}
           {% set status_text = 'Offline' %}
           {% set color = '158, 158, 158' %}    
           {% set badge_content = status_text %}

        {% elif status_bin == 'on' %}
           /* --- HIGH POWER (SPINNING) --- */
           {% if power > thresh_spin %}
             {% set status_text = 'Spinning' %}
             {% set color = '0, 255, 255' %} 
             {% set anim_type = 'none' %}
             {% set overlay_img = 'none' %}
             {% set icon_shake = 'washer-spin-smooth 0.8s linear infinite' %} 
           
           /* --- NORMAL POWER (WASHING) --- */
           {% else %}
             {% set status_text = 'Washing' %}
             {% set color = '33, 150, 243' %}
             {% set anim_type = 'bubbles 2s linear infinite' %}
             {% set overlay_img = 'radial-gradient(2px 2px at 20% 80%, white, transparent), radial-gradient(2px 2px at 50% 70%, white, transparent)' %}
             {% set icon_shake = 'shake 2s ease-in-out infinite' %} 
           {% endif %}
           
           {% set wave_anim = 'wave 4s linear infinite' %}
           {% set level = 60 %}
           {% set badge_content = status_text ~ " • " ~ power ~ " W" %}

        {% else %}
           /* --- IDLE STATE --- */
           {% set status_text = 'Idle' %}
           {% set color = '158, 158, 158' %}       
           {% set badge_content = status_text ~ " • " ~ power ~ " W" %}
        {% endif %}

        /* --- OUTPUT VARIABLES --- */
        --wm-color: {{ color }};
        --wm-level: {{ level }}%;
        --wm-anim-overlay: {{ anim_type }};
        --wm-anim-shake: {{ icon_shake }};
        --wm-anim-wave: {{ wave_anim }};
        --wm-overlay-bg: {{ overlay_img }};
        --wm-badge-status: "{{ badge_content }}";
        
        --wm-time-text: "{{ time_str }}";
        --wm-time-display: {{ 'block' if time_str | length > 0 else 'none' }};
        
        transition: all 0.5s ease;
        overflow: hidden;
      }

      /* 1. STATUS BADGE */
      ha-card::before {
        content: var(--wm-badge-status);
        position: absolute;
        top: 8px; right: 10px;
        background: rgba(var(--wm-color), 0.15);
        color: rgb(var(--wm-color));
        border: 1px solid rgba(var(--wm-color), 0.3);
        padding: 2px 8px;
        border-radius: 10px;
        font-weight: 700;
        text-transform: uppercase;
        font-size: var(--config-font-badge);
        letter-spacing: 0.5px;
        z-index: 5;
      }

      /* 2. PROGRESS BAR */
      ha-card::after {
        content: '';
        position: absolute;
        bottom: 0; left: 0;
        height: 4px;
        width: var(--wm-level);
        background: rgb(var(--wm-color));
        box-shadow: 0 0 10px rgb(var(--wm-color));
        transition: width 0.5s ease;
        z-index: 1;
      }
    mushroom-state-info$: >
      .container .primary { font-size: var(--config-font-primary) !important; }
      .container .secondary { font-size: var(--config-font-secondary)
      !important; }

      .container::after {
        content: var(--wm-time-text);
        position: absolute;
        top: 40px; 
        right: 10px;
        color: var(--primary-text-color);
        background: rgba(var(--rgb-primary-text-color), 0.05);
        border: 1px solid rgba(var(--rgb-primary-text-color), 0.1);
        padding: 2px 8px;
        border-radius: 10px;
        font-weight: 700;
        font-size: var(--config-font-badge);
        letter-spacing: 0.5px;
        display: var(--wm-time-display);
      }
    mushroom-shape-icon$: >
      .shape {
        --icon-size: var(--config-icon-size) !important;
        background: rgba(255, 255, 255, 0.05) !important;
        overflow: hidden !important; 
        position: relative;
        border: 1px solid rgba(255,255,255,0.1);
        animation: var(--wm-anim-shake) !important;
        transform-origin: 50% 50%; 
      } 

      .shape::before {
        content: '';
        position: absolute;
        left: -50%;
        width: 200%; height: 200%;
        top: calc(100% - var(--wm-level));
        background: rgba(var(--wm-color), 0.6);
        border-radius: 40%;
        animation: var(--wm-anim-wave);
      } 

      .shape::after {
        content: '';
        position: absolute;
        inset: 0;
        background-image: var(--wm-overlay-bg);
        background-size: 100% 100%;
        animation: var(--wm-anim-overlay);
        z-index: 2;
      } 

      ha-icon {
        z-index: 3;
        mix-blend-mode: overlay;
        color: white !important;
      } 

      @keyframes wave { from { transform: rotate(0deg); } to { transform:
      rotate(360deg); } } @keyframes shake {
        0%, 100% { transform: rotate(0deg); }
        25% { transform: rotate(5deg) translateY(-1px); }
        75% { transform: rotate(-5deg) translateY(1px); }
      } 

      @keyframes bubbles {
        0% { transform: translateY(10px); opacity: 0; }
        50% { opacity: 1; }
        100% { transform: translateY(-20px); opacity: 0; }
      } 

      @keyframes washer-spin-smooth {
        0% {
          transform: rotate(0deg) translate(0,0);
          box-shadow: inset 0 0 0 2px rgba(var(--wm-color), 0.7);
        }
        25% { transform: rotate(90deg) translate(0.5px, 0.5px); }
        50% { transform: rotate(180deg) translate(0,0); }
        75% { transform: rotate(270deg) translate(-0.5px, -0.5px); }
        100% {
          transform: rotate(360deg) translate(0,0);
          box-shadow: inset 0 0 0 2px rgba(var(--wm-color), 0.7);
        }
      }

Dumb Washing Machine (Helper/Template)
  - binary_sensor:
      - name: "Washing Machine Active delay"
        unique_id: washing_machine_active_delay
        # Change the entity_id below to match your actual smart plug
        state: >
          {{ states('sensor.smart_plug_power')|float(0) > 5 }}
        delay_off: "00:05:00"
        device_class: running
        icon: mdi:washing-machine

7 - Dumb Dryer (smart plug)
type: custom:mushroom-entity-card
entity: binary_sensor.dryer_active_delay
name: Dumb Dryer
icon: mdi:tumble-dryer
primary_info: name
secondary_info: state
tap_action:
  action: more-info
fill_container: false
icon_color: white
card_mod:
  style:
    .: |
      ha-card {
        /* ======================== */
        /* USER CONFIGURATION       */
        /* ======================== */
        
        {% set ent_switch = 'switch.smart_plug' %} 
        {% set ent_power  = 'sensor.smart_plug_power' %}
        
        /* Optional Helper (Leave as is if you don't have one) */
        /* If in-use, then you can use this entity as the main card entity above */
        /* and it will show useful secondary info like */
        /* (Not Running, Running) instead of repeating wattage */
        
        {% set ent_helper = 'binary_sensor.dryer_active_delay' %}

        /* Thresholds */
        
        {% set thresh_heat = 500 %} 
        {% set thresh_active = 5 %}

        /* SIZES */
        --config-icon-size:       65px;
        --config-font-primary:    15px;
        --config-font-secondary:  12px;
        --config-font-badge:      11px;
        /* ======================== */

        /* --- DEFAULTS --- */
        {% set icon_shake = 'none' %}
        {% set anim_type = 'none' %}
        {% set wave_anim = 'none' %}
        {% set overlay_img = 'none' %}
        {% set level = 0 %}
        {% set badge_content = '' %}
        {% set time_str = '' %}
        {% set color = '158, 158, 158' %}

        /* --- DATA FETCHING --- */
        {% set power = states(ent_power) | float(0) | int %}
        {% set switch_state = states(ent_switch) %}

        /* Check if helpers exist in HA */
        {% set has_helper = states(ent_helper) not in ['unknown', 'unavailable', 'none'] %}
        
        /* --- SMART LOGIC --- */
        {% if has_helper %}
          {% set status_bin = states(ent_helper) %}
        {% else %}
          /* Fallback: Active if power > 5W */
          {% set status_bin = 'on' if power > thresh_active else 'off' %}
        {% endif %}
        
        /* --- DURATION TIMER --- */
        {% if status_bin == 'on' and switch_state == 'on' %}
          {% if has_helper %}
             {% set start_time = states[ent_helper].last_changed %}
             {% set seconds = as_timestamp(now()) - as_timestamp(start_time) %}
             {% set hours = (seconds / 3600) | int %}
             {% set mins = ((seconds % 3600) / 60) | int %}
             {% if seconds > 60 %}
                {% set time_str = '%dh %02dm' | format(hours, mins) %}
             {% else %}
                {% set time_str = 'Started' %}
             {% endif %}
          {% else %}
             {% set time_str = 'Started' %}
          {% endif %}
        {% else %}
          {% set time_str = '' %}
        {% endif %}

        /* --- STATE LOGIC --- */
        {% if switch_state == 'off' %}
           {% set status_text = 'Plug Off' %}
           {% set color = '244, 67, 54' %}        
           {% set badge_content = status_text %}

        {% elif switch_state in ['unavailable', 'unknown'] %}
           {% set status_text = 'Offline' %}
           {% set color = '158, 158, 158' %}     
           {% set badge_content = status_text %}

        {% elif status_bin == 'on' %}
        
           /* --- HIGH POWER (HEATING/DRYING) --- */
           {% if power > thresh_heat %}
             {% set status_text = 'Drying' %}
             {% set color = '255, 87, 34' %}   /* Deep Orange */
             {% set anim_type = 'steam-rise 2s ease-in-out infinite' %}
             {% set overlay_img = 'linear-gradient(0deg, transparent, rgba(255,255,255,0.4), transparent)' %}
             {% set icon_shake = 'shake 0.8s ease-in-out infinite' %} 
           
           /* --- MEDIUM POWER (TUMBLING/COOLING) --- */
           {% else %}
             {% set status_text = 'Tumbling' %}
             {% set color = '33, 150, 243' %}  /* Blue (Air) */
             {% set anim_type = 'breeze 3s ease-in-out infinite' %}
             {% set overlay_img = 'radial-gradient(circle, rgba(255,255,255,0.5) 0%, transparent 70%)' %}
             {% set icon_shake = 'wobble 2s ease-in-out infinite' %} 
           {% endif %}
           
           {% set wave_anim = 'wave 4s linear infinite' %}
           {% set level = 60 %}
           {% set badge_content = status_text ~ " • " ~ power ~ " W" %}

        {% else %}
           /* --- IDLE STATE --- */
           {% set status_text = 'Idle' %}
           {% set color = '158, 158, 158' %}        
           {% set badge_content = status_text ~ " • " ~ power ~ " W" %}
        {% endif %}

        /* --- OUTPUT VARIABLES --- */
        --dryer-color: {{ color }};
        --dryer-level: {{ level }}%;
        --dryer-anim-overlay: {{ anim_type }};
        --dryer-anim-shake: {{ icon_shake }};
        --dryer-anim-wave: {{ wave_anim }};
        --dryer-overlay-bg: {{ overlay_img }};
        --dryer-badge-status: "{{ badge_content }}";
        
        --dryer-time-text: "{{ time_str }}";
        --dryer-time-display: {{ 'block' if time_str | length > 0 else 'none' }};
        
        transition: all 0.5s ease;
        overflow: hidden;
      }

      /* 1. STATUS BADGE */
      ha-card::before {
        content: var(--dryer-badge-status);
        position: absolute;
        top: 8px; right: 10px;
        background: rgba(var(--dryer-color), 0.15);
        color: rgb(var(--dryer-color));
        border: 1px solid rgba(var(--dryer-color), 0.3);
        padding: 2px 8px;
        border-radius: 10px;
        font-weight: 700;
        text-transform: uppercase;
        font-size: var(--config-font-badge);
        letter-spacing: 0.5px;
        z-index: 5;
      }

      /* 2. PROGRESS BAR (Visual Only) */
      ha-card::after {
        content: '';
        position: absolute;
        bottom: 0; left: 0;
        height: 4px;
        width: var(--dryer-level);
        background: rgb(var(--dryer-color));
        box-shadow: 0 0 10px rgb(var(--dryer-color));
        transition: width 0.5s ease;
        z-index: 1;
      }
    mushroom-state-info$: >
      .container .primary { font-size: var(--config-font-primary) !important; }
      .container .secondary { font-size: var(--config-font-secondary)
      !important; }

      .container::after {
        content: var(--dryer-time-text);
        position: absolute;
        top: 40px; 
        right: 10px;
        color: var(--primary-text-color);
        background: rgba(var(--rgb-primary-text-color), 0.05);
        border: 1px solid rgba(var(--rgb-primary-text-color), 0.1);
        padding: 2px 8px;
        border-radius: 10px;
        font-weight: 700;
        font-size: var(--config-font-badge);
        letter-spacing: 0.5px;
        display: var(--dryer-time-display);
      }
    mushroom-shape-icon$: >
      .shape {
        --icon-size: var(--config-icon-size) !important;
        background: rgba(255, 255, 255, 0.05) !important;
        overflow: hidden !important; 
        position: relative;
        border: 1px solid rgba(255,255,255,0.1);
        animation: var(--dryer-anim-shake) !important;
        transform-origin: 50% 50%; 
      } 

      .shape::before {
        content: '';
        position: absolute;
        left: -50%;
        width: 200%; height: 200%;
        top: calc(100% - var(--dryer-level));
        background: rgba(var(--dryer-color), 0.6);
        border-radius: 40%;
        animation: var(--dryer-anim-wave);
      } 

      .shape::after {
        content: '';
        position: absolute;
        inset: 0;
        background-image: var(--dryer-overlay-bg);
        background-size: 100% 100%;
        animation: var(--dryer-anim-overlay);
        z-index: 2;
      } 

      ha-icon {
        z-index: 3;
        mix-blend-mode: overlay;
        color: white !important;
      } 

      /* --- ANIMATIONS --- */ @keyframes wave { from { transform: rotate(0deg);
      } to { transform: rotate(360deg); } } 

      @keyframes shake {
        0%, 100% { transform: rotate(0deg); }
        25% { transform: rotate(10deg) translateY(-2px); }
        50% { transform: rotate(0deg); }
        75% { transform: rotate(-10deg) translateY(2px); }
      }

      @keyframes wobble {
        0%, 100% { transform: rotate(0deg); }
        50% { transform: rotate(5deg); }
      }

      @keyframes steam-rise {
        0% { opacity: 0; transform: translateY(10px) scale(0.9); }
        50% { opacity: 0.6; }
        100% { opacity: 0; transform: translateY(-20px) scale(1.1); }
      }

      @keyframes breeze {
        0% { opacity: 0.2; transform: scale(0.95); }
        50% { opacity: 0.5; transform: scale(1.05); }
        100% { opacity: 0.2; transform: scale(0.95); }
      }

Dumb Dryer (Helper/Template)
  - binary_sensor:
      - name: "Dryer Active delay"
        unique_id: dryer_active_status
        # Change the entity_id below to match your actual smart plug
        state: >
          {{ states('sensor.smart_plug_power')|float(0) > 5 }}
        delay_off: "00:05:00"
        device_class: running
        icon: mdi:tumble-dryer

8 - Combo Washing machine & Dryer (smart plug)
type: custom:mushroom-entity-card
entity: binary_sensor.combo_machine_active_delay
name: Dumb Combo
icon: mdi:washing-machine
primary_info: name
secondary_info: state
tap_action:
  action: more-info
fill_container: false
icon_color: white
card_mod:
  style:
    .: |
      ha-card {
        /* ======================== */
        /* USER CONFIGURATION       */
        /* ======================== */
        
        /* 1. ENTITIES */
        {% set ent_switch    = 'switch.smart_plug' %}
        {% set ent_power     = 'sensor.smart_plug_power' %}

        /* Optional Helpers (Leave as is if you don't have one) */
        /* If in-use, then you can use "ent_run" entity as the main card entity above */
        /* and it will show useful secondary info like */
        /* (Not Running, Running) instead of repeating wattage */
        
        {% set ent_run       = 'binary_sensor.combo_machine_active_delay' %}
        {% set ent_dry_mode  = 'binary_sensor.combo_machine_drying_detector' %}
        
        /* THRESHOLDS */
        {% set thresh_high = 800 %}
        {% set thresh_active = 5 %}

        /* 2. SIZES */
        --config-icon-size:       65px;
        --config-font-primary:    15px;
        --config-font-secondary:  12px;
        --config-font-badge:      11px;
        /* ======================== */

        /* --- DEFAULTS --- */
        {% set icon_shake = 'none' %}
        {% set anim_type = 'none' %}
        {% set wave_anim = 'none' %}
        {% set overlay_img = 'none' %}
        {% set level = 0 %}
        {% set badge_content = '' %}
        {% set time_str = '' %}
        {% set color = '158, 158, 158' %}

        /* --- DATA FETCHING --- */
        {% set power = states(ent_power) | float(0) | int %}
        {% set switch_state = states(ent_switch) %}
        
        /* Check if helpers exist in HA */
        {% set run_state = states(ent_run) %}
        {% set dry_state = states(ent_dry_mode) %}
        {% set has_run_helper = run_state not in ['unknown', 'unavailable', 'none'] %}
        {% set has_dry_helper = dry_state not in ['unknown', 'unavailable', 'none'] %}

        /* --- SMART LOGIC (With Fallbacks) --- */
        {% if has_run_helper %}
            /* Use Helper */
            {% set is_running = run_state == 'on' %}
        {% else %}
            /* Fallback: Power > 5W */
            {% set is_running = power > thresh_active %}
        {% endif %}

        {% if has_dry_helper %}
            /* Use Helper */
            {% set is_drying_mode = dry_state == 'on' %}
        {% else %}
            /* Fallback: We can't safely guess drying mode without a timer/helper */
            /* So we default to False (Washing) to be safe */
            {% set is_drying_mode = false %}
        {% endif %}
        
        /* --- TIMER CALCULATION --- */
        {% if is_running and switch_state == 'on' %}
             {% if has_run_helper %}
                 /* Calculate precise time if helper exists */
                 {% set start_time = states[ent_run].last_changed %}
                 {% set seconds = as_timestamp(now()) - as_timestamp(start_time) %}
                 {% set hours = (seconds / 3600) | int %}
                 {% set mins = ((seconds % 3600) / 60) | int %}
                 {% if seconds > 60 %}
                    {% set time_str = '%dh %02dm' | format(hours, mins) %}
                 {% else %}
                    {% set time_str = 'Started' %}
                 {% endif %}
             {% else %}
                 /* Generic text if no helper */
                 {% set time_str = 'Running' %}
             {% endif %}
        {% else %}
          {% set time_str = '' %}
        {% endif %}

        /* --- MAIN LOGIC --- */
        
        /* PRIORITY 1: CHECK SWITCH STATE */
        {% if switch_state in ['unavailable', 'unknown'] %}
           {% set status_text = 'Offline' %}
           {% set color = '158, 158, 158' %}   /* Dark Grey */   
           {% set badge_content = status_text %}
           {% set level = 0 %}

        /* PRIORITY 1: CHECK SWITCH STATE */
        {% elif switch_state == 'off' %}
           {% set status_text = 'Plug Off' %}
           {% set color = '244, 67, 54' %}     /* Red */   
           {% set badge_content = status_text %}
           {% set level = 0 %}

        /* PRIORITY 2: MACHINE IDLE */
        {% elif not is_running %}
           {% set status_text = 'Idle' %}
           {% set color = '158, 158, 158' %}   /* Grey */      
           /* ADDED POWER DISPLAY HERE */
           {% set badge_content = status_text ~ " • " ~ power ~ " W" %}

        /* PRIORITY 3: MACHINE RUNNING */
        {% else %}
           
           {% if is_drying_mode %}
             /* === DRYING === */
             {% set status_text = 'Drying' %}
             {% set color = '255, 87, 34' %}   /* Orange */
             {% set anim_type = 'steam-rise 2s ease-in-out infinite' %}
             {% set overlay_img = 'linear-gradient(0deg, transparent, rgba(255,255,255,0.4), transparent)' %}
             {% set icon_shake = 'shake 0.8s ease-in-out infinite' if power > 100 else 'wobble 2s ease-in-out infinite' %} 
           
           {% else %}
             /* === WASHING === */
             {% set status_text = 'Washing' %}
             {% set color = '33, 150, 243' %}  /* Blue */
             {% set anim_type = 'bubbles 2s linear infinite' %}
             {% set overlay_img = 'radial-gradient(2px 2px at 20% 80%, white, transparent), radial-gradient(2px 2px at 50% 70%, white, transparent)' %}
             
             {% if power > thresh_high %}
                {% set status_text = 'Spinning' %}
                {% set color = '0, 255, 255' %} /* Cyan */
                {% set icon_shake = 'washer-spin-smooth 0.8s linear infinite' %}
             {% else %}
                {% set icon_shake = 'shake 2s ease-in-out infinite' %}
             {% endif %}
           {% endif %}
           
           {% set wave_anim = 'wave 4s linear infinite' %}
           {% set level = 60 %}
           {% set badge_content = status_text ~ " • " ~ power ~ " W" %}

        {% endif %}

        /* --- CSS VARIABLES --- */
        --combo-color: {{ color }};
        --combo-level: {{ level }}%;
        --combo-anim-overlay: {{ anim_type }};
        --combo-anim-shake: {{ icon_shake }};
        --combo-anim-wave: {{ wave_anim }};
        --combo-overlay-bg: {{ overlay_img }};
        --combo-badge-status: "{{ badge_content }}";
        
        --combo-time-text: "{{ time_str }}";
        --combo-time-display: {{ 'block' if time_str | length > 0 else 'none' }};
        
        transition: all 0.5s ease;
        overflow: hidden;
      }

      /* BADGE */
      ha-card::before {
        content: var(--combo-badge-status);
        position: absolute;
        top: 8px; right: 10px;
        background: rgba(var(--combo-color), 0.15);
        color: rgb(var(--combo-color));
        border: 1px solid rgba(var(--combo-color), 0.3);
        padding: 2px 8px;
        border-radius: 10px;
        font-weight: 700;
        text-transform: uppercase;
        font-size: var(--config-font-badge);
        letter-spacing: 0.5px;
        z-index: 5;
      }

      /* BAR */
      ha-card::after {
        content: '';
        position: absolute;
        bottom: 0; left: 0;
        height: 4px;
        width: var(--combo-level);
        background: rgb(var(--combo-color));
        box-shadow: 0 0 10px rgb(var(--combo-color));
        transition: width 0.5s ease;
        z-index: 1;
      }
    mushroom-state-info$: >
      .container .primary { font-size: var(--config-font-primary) !important; }
      .container .secondary { font-size: var(--config-font-secondary)
      !important; }

      .container::after {
        content: var(--combo-time-text);
        position: absolute;
        top: 40px; 
        right: 10px;
        color: var(--primary-text-color);
        background: rgba(var(--rgb-primary-text-color), 0.05);
        border: 1px solid rgba(var(--rgb-primary-text-color), 0.1);
        padding: 2px 8px;
        border-radius: 10px;
        font-weight: 700;
        font-size: var(--config-font-badge);
        letter-spacing: 0.5px;
        display: var(--combo-time-display);
      }
    mushroom-shape-icon$: >
      .shape {
        --icon-size: var(--config-icon-size) !important;
        background: rgba(255, 255, 255, 0.05) !important;
        overflow: hidden !important; 
        position: relative;
        border: 1px solid rgba(255,255,255,0.1);
        animation: var(--combo-anim-shake) !important;
        transform-origin: 50% 50%; 
      } 

      .shape::before {
        content: '';
        position: absolute;
        left: -50%;
        width: 200%; height: 200%;
        top: calc(100% - var(--combo-level));
        background: rgba(var(--combo-color), 0.6);
        border-radius: 40%;
        animation: var(--combo-anim-wave);
      } 

      .shape::after {
        content: '';
        position: absolute;
        inset: 0;
        background-image: var(--combo-overlay-bg);
        background-size: 100% 100%;
        animation: var(--combo-anim-overlay);
        z-index: 2;
      } 

      ha-icon {
        z-index: 3;
        mix-blend-mode: overlay;
        color: white !important;
      } 

      @keyframes wave { from { transform: rotate(0deg); } to { transform:
      rotate(360deg); } } 

      @keyframes shake {
        0%, 100% { transform: rotate(0deg); }
        25% { transform: rotate(10deg) translateY(-2px); }
        50% { transform: rotate(0deg); }
        75% { transform: rotate(-10deg) translateY(2px); }
      }

      @keyframes wobble {
        0%, 100% { transform: rotate(0deg); }
        50% { transform: rotate(5deg); }
      }

      @keyframes steam-rise {
        0% { opacity: 0; transform: translateY(10px) scale(0.9); }
        50% { opacity: 0.6; }
        100% { opacity: 0; transform: translateY(-20px) scale(1.1); }
      }

      @keyframes bubbles {
        0% { transform: translateY(10px); opacity: 0; }
        50% { opacity: 1; }
        100% { transform: translateY(-20px); opacity: 0; }
      }

      @keyframes washer-spin-smooth {
        0% {
          transform: rotate(0deg) translate(0,0);
          box-shadow: inset 0 0 0 2px rgba(var(--combo-color), 0.7);
        }
        25% { transform: rotate(90deg) translate(0.5px, 0.5px); }
        50% { transform: rotate(180deg) translate(0,0); }
        75% { transform: rotate(270deg) translate(-0.5px, -0.5px); }
        100% {
          transform: rotate(360deg) translate(0,0);
          box-shadow: inset 0 0 0 2px rgba(var(--combo-color), 0.7);
        }
      }

Dumb Combo Washing machine & Dryer (Helper/Template)
  - binary_sensor:
      # 1. Main "Combo Machine Running" Detector
      - name: "Combo Machine Active Delay"
        unique_id: combo_machine_active_delay
        device_class: running
        icon: mdi:washing-machine
        state: >
          {{ states('sensor.smart_plug_power')|float(0) > 5 }}
        delay_off: "00:05:00" # Wait 5 min before saying it's off

      # 2. "Drying Mode" Detector
      # Logic If we see HIGH power for a sustained period, we assume Drying.
      # Note: Washing heaters cycle on/off quickly. Dryers stay on longer.
      - name: "Combo Machine Drying Detector"
        unique_id: combo_machine_drying_detector
        state: >
          {{ states('sensor.smart_plug_power')|float(0) > 800 }}
        # MUST be high for 15 mins to count as drying
        delay_on: "00:15:00"
        # Keeps drying active during cool down
        delay_off: "00:05:00"