diff --git a/plugin-designs/plugin-studio/plugin-studio.vue b/plugin-designs/plugin-studio/plugin-studio.vue
index 9b4fa8916..9d7e33468 100644
--- a/plugin-designs/plugin-studio/plugin-studio.vue
+++ b/plugin-designs/plugin-studio/plugin-studio.vue
@@ -447,7 +447,8 @@ const WIDGET_CSS = `
[data-wb-icon]{display:grid;place-items:center;flex:none;color:#38bdf8}
[data-wb-icon] svg,[data-wb-chev] svg{width:20px;height:20px;display:block}
[data-wb-text]{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
-[data-widget-bubble][data-listening="true"]{width:min(300px,calc(100vw - 32px))}
+/* ★ WHILE RECORDING THE PILL DOES NOT BREATHE. The Driver: "it keeps RESIZING, kind of distracting — it should stay the same width". width alone was not enough: the bubble is inline-flex, so it still sizes to content wherever width loses — and it carries a max-width that the <=480px query overrides, which is exactly the phone case he was looking at. Truncating the text cannot fix it either: 33 CHARACTERS is 133px of "illi" and 344px of "MMM WOW", so a character count is not a width. min-width and max-width are pinned to the same value as width so no later rule and no viewport can let it grow or shrink; the text ellipsises inside it. */
+[data-widget-bubble][data-listening="true"]{width:min(300px,calc(100vw - 32px));min-width:min(300px,calc(100vw - 32px));max-width:min(300px,calc(100vw - 32px))}
[data-widget-bubble][data-listening="true"] [data-wb-text]{flex:1 1 auto}
[data-wb-dot],[data-wb-chev]{display:none;flex:none}
[data-wb-dot]{width:10px;height:10px;border-radius:50%;background:#ef4444}
@@ -465,6 +466,8 @@ const WIDGET_CSS = `
[data-studio-widgets$="left"]{left:max(8px,env(safe-area-inset-left))}
[data-widget-panel]{width:calc(100vw - 16px);max-width:none;height:60vh;height:60dvh}
[data-widget-bubble]{max-width:calc(100vw - 16px)}
+ /* ...but a RECORDING pill keeps its fixed width on a phone too, or it grows to the viewport. */
+ [data-widget-bubble][data-listening="true"]{width:min(300px,calc(100vw - 16px));min-width:min(300px,calc(100vw - 16px));max-width:min(300px,calc(100vw - 16px))}
}`
const WIDGET_ICON_OPEN = ''
const WIDGET_ICON_CLOSE = ''
diff --git a/plugin-designs/rudder-voice/rudder-voice.vue b/plugin-designs/rudder-voice/rudder-voice.vue
index 78978ed84..8136d6da7 100644
--- a/plugin-designs/rudder-voice/rudder-voice.vue
+++ b/plugin-designs/rudder-voice/rudder-voice.vue
@@ -1171,9 +1171,20 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 1
.compact .debug { order: 4; }
/* A phone-sized panel: less padding, and a shorter draft so it stays in view below the controls. */
@media (max-width: 480px) {
- .rudder { min-height: 100%; padding: 12px; gap: 10px; }
- .compose { min-height: 200px; }
- .draft { min-height: 180px; }
+ /* ★ THE TEXT AREA GETS THE LEFTOVER SPACE AND SCROLLS. The Driver on a phone: "a lot of header
+ space … fills the entire page … I can't scroll down in the text area and see everything". The
+ panel is capped at 60vh here, and a min-height on the draft cannot fix that: a MINIMUM makes
+ the box refuse to shrink, so whatever the header takes is pushed off the bottom and the
+ draft's own scrollbar never appears. Lowering it from 240 to 180 only moved the threshold.
+ So the column owns the height (min-height:0 is what lets a flex child shrink BELOW its
+ content, and is the whole fix), the draft takes what is left and scrolls inside it, and the
+ header gives back the space it was holding. */
+ .rudder { min-height: 0; height: 100%; padding: 10px; gap: 8px; display: flex; flex-direction: column; }
+ .compose { min-height: 0; flex: 1 1 0; display: flex; flex-direction: column; }
+ .draft { min-height: 0; flex: 1 1 0; overflow-y: auto; resize: none; padding: 10px; }
+ .top { gap: 8px; row-gap: 6px; }
+ .bar .name { font-size: 13px; }
+ .bar .status { padding: 2px 7px; font-size: 11.5px; }
/* Notices (engine offline, mic muted, …) sit below the draft here, so the draft stays in view. */
.notice, .hint { order: 1; }
.bottom { order: 2; }