OK update, after hours, and going back to it several times, and asking Brave’s AI, (I hate AI - but I also want to pass on what I learned, rather than what I get off some people “just use AI”, yeah that doesn’t help solve anything), anyway back on track, I finally got what I wanted in a roundabout way, thinking creatively and using what I’d learned on other projects.
Short of it is, I’m not sure it can be done with the current Mushroom or Tile cards, due to architectural limitations and Shadow DOM Encapsulation, where UI eXtension style: can’t penetrate certain selectors like ::after and $. Please do correct me if I’m wrong and there is a way to do it in Mushroom and Tile.
So, what I thought about doing is using Bubble Card coz it has sub buttons, and I can move the sub button, on the right by default to be behind the entity-picture and then make it slightly bigger for a red circle outline, but this was initially done with manual positioning, which wasn’t good when in different monitor sizes, or moved to different areas on the Dashboard, I later implemented it to force the sub button to the left, then I fine tuned it from a left margin to be exactly over the icon/picture.
In between I remembered you can replace icons with images after flex-horseshoe-card implemented it in one of his recent dev releases, so I did that and changed the z-index so the icon/image is now on top of the entity-picture.
I also figured out Streaming does actually mean ‘on’, so I used ‘on’ instead of ‘Streaming’, and because I’m using 2 buttons, I’m also now using binary_sensor.streamer_live to drive the ‘on’ state for the image rather than sensor.streamer, I found Running = ‘on’ in the binary sensor triggered the on state for the image, whereas the sensor.streamer Streaming = ‘on’ did not.
Here’s my working code, I’ve left the AI annotations there in case it helps anyone finding this post, the grid code at the bottom is purely to limit the width on my dashboard, and the scrolling_effect needs to be false, otherwise the card does weird stuff and rapidly pushes everything to the right:
type: custom:bubble-card
card_type: button
entity: sensor.trucker_dylan
icon_type: entity-picture
show_state: true
sub_button:
- entity: binary_sensor.trucker_dylan_live
icon: mdi:camera-image
show_background: false
show_name: false
show_state: false
tap_action:
action: none
styles: |
/* 1. Detach the container from the right side and move it to the left */
.bubble-sub-button-container {
position: absolute !important; /* Force absolute positioning */
left: 7px !important; /* Pin to the left edge (adjust margin as needed) */
right: inherit !important; /* CRITICAL: Remove the default 'right: 10px' */
bottom: 4px !important; /* Optional: Pin to bottom if desired, or remove for vertical center */
justify-content: flex-start !important; /* Align items to the start (left) */
width: auto !important; /* Allow width to shrink to content */
z-index: 10 !important;
}
/* 2. Your Overlay Logic (Replacing Icon with Image) */
${subButtonIcon[0].setAttribute("icon", "")}
.bubble-sub-button-1 {
display: ${hass.states['binary_sensor.trucker_dylan_live'].state === 'on' ? 'flex' : 'none'} !important;
background-image: url('/local/Twitch/live-overlay.png') !important;
background-size: contain !important;
background-position: center !important;
background-repeat: no-repeat !important;
width: 46px !important;
height: 46px !important;
border-radius: 50% !important;
z-index: 100 !important;
position: relative !important;
}
.bubble-sub-button-1 ha-icon {
display: none !important;
}
/* 3. Adjust Main Icon if it overlaps */
.bubble-icon {
width: 48px !important;
height: 48px !important;
}
button_type: state
scrolling_effect: false
grid_options:
columns: 6
rows: auto
Here’s 2 examples with offline and streaming states:

I might add a blink-animate at some point that lasts for 5 mins when ‘on’ is detected, looks easy enough to do, just need to add an input_boolean to limit the animation, but a mini project for another day, I’ll see if I need it first.