@memberjunction/ng-conversations 6.2.0-edge.5 → 6.2.0-edge.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/dist/lib/components/attachment/image-viewer.component.d.ts +3 -1
  2. package/dist/lib/components/attachment/image-viewer.component.d.ts.map +1 -1
  3. package/dist/lib/components/attachment/image-viewer.component.js +5 -1
  4. package/dist/lib/components/attachment/image-viewer.component.js.map +1 -1
  5. package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
  6. package/dist/lib/components/collection/collection-view.component.js +1 -0
  7. package/dist/lib/components/collection/collection-view.component.js.map +1 -1
  8. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +188 -9
  9. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  10. package/dist/lib/components/conversation/conversation-chat-area.component.js +1333 -464
  11. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  12. package/dist/lib/components/conversation/conversation-mode-picker.component.js +2 -2
  13. package/dist/lib/components/conversation/conversation-mode-picker.component.js.map +1 -1
  14. package/dist/lib/components/conversation/conversation-remote-browser-controller.d.ts +109 -0
  15. package/dist/lib/components/conversation/conversation-remote-browser-controller.d.ts.map +1 -0
  16. package/dist/lib/components/conversation/conversation-remote-browser-controller.js +298 -0
  17. package/dist/lib/components/conversation/conversation-remote-browser-controller.js.map +1 -0
  18. package/dist/lib/components/message/agent-handoff-card.component.d.ts +102 -0
  19. package/dist/lib/components/message/agent-handoff-card.component.d.ts.map +1 -0
  20. package/dist/lib/components/message/agent-handoff-card.component.js +439 -0
  21. package/dist/lib/components/message/agent-handoff-card.component.js.map +1 -0
  22. package/dist/lib/components/message/message-input.component.d.ts +126 -59
  23. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  24. package/dist/lib/components/message/message-input.component.js +559 -554
  25. package/dist/lib/components/message/message-input.component.js.map +1 -1
  26. package/dist/lib/components/message/message-item.component.d.ts +34 -2
  27. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  28. package/dist/lib/components/message/message-item.component.js +678 -520
  29. package/dist/lib/components/message/message-item.component.js.map +1 -1
  30. package/dist/lib/components/message/message-list.component.d.ts +13 -1
  31. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  32. package/dist/lib/components/message/message-list.component.js +92 -39
  33. package/dist/lib/components/message/message-list.component.js.map +1 -1
  34. package/dist/lib/components/overlay/chat-overlay.component.d.ts +19 -0
  35. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  36. package/dist/lib/components/overlay/chat-overlay.component.js +125 -13
  37. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  38. package/dist/lib/components/project/project-form-modal.component.js +2 -2
  39. package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
  40. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js +1 -1
  41. package/dist/lib/components/realtime/interactive-component/run-view-component-artifact-source.js.map +1 -1
  42. package/dist/lib/components/realtime/media/media-channel-state.d.ts +5 -0
  43. package/dist/lib/components/realtime/media/media-channel-state.d.ts.map +1 -1
  44. package/dist/lib/components/realtime/media/media-channel-state.js +27 -1
  45. package/dist/lib/components/realtime/media/media-channel-state.js.map +1 -1
  46. package/dist/lib/components/realtime/media/media-channel.d.ts.map +1 -1
  47. package/dist/lib/components/realtime/media/media-channel.js +7 -2
  48. package/dist/lib/components/realtime/media/media-channel.js.map +1 -1
  49. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts +19 -2
  50. package/dist/lib/components/realtime/media/realtime-media-surface.component.d.ts.map +1 -1
  51. package/dist/lib/components/realtime/media/realtime-media-surface.component.js +59 -10
  52. package/dist/lib/components/realtime/media/realtime-media-surface.component.js.map +1 -1
  53. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +22 -6
  54. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  55. package/dist/lib/components/realtime/realtime-agent-banner.component.js +160 -98
  56. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  57. package/dist/lib/components/realtime/realtime-call-failure-notice.d.ts +13 -0
  58. package/dist/lib/components/realtime/realtime-call-failure-notice.d.ts.map +1 -0
  59. package/dist/lib/components/realtime/realtime-call-failure-notice.js +21 -0
  60. package/dist/lib/components/realtime/realtime-call-failure-notice.js.map +1 -0
  61. package/dist/lib/components/realtime/realtime-composer.component.d.ts +26 -3
  62. package/dist/lib/components/realtime/realtime-composer.component.d.ts.map +1 -1
  63. package/dist/lib/components/realtime/realtime-composer.component.js +226 -120
  64. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  65. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +73 -16
  66. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  67. package/dist/lib/components/realtime/realtime-session-overlay.component.js +219 -108
  68. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  69. package/dist/lib/components/realtime/realtime-ui-config.d.ts +9 -12
  70. package/dist/lib/components/realtime/realtime-ui-config.d.ts.map +1 -1
  71. package/dist/lib/components/realtime/realtime-ui-config.js +38 -18
  72. package/dist/lib/components/realtime/realtime-ui-config.js.map +1 -1
  73. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  74. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +34 -5
  75. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  76. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts +8 -2
  77. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts.map +1 -1
  78. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js +51 -10
  79. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js.map +1 -1
  80. package/dist/lib/components/realtime/whiteboard/whiteboard-channel-config.d.ts +46 -0
  81. package/dist/lib/components/realtime/whiteboard/whiteboard-channel-config.d.ts.map +1 -0
  82. package/dist/lib/components/realtime/whiteboard/whiteboard-channel-config.js +64 -0
  83. package/dist/lib/components/realtime/whiteboard/whiteboard-channel-config.js.map +1 -0
  84. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts +131 -9
  85. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.d.ts.map +1 -1
  86. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js +347 -38
  87. package/dist/lib/components/realtime/whiteboard/whiteboard-channel.js.map +1 -1
  88. package/dist/lib/conversations.module.d.ts +2 -1
  89. package/dist/lib/conversations.module.d.ts.map +1 -1
  90. package/dist/lib/conversations.module.js +9 -4
  91. package/dist/lib/conversations.module.js.map +1 -1
  92. package/dist/lib/events/chat-events.d.ts +5 -4
  93. package/dist/lib/events/chat-events.d.ts.map +1 -1
  94. package/dist/lib/events/chat-events.js +2 -2
  95. package/dist/lib/events/chat-events.js.map +1 -1
  96. package/dist/lib/models/agent-turn.model.d.ts +11 -7
  97. package/dist/lib/models/agent-turn.model.d.ts.map +1 -1
  98. package/dist/lib/models/agent-turn.model.js.map +1 -1
  99. package/dist/lib/services/active-tasks.service.d.ts +5 -0
  100. package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
  101. package/dist/lib/services/active-tasks.service.js +16 -0
  102. package/dist/lib/services/active-tasks.service.js.map +1 -1
  103. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  104. package/dist/lib/services/agent-state.service.js +7 -1
  105. package/dist/lib/services/agent-state.service.js.map +1 -1
  106. package/dist/lib/services/artifact-permission.service.d.ts.map +1 -1
  107. package/dist/lib/services/artifact-permission.service.js +2 -0
  108. package/dist/lib/services/artifact-permission.service.js.map +1 -1
  109. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  110. package/dist/lib/services/artifact-state.service.js +1 -0
  111. package/dist/lib/services/artifact-state.service.js.map +1 -1
  112. package/dist/lib/services/collection-permission.service.d.ts.map +1 -1
  113. package/dist/lib/services/collection-permission.service.js +1 -0
  114. package/dist/lib/services/collection-permission.service.js.map +1 -1
  115. package/dist/lib/services/conversation-agent.service.d.ts +38 -16
  116. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  117. package/dist/lib/services/conversation-agent.service.js +57 -71
  118. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  119. package/dist/lib/services/conversation-detail-window.store.d.ts +5 -0
  120. package/dist/lib/services/conversation-detail-window.store.d.ts.map +1 -1
  121. package/dist/lib/services/conversation-detail-window.store.js +52 -5
  122. package/dist/lib/services/conversation-detail-window.store.js.map +1 -1
  123. package/dist/lib/services/realtime-session-review.service.d.ts +2 -1
  124. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
  125. package/dist/lib/services/realtime-session-review.service.js.map +1 -1
  126. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  127. package/dist/lib/services/realtime-session.service.js +2 -1
  128. package/dist/lib/services/realtime-session.service.js.map +1 -1
  129. package/dist/lib/services/search.service.d.ts.map +1 -1
  130. package/dist/lib/services/search.service.js +1 -0
  131. package/dist/lib/services/search.service.js.map +1 -1
  132. package/dist/lib/utils/agent-failure-display.d.ts +14 -0
  133. package/dist/lib/utils/agent-failure-display.d.ts.map +1 -0
  134. package/dist/lib/utils/agent-failure-display.js +26 -0
  135. package/dist/lib/utils/agent-failure-display.js.map +1 -0
  136. package/dist/lib/utils/agent-handoff-map.d.ts +52 -0
  137. package/dist/lib/utils/agent-handoff-map.d.ts.map +1 -0
  138. package/dist/lib/utils/agent-handoff-map.js +270 -0
  139. package/dist/lib/utils/agent-handoff-map.js.map +1 -0
  140. package/dist/lib/utils/agent-turn-routing.d.ts +62 -7
  141. package/dist/lib/utils/agent-turn-routing.d.ts.map +1 -1
  142. package/dist/lib/utils/agent-turn-routing.js +147 -6
  143. package/dist/lib/utils/agent-turn-routing.js.map +1 -1
  144. package/dist/lib/utils/decision-routing.d.ts +17 -9
  145. package/dist/lib/utils/decision-routing.d.ts.map +1 -1
  146. package/dist/lib/utils/decision-routing.js +23 -14
  147. package/dist/lib/utils/decision-routing.js.map +1 -1
  148. package/dist/lib/utils/message-list-order.d.ts +13 -0
  149. package/dist/lib/utils/message-list-order.d.ts.map +1 -0
  150. package/dist/lib/utils/message-list-order.js +31 -0
  151. package/dist/lib/utils/message-list-order.js.map +1 -0
  152. package/dist/lib/utils/pin-state.d.ts +11 -0
  153. package/dist/lib/utils/pin-state.d.ts.map +1 -0
  154. package/dist/lib/utils/pin-state.js +9 -0
  155. package/dist/lib/utils/pin-state.js.map +1 -0
  156. package/dist/lib/utils/thread-replies.d.ts +34 -0
  157. package/dist/lib/utils/thread-replies.d.ts.map +1 -0
  158. package/dist/lib/utils/thread-replies.js +49 -0
  159. package/dist/lib/utils/thread-replies.js.map +1 -0
  160. package/dist/public-api.d.ts +6 -0
  161. package/dist/public-api.d.ts.map +1 -1
  162. package/dist/public-api.js +6 -0
  163. package/dist/public-api.js.map +1 -1
  164. package/package.json +36 -36
@@ -78,19 +78,32 @@ function RealtimeAgentBannerComponent_Conditional_1_Template(rf, ctx) { if (rf &
78
78
  i0.ɵɵadvance(6);
79
79
  i0.ɵɵconditional(ctx_r1.ShowStartLive ? 15 : -1);
80
80
  } }
81
- function RealtimeAgentBannerComponent_Conditional_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
82
- i0.ɵɵelement(0, "i", 24);
81
+ function RealtimeAgentBannerComponent_Conditional_2_Conditional_5_Conditional_1_Template(rf, ctx) { if (rf & 1) {
82
+ i0.ɵɵelement(0, "i", 25);
83
83
  } }
84
- function RealtimeAgentBannerComponent_Conditional_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
85
- i0.ɵɵelement(0, "span", 25);
84
+ function RealtimeAgentBannerComponent_Conditional_2_Conditional_5_Conditional_2_Template(rf, ctx) { if (rf & 1) {
85
+ i0.ɵɵelement(0, "span", 26);
86
86
  } if (rf & 2) {
87
- const ctx_r1 = i0.ɵɵnextContext(2);
87
+ const ctx_r1 = i0.ɵɵnextContext(3);
88
88
  i0.ɵɵattribute("data-state", ctx_r1.OrbState(ctx_r1.State));
89
89
  } }
90
- function RealtimeAgentBannerComponent_Conditional_2_Conditional_10_Template(rf, ctx) { if (rf & 1) {
90
+ function RealtimeAgentBannerComponent_Conditional_2_Conditional_5_Template(rf, ctx) { if (rf & 1) {
91
+ i0.ɵɵelementStart(0, "span", 23);
92
+ i0.ɵɵconditionalCreate(1, RealtimeAgentBannerComponent_Conditional_2_Conditional_5_Conditional_1_Template, 1, 0, "i", 25)(2, RealtimeAgentBannerComponent_Conditional_2_Conditional_5_Conditional_2_Template, 1, 1, "span", 26);
93
+ i0.ɵɵelementStart(3, "span", 27);
94
+ i0.ɵɵtext(4);
95
+ i0.ɵɵelementEnd()();
96
+ } if (rf & 2) {
97
+ const ctx_r1 = i0.ɵɵnextContext(2);
98
+ i0.ɵɵadvance();
99
+ i0.ɵɵconditional(ctx_r1.IsBusy(ctx_r1.State) ? 1 : 2);
100
+ i0.ɵɵadvance(3);
101
+ i0.ɵɵtextInterpolate(ctx_r1.StateLabel(ctx_r1.State));
102
+ } }
103
+ function RealtimeAgentBannerComponent_Conditional_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
91
104
  const _r5 = i0.ɵɵgetCurrentView();
92
105
  i0.ɵɵelementStart(0, "button", 28);
93
- i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_2_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MinimizeRequested.emit()); });
106
+ i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_2_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MinimizeRequested.emit()); });
94
107
  i0.ɵɵelement(1, "i", 29);
95
108
  i0.ɵɵelementEnd();
96
109
  } }
@@ -101,26 +114,32 @@ function RealtimeAgentBannerComponent_Conditional_2_Template(rf, ctx) { if (rf &
101
114
  i0.ɵɵelementStart(3, "span", 22);
102
115
  i0.ɵɵtext(4);
103
116
  i0.ɵɵelementEnd();
104
- i0.ɵɵelementStart(5, "span", 23);
105
- i0.ɵɵconditionalCreate(6, RealtimeAgentBannerComponent_Conditional_2_Conditional_6_Template, 1, 0, "i", 24)(7, RealtimeAgentBannerComponent_Conditional_2_Conditional_7_Template, 1, 1, "span", 25);
106
- i0.ɵɵelementStart(8, "span", 26);
107
- i0.ɵɵtext(9);
108
- i0.ɵɵelementEnd()()();
109
- i0.ɵɵconditionalCreate(10, RealtimeAgentBannerComponent_Conditional_2_Conditional_10_Template, 2, 0, "button", 27);
117
+ i0.ɵɵconditionalCreate(5, RealtimeAgentBannerComponent_Conditional_2_Conditional_5_Template, 5, 2, "span", 23);
118
+ i0.ɵɵelementEnd();
119
+ i0.ɵɵconditionalCreate(6, RealtimeAgentBannerComponent_Conditional_2_Conditional_6_Template, 2, 0, "button", 24);
110
120
  } if (rf & 2) {
111
121
  const ctx_r1 = i0.ɵɵnextContext();
112
122
  i0.ɵɵadvance(2);
113
123
  i0.ɵɵtextInterpolate(ctx_r1.AgentName.charAt(0));
114
124
  i0.ɵɵadvance(2);
115
125
  i0.ɵɵtextInterpolate(ctx_r1.AgentName);
116
- i0.ɵɵadvance(2);
117
- i0.ɵɵconditional(ctx_r1.IsBusy(ctx_r1.State) ? 6 : 7);
118
- i0.ɵɵadvance(3);
119
- i0.ɵɵtextInterpolate(ctx_r1.StateLabel(ctx_r1.State));
120
126
  i0.ɵɵadvance();
121
- i0.ɵɵconditional(ctx_r1.ShowMinimize ? 10 : -1);
127
+ i0.ɵɵconditional(!ctx_r1.HideState ? 5 : -1);
128
+ i0.ɵɵadvance();
129
+ i0.ɵɵconditional(ctx_r1.ShowMinimize ? 6 : -1);
130
+ } }
131
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_7_Template(rf, ctx) { if (rf & 1) {
132
+ i0.ɵɵelementStart(0, "span", 33);
133
+ i0.ɵɵtext(1, "speaking as ");
134
+ i0.ɵɵelementStart(2, "b");
135
+ i0.ɵɵtext(3);
136
+ i0.ɵɵelementEnd()();
137
+ } if (rf & 2) {
138
+ const ctx_r1 = i0.ɵɵnextContext(2);
139
+ i0.ɵɵadvance(3);
140
+ i0.ɵɵtextInterpolate(ctx_r1.AgentName);
122
141
  } }
123
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_11_Template(rf, ctx) { if (rf & 1) {
142
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_8_Template(rf, ctx) { if (rf & 1) {
124
143
  i0.ɵɵelementStart(0, "span", 34);
125
144
  i0.ɵɵtext(1);
126
145
  i0.ɵɵelementEnd();
@@ -130,97 +149,123 @@ function RealtimeAgentBannerComponent_Conditional_3_Conditional_11_Template(rf,
130
149
  i0.ɵɵadvance();
131
150
  i0.ɵɵtextInterpolate1("\u00B7 ", ctx_r1.ModelName);
132
151
  } }
133
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_12_Template(rf, ctx) { if (rf & 1) {
152
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_9_Template(rf, ctx) { if (rf & 1) {
134
153
  const _r6 = i0.ɵɵgetCurrentView();
135
154
  i0.ɵɵelementStart(0, "button", 16);
136
- i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_12_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OpenSession()); });
155
+ i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_9_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OpenSession()); });
137
156
  i0.ɵɵelement(1, "i", 17);
138
157
  i0.ɵɵelementStart(2, "span");
139
158
  i0.ɵɵtext(3, "Open session");
140
159
  i0.ɵɵelementEnd()();
141
160
  } }
142
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Template(rf, ctx) { if (rf & 1) {
143
- i0.ɵɵelement(0, "i", 24);
161
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_10_Conditional_1_Template(rf, ctx) { if (rf & 1) {
162
+ i0.ɵɵelement(0, "i", 25);
144
163
  } }
145
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_15_Template(rf, ctx) { if (rf & 1) {
146
- i0.ɵɵelementStart(0, "div", 41);
164
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_10_Conditional_2_Template(rf, ctx) { if (rf & 1) {
165
+ i0.ɵɵelementStart(0, "div", 42);
147
166
  i0.ɵɵelement(1, "span")(2, "span")(3, "span")(4, "span")(5, "span")(6, "span")(7, "span")(8, "span");
148
167
  i0.ɵɵelementEnd();
149
168
  } if (rf & 2) {
150
- const ctx_r1 = i0.ɵɵnextContext(2);
169
+ const ctx_r1 = i0.ɵɵnextContext(3);
151
170
  i0.ɵɵclassProp("waveform--idle", ctx_r1.State !== "speaking");
152
171
  } }
153
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_19_Template(rf, ctx) { if (rf & 1) {
172
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_10_Template(rf, ctx) { if (rf & 1) {
173
+ i0.ɵɵelementStart(0, "div", 39);
174
+ i0.ɵɵconditionalCreate(1, RealtimeAgentBannerComponent_Conditional_3_Conditional_10_Conditional_1_Template, 1, 0, "i", 25)(2, RealtimeAgentBannerComponent_Conditional_3_Conditional_10_Conditional_2_Template, 9, 2, "div", 40);
175
+ i0.ɵɵelementStart(3, "span", 41);
176
+ i0.ɵɵtext(4);
177
+ i0.ɵɵelementEnd()();
178
+ } if (rf & 2) {
179
+ const ctx_r1 = i0.ɵɵnextContext(2);
180
+ i0.ɵɵclassProp("banner__state--busy", ctx_r1.IsBusy(ctx_r1.State));
181
+ i0.ɵɵadvance();
182
+ i0.ɵɵconditional(ctx_r1.IsBusy(ctx_r1.State) ? 1 : 2);
183
+ i0.ɵɵadvance(3);
184
+ i0.ɵɵtextInterpolate(ctx_r1.StateLabel(ctx_r1.State));
185
+ } }
186
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_12_Template(rf, ctx) { if (rf & 1) {
154
187
  const _r7 = i0.ɵɵgetCurrentView();
155
- i0.ɵɵelementStart(0, "button", 42);
156
- i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_19_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleGear($event)); });
157
- i0.ɵɵelement(1, "i", 43);
188
+ i0.ɵɵelementStart(0, "button", 43);
189
+ i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_12_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleGear($event)); });
190
+ i0.ɵɵelement(1, "i", 44);
158
191
  i0.ɵɵelementEnd();
159
192
  } if (rf & 2) {
160
193
  const ctx_r1 = i0.ɵɵnextContext(2);
161
194
  i0.ɵɵclassProp("iconb--on", ctx_r1.GearOpen || ctx_r1.DevMode);
162
195
  i0.ɵɵattribute("aria-expanded", ctx_r1.GearOpen);
163
196
  } }
164
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_20_Template(rf, ctx) { if (rf & 1) {
197
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_13_Template(rf, ctx) { if (rf & 1) {
165
198
  const _r8 = i0.ɵɵgetCurrentView();
166
- i0.ɵɵelementStart(0, "button", 44);
167
- i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_20_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MinimizeRequested.emit()); });
168
- i0.ɵɵelement(1, "i", 45);
199
+ i0.ɵɵelementStart(0, "button", 45);
200
+ i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_13_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.MinimizeRequested.emit()); });
201
+ i0.ɵɵelement(1, "i", 46);
169
202
  i0.ɵɵelementEnd();
170
203
  } }
171
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Conditional_3_For_5_Template(rf, ctx) { if (rf & 1) {
172
- const _r10 = i0.ɵɵgetCurrentView();
204
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_3_For_5_Template(rf, ctx) { if (rf & 1) {
205
+ const _r9 = i0.ɵɵgetCurrentView();
173
206
  i0.ɵɵelementStart(0, "button", 56);
174
- i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Conditional_3_For_5_Template_button_click_0_listener() { const d_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SelectDensity(d_r11.Key)); });
207
+ i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_3_For_5_Template_button_click_0_listener() { const d_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.SelectDensity(d_r10.Key)); });
175
208
  i0.ɵɵtext(1);
176
209
  i0.ɵɵelementEnd();
177
210
  } if (rf & 2) {
178
- const d_r11 = ctx.$implicit;
211
+ const d_r10 = ctx.$implicit;
179
212
  const ctx_r1 = i0.ɵɵnextContext(4);
180
- i0.ɵɵclassProp("on", ctx_r1.Density === d_r11.Key);
181
- i0.ɵɵattribute("aria-checked", ctx_r1.Density === d_r11.Key);
213
+ i0.ɵɵclassProp("on", ctx_r1.Density === d_r10.Key);
214
+ i0.ɵɵattribute("aria-checked", ctx_r1.Density === d_r10.Key);
182
215
  i0.ɵɵadvance();
183
- i0.ɵɵtextInterpolate(d_r11.Label);
216
+ i0.ɵɵtextInterpolate(d_r10.Label);
184
217
  } }
185
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Conditional_3_Template(rf, ctx) { if (rf & 1) {
186
- i0.ɵɵelementStart(0, "div", 50)(1, "span", 51);
218
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_3_Template(rf, ctx) { if (rf & 1) {
219
+ i0.ɵɵelementStart(0, "div", 51)(1, "span", 52);
187
220
  i0.ɵɵtext(2, "Density");
188
221
  i0.ɵɵelementEnd();
189
- i0.ɵɵelementStart(3, "div", 52);
190
- i0.ɵɵrepeaterCreate(4, RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Conditional_3_For_5_Template, 2, 4, "button", 53, _forTrack0);
222
+ i0.ɵɵelementStart(3, "div", 53);
223
+ i0.ɵɵrepeaterCreate(4, RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_3_For_5_Template, 2, 4, "button", 54, _forTrack0);
191
224
  i0.ɵɵelementEnd()();
192
- i0.ɵɵelementStart(6, "div", 54);
225
+ i0.ɵɵelementStart(6, "div", 55);
193
226
  i0.ɵɵtext(7, "Simple returns to the pure-audio surface. Auto grows the console as you use it.");
194
227
  i0.ɵɵelementEnd();
195
- i0.ɵɵelement(8, "div", 55);
196
228
  } if (rf & 2) {
197
229
  const ctx_r1 = i0.ɵɵnextContext(3);
198
230
  i0.ɵɵadvance(4);
199
231
  i0.ɵɵrepeater(ctx_r1.Densities);
200
232
  } }
201
- function RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Template(rf, ctx) { if (rf & 1) {
202
- const _r9 = i0.ɵɵgetCurrentView();
203
- i0.ɵɵelementStart(0, "div", 46);
204
- i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Template_div_click_0_listener($event) { return $event.stopPropagation(); });
205
- i0.ɵɵelementStart(1, "div", 47);
233
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_4_Template(rf, ctx) { if (rf & 1) {
234
+ i0.ɵɵelement(0, "div", 49);
235
+ } }
236
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_5_Template(rf, ctx) { if (rf & 1) {
237
+ const _r11 = i0.ɵɵgetCurrentView();
238
+ i0.ɵɵelementStart(0, "button", 57);
239
+ i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ToggleDev()); });
240
+ i0.ɵɵelement(1, "i", 58);
241
+ i0.ɵɵtext(2);
242
+ i0.ɵɵelementEnd();
243
+ } if (rf & 2) {
244
+ const ctx_r1 = i0.ɵɵnextContext(3);
245
+ i0.ɵɵattribute("aria-pressed", ctx_r1.DevMode);
246
+ i0.ɵɵadvance();
247
+ i0.ɵɵproperty("ngClass", ctx_r1.DevMode ? "fa-toggle-on" : "fa-toggle-off");
248
+ i0.ɵɵadvance();
249
+ i0.ɵɵtextInterpolate1(" Developer links ", ctx_r1.DevMode ? "on" : "off", " ");
250
+ } }
251
+ function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Template(rf, ctx) { if (rf & 1) {
252
+ i0.ɵɵelementStart(0, "div", 47);
253
+ i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Template_div_click_0_listener($event) { return $event.stopPropagation(); });
254
+ i0.ɵɵelementStart(1, "div", 48);
206
255
  i0.ɵɵtext(2, "Interface");
207
256
  i0.ɵɵelementEnd();
208
- i0.ɵɵconditionalCreate(3, RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Conditional_3_Template, 9, 0);
209
- i0.ɵɵelementStart(4, "button", 48);
210
- i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ToggleDev()); });
211
- i0.ɵɵelement(5, "i", 49);
212
- i0.ɵɵtext(6);
213
- i0.ɵɵelementEnd()();
257
+ i0.ɵɵconditionalCreate(3, RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_3_Template, 8, 0);
258
+ i0.ɵɵconditionalCreate(4, RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_4_Template, 1, 0, "div", 49);
259
+ i0.ɵɵconditionalCreate(5, RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Conditional_5_Template, 3, 3, "button", 50);
260
+ i0.ɵɵelementEnd();
214
261
  } if (rf & 2) {
215
262
  const ctx_r1 = i0.ɵɵnextContext(2);
216
263
  i0.ɵɵadvance(3);
217
264
  i0.ɵɵconditional(ctx_r1.ShowDensityPicker ? 3 : -1);
218
265
  i0.ɵɵadvance();
219
- i0.ɵɵattribute("aria-pressed", ctx_r1.DevMode);
220
- i0.ɵɵadvance();
221
- i0.ɵɵproperty("ngClass", ctx_r1.DevMode ? "fa-toggle-on" : "fa-toggle-off");
266
+ i0.ɵɵconditional(ctx_r1.ShowDensityPicker && ctx_r1.AllowDevLinks ? 4 : -1);
222
267
  i0.ɵɵadvance();
223
- i0.ɵɵtextInterpolate1(" Developer links ", ctx_r1.DevMode ? "on" : "off", " ");
268
+ i0.ɵɵconditional(ctx_r1.AllowDevLinks ? 5 : -1);
224
269
  } }
225
270
  function RealtimeAgentBannerComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
226
271
  i0.ɵɵelement(0, "div", 30);
@@ -231,47 +276,35 @@ function RealtimeAgentBannerComponent_Conditional_3_Template(rf, ctx) { if (rf &
231
276
  i0.ɵɵelement(5, "i", 32);
232
277
  i0.ɵɵtext(6, " Co-Agent");
233
278
  i0.ɵɵelementEnd();
234
- i0.ɵɵelementStart(7, "span", 33);
235
- i0.ɵɵtext(8, "speaking as ");
236
- i0.ɵɵelementStart(9, "b");
237
- i0.ɵɵtext(10);
238
- i0.ɵɵelementEnd()();
239
- i0.ɵɵconditionalCreate(11, RealtimeAgentBannerComponent_Conditional_3_Conditional_11_Template, 2, 2, "span", 34);
240
- i0.ɵɵconditionalCreate(12, RealtimeAgentBannerComponent_Conditional_3_Conditional_12_Template, 4, 0, "button", 8);
279
+ i0.ɵɵconditionalCreate(7, RealtimeAgentBannerComponent_Conditional_3_Conditional_7_Template, 4, 1, "span", 33);
280
+ i0.ɵɵconditionalCreate(8, RealtimeAgentBannerComponent_Conditional_3_Conditional_8_Template, 2, 2, "span", 34);
281
+ i0.ɵɵconditionalCreate(9, RealtimeAgentBannerComponent_Conditional_3_Conditional_9_Template, 4, 0, "button", 8);
241
282
  i0.ɵɵelementEnd();
242
- i0.ɵɵelementStart(13, "div", 35);
243
- i0.ɵɵconditionalCreate(14, RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Template, 1, 0, "i", 24)(15, RealtimeAgentBannerComponent_Conditional_3_Conditional_15_Template, 9, 2, "div", 36);
244
- i0.ɵɵelementStart(16, "span", 37);
245
- i0.ɵɵtext(17);
246
- i0.ɵɵelementEnd()();
247
- i0.ɵɵelementStart(18, "div", 12);
248
- i0.ɵɵconditionalCreate(19, RealtimeAgentBannerComponent_Conditional_3_Conditional_19_Template, 2, 3, "button", 38);
249
- i0.ɵɵconditionalCreate(20, RealtimeAgentBannerComponent_Conditional_3_Conditional_20_Template, 2, 0, "button", 39);
283
+ i0.ɵɵconditionalCreate(10, RealtimeAgentBannerComponent_Conditional_3_Conditional_10_Template, 5, 4, "div", 35);
284
+ i0.ɵɵelementStart(11, "div", 12);
285
+ i0.ɵɵconditionalCreate(12, RealtimeAgentBannerComponent_Conditional_3_Conditional_12_Template, 2, 3, "button", 36);
286
+ i0.ɵɵconditionalCreate(13, RealtimeAgentBannerComponent_Conditional_3_Conditional_13_Template, 2, 0, "button", 37);
250
287
  i0.ɵɵelementEnd();
251
- i0.ɵɵconditionalCreate(21, RealtimeAgentBannerComponent_Conditional_3_Conditional_21_Template, 7, 4, "div", 40);
288
+ i0.ɵɵconditionalCreate(14, RealtimeAgentBannerComponent_Conditional_3_Conditional_14_Template, 6, 3, "div", 38);
252
289
  } if (rf & 2) {
253
290
  const ctx_r1 = i0.ɵɵnextContext();
254
291
  i0.ɵɵattribute("data-state", ctx_r1.OrbState(ctx_r1.State));
255
292
  i0.ɵɵadvance(3);
256
293
  i0.ɵɵtextInterpolate1("Voice for ", ctx_r1.AgentName);
257
- i0.ɵɵadvance(7);
258
- i0.ɵɵtextInterpolate(ctx_r1.AgentName);
259
- i0.ɵɵadvance();
260
- i0.ɵɵconditional(ctx_r1.ModelName ? 11 : -1);
294
+ i0.ɵɵadvance(4);
295
+ i0.ɵɵconditional(!ctx_r1.HideState ? 7 : -1);
261
296
  i0.ɵɵadvance();
262
- i0.ɵɵconditional(ctx_r1.ShowOpenSession ? 12 : -1);
297
+ i0.ɵɵconditional(ctx_r1.ModelName ? 8 : -1);
263
298
  i0.ɵɵadvance();
264
- i0.ɵɵclassProp("banner__state--busy", ctx_r1.IsBusy(ctx_r1.State));
299
+ i0.ɵɵconditional(ctx_r1.ShowOpenSession ? 9 : -1);
265
300
  i0.ɵɵadvance();
266
- i0.ɵɵconditional(ctx_r1.IsBusy(ctx_r1.State) ? 14 : 15);
267
- i0.ɵɵadvance(3);
268
- i0.ɵɵtextInterpolate(ctx_r1.StateLabel(ctx_r1.State));
301
+ i0.ɵɵconditional(!ctx_r1.HideState ? 10 : -1);
269
302
  i0.ɵɵadvance(2);
270
- i0.ɵɵconditional(ctx_r1.ShowGear ? 19 : -1);
303
+ i0.ɵɵconditional(ctx_r1.ShowGear ? 12 : -1);
271
304
  i0.ɵɵadvance();
272
- i0.ɵɵconditional(ctx_r1.ShowMinimize ? 20 : -1);
305
+ i0.ɵɵconditional(ctx_r1.ShowMinimize ? 13 : -1);
273
306
  i0.ɵɵadvance();
274
- i0.ɵɵconditional(ctx_r1.GearOpen ? 21 : -1);
307
+ i0.ɵɵconditional(ctx_r1.GearOpen ? 14 : -1);
275
308
  } }
276
309
  /**
277
310
  * The call overlay's UNIFIED APP-BAR (per Redesign A — `plans/realtime/mockups/redesign-a.html`):
@@ -304,6 +337,11 @@ export class RealtimeAgentBannerComponent {
304
337
  * Default `false` (the full console banner is unchanged).
305
338
  */
306
339
  Compact = false;
340
+ /**
341
+ * Whether to suppress the turn-state pill and redundant "speaking as" label in the banner
342
+ * because the center hero orb is already displaying the agent's name and live turn state.
343
+ */
344
+ HideState = false;
307
345
  /** Display name of the agent the voice session fronts (e.g. "Sage"). */
308
346
  AgentName = 'the agent';
309
347
  /**
@@ -330,20 +368,38 @@ export class RealtimeAgentBannerComponent {
330
368
  ReviewStartedAt = null;
331
369
  /** When reviewing: when the past session closed (null while it is still open). */
332
370
  ReviewClosedAt = null;
333
- /** When reviewing: why the past session closed (`Explicit` | `Janitor` | `Shutdown` | `Error`), when known. */
371
+ /** When reviewing: why the past session closed (`Explicit` | `Janitor` | `Shutdown` | `Error` | `TimeLimit` | `Idle`), when known. */
334
372
  ReviewCloseReason = null;
335
373
  // ── App-bar action cluster (disclosure-gated by the overlay) ────────────────
336
374
  // STATE + WINDOW-CHROME only. Captions & End were removed (they duplicated the bottom dock's
337
375
  // controls — one home per control), and "pure audio" was folded into the gear's Density = Simple.
338
- /** Whether the gear (density escape hatch + dev toggle) renders (disclosure level 2+). */
339
- ShowGear = false;
376
+ /**
377
+ * Whether the gear (density escape hatch + dev toggle) renders (disclosure level 2+). Taking the
378
+ * gear away also closes its popover, so no empty popover outlives the button that opened it.
379
+ */
380
+ set ShowGear(value) {
381
+ this._showGear = value;
382
+ if (!value) {
383
+ this.GearOpen = false;
384
+ }
385
+ }
386
+ get ShowGear() {
387
+ return this._showGear;
388
+ }
389
+ _showGear = false;
340
390
  /**
341
391
  * Whether the interface-density segmented control renders inside the gear popover.
342
392
  * Default `true` (historical behaviour); a host may hide it via the overlay's
343
- * `[ShowDensityPicker]` input. The gear itself (and its developer-links toggle) still
344
- * renders when {@link ShowGear} is true even if the density picker is hidden.
393
+ * `[ShowDensityPicker]` input. The gear itself still renders when {@link ShowGear} is true
394
+ * even if the density picker is hidden; its developer-links toggle renders only when
395
+ * {@link AllowDevLinks} is also true.
345
396
  */
346
397
  ShowDensityPicker = true;
398
+ /**
399
+ * Host ceiling for developer links: `false` removes the gear's "Developer links" toggle.
400
+ * Per-session {@link DevMode} still decides whether links render when allowed.
401
+ */
402
+ AllowDevLinks = true;
347
403
  /** Whether the Minimize control renders (live sessions only). */
348
404
  ShowMinimize = false;
349
405
  /** Review only: whether the "Start live session" action renders. */
@@ -417,6 +473,8 @@ export class RealtimeAgentBannerComponent {
417
473
  switch (this.ReviewCloseReason) {
418
474
  case 'Explicit': return 'Ended by user';
419
475
  case 'Janitor': return 'Closed by janitor';
476
+ case 'TimeLimit': return 'Time limit';
477
+ case 'Idle': return 'Idle — no activity';
420
478
  case 'Shutdown': return 'Closed at shutdown';
421
479
  case 'Error': return 'Ended with error';
422
480
  default: return '';
@@ -457,9 +515,9 @@ export class RealtimeAgentBannerComponent {
457
515
  static ɵfac = function RealtimeAgentBannerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RealtimeAgentBannerComponent)(); };
458
516
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RealtimeAgentBannerComponent, selectors: [["mj-realtime-agent-banner"]], hostBindings: function RealtimeAgentBannerComponent_HostBindings(rf, ctx) { if (rf & 1) {
459
517
  i0.ɵɵlistener("click", function RealtimeAgentBannerComponent_click_HostBindingHandler() { return ctx.OnDocumentClick(); }, i0.ɵɵresolveDocument);
460
- } }, inputs: { State: "State", Compact: "Compact", AgentName: "AgentName", ErrorLabel: "ErrorLabel", ModelName: "ModelName", DevMode: "DevMode", SessionID: "SessionID", ReviewMode: "ReviewMode", ReviewStartedAt: "ReviewStartedAt", ReviewClosedAt: "ReviewClosedAt", ReviewCloseReason: "ReviewCloseReason", ShowGear: "ShowGear", ShowDensityPicker: "ShowDensityPicker", ShowMinimize: "ShowMinimize", ShowStartLive: "ShowStartLive", Density: "Density" }, outputs: { OpenSessionRequested: "OpenSessionRequested", DevModeToggled: "DevModeToggled", DensityChanged: "DensityChanged", MinimizeRequested: "MinimizeRequested", StartLiveRequested: "StartLiveRequested", CloseRequested: "CloseRequested" }, decls: 4, vars: 5, consts: [[1, "banner"], ["aria-hidden", "true", 1, "agent-orb", "agent-orb--review"], [1, "banner__id"], [1, "banner__name"], [1, "pill", "pill--review"], ["aria-hidden", "true", 1, "fa-solid", "fa-clock-rotate-left"], [1, "banner__for", "banner__range"], [1, "pill", "pill--close-reason", 3, "title"], ["type", "button", "title", "Open the agent session record", 1, "dev-link"], [1, "banner__state", "banner__state--review"], ["aria-hidden", "true", 1, "fa-solid", "fa-box-archive"], [1, "banner__state-label", "banner__state-label--review"], [1, "bar-actions"], ["type", "button", "title", "Resume this session as a new live call", 1, "start-live-pill"], ["type", "button", "title", "Close review", "aria-label", "Close session review", 1, "iconb", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["type", "button", "title", "Open the agent session record", 1, "dev-link", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], ["type", "button", "title", "Resume this session as a new live call", 1, "start-live-pill", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-phone"], [1, "banner__id", "banner__id--compact"], ["aria-hidden", "true", 1, "banner__avatar"], [1, "banner__name", "banner__name--compact"], [1, "banner__state-chip"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["aria-hidden", "true", 1, "banner__state-dot"], [1, "banner__state-chip-label"], ["type", "button", "title", "Hide the call view \u2014 the call stays live", "aria-label", "Minimize the call view", 1, "iconb", "banner__minimize--compact"], ["type", "button", "title", "Hide the call view \u2014 the call stays live", "aria-label", "Minimize the call view", 1, "iconb", "banner__minimize--compact", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-minus"], ["aria-hidden", "true", 1, "agent-orb"], [1, "pill", "pill--sage"], ["aria-hidden", "true", 1, "fa-solid", "fa-feather"], [1, "banner__for"], [1, "banner__model", 3, "title"], [1, "banner__state"], ["aria-hidden", "true", 1, "waveform", 3, "waveform--idle"], [1, "banner__state-label"], ["type", "button", "title", "Interface density & developer links", 1, "iconb", 3, "iconb--on"], ["type", "button", "title", "Hide the call view \u2014 the call stays live", "aria-label", "Minimize the call view", 1, "iconb"], ["role", "menu", "aria-label", "Interface settings", 1, "gear-pop"], ["aria-hidden", "true", 1, "waveform"], ["type", "button", "title", "Interface density & developer links", 1, "iconb", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-gear"], ["type", "button", "title", "Hide the call view \u2014 the call stays live", "aria-label", "Minimize the call view", 1, "iconb", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-down-left-and-up-right-to-center"], ["role", "menu", "aria-label", "Interface settings", 1, "gear-pop", 3, "click"], [1, "gp-h"], ["type", "button", 1, "gp-link", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", 3, "ngClass"], [1, "gp-row"], [1, "gp-l"], ["role", "radiogroup", "aria-label", "Interface density", 1, "gp-seg"], ["type", "button", "role", "radio", 3, "on"], [1, "gp-note"], [1, "gp-div"], ["type", "button", "role", "radio", 3, "click"]], template: function RealtimeAgentBannerComponent_Template(rf, ctx) { if (rf & 1) {
518
+ } }, inputs: { State: "State", Compact: "Compact", HideState: "HideState", AgentName: "AgentName", ErrorLabel: "ErrorLabel", ModelName: "ModelName", DevMode: "DevMode", SessionID: "SessionID", ReviewMode: "ReviewMode", ReviewStartedAt: "ReviewStartedAt", ReviewClosedAt: "ReviewClosedAt", ReviewCloseReason: "ReviewCloseReason", ShowGear: "ShowGear", ShowDensityPicker: "ShowDensityPicker", AllowDevLinks: "AllowDevLinks", ShowMinimize: "ShowMinimize", ShowStartLive: "ShowStartLive", Density: "Density" }, outputs: { OpenSessionRequested: "OpenSessionRequested", DevModeToggled: "DevModeToggled", DensityChanged: "DensityChanged", MinimizeRequested: "MinimizeRequested", StartLiveRequested: "StartLiveRequested", CloseRequested: "CloseRequested" }, decls: 4, vars: 5, consts: [[1, "banner"], ["aria-hidden", "true", 1, "agent-orb", "agent-orb--review"], [1, "banner__id"], [1, "banner__name"], [1, "pill", "pill--review"], ["aria-hidden", "true", 1, "fa-solid", "fa-clock-rotate-left"], [1, "banner__for", "banner__range"], [1, "pill", "pill--close-reason", 3, "title"], ["type", "button", "title", "Open the agent session record", 1, "dev-link"], [1, "banner__state", "banner__state--review"], ["aria-hidden", "true", 1, "fa-solid", "fa-box-archive"], [1, "banner__state-label", "banner__state-label--review"], [1, "bar-actions"], ["type", "button", "title", "Resume this session as a new live call", 1, "start-live-pill"], ["type", "button", "title", "Close review", "aria-label", "Close session review", 1, "iconb", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["type", "button", "title", "Open the agent session record", 1, "dev-link", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], ["type", "button", "title", "Resume this session as a new live call", 1, "start-live-pill", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-phone"], [1, "banner__id", "banner__id--compact"], ["aria-hidden", "true", 1, "banner__avatar"], [1, "banner__name", "banner__name--compact"], [1, "banner__state-chip"], ["type", "button", "title", "Hide the call view \u2014 the call stays live", "aria-label", "Minimize the call view", 1, "iconb", "banner__minimize--compact"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["aria-hidden", "true", 1, "banner__state-dot"], [1, "banner__state-chip-label"], ["type", "button", "title", "Hide the call view \u2014 the call stays live", "aria-label", "Minimize the call view", 1, "iconb", "banner__minimize--compact", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-minus"], ["aria-hidden", "true", 1, "agent-orb"], [1, "pill", "pill--sage"], ["aria-hidden", "true", 1, "fa-solid", "fa-feather"], [1, "banner__for"], [1, "banner__model", 3, "title"], [1, "banner__state", 3, "banner__state--busy"], ["type", "button", "title", "Interface density & developer links", 1, "iconb", 3, "iconb--on"], ["type", "button", "title", "Hide the call view \u2014 the call stays live", "aria-label", "Minimize the call view", 1, "iconb"], ["role", "menu", "aria-label", "Interface settings", 1, "gear-pop"], [1, "banner__state"], ["aria-hidden", "true", 1, "waveform", 3, "waveform--idle"], [1, "banner__state-label"], ["aria-hidden", "true", 1, "waveform"], ["type", "button", "title", "Interface density & developer links", 1, "iconb", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-gear"], ["type", "button", "title", "Hide the call view \u2014 the call stays live", "aria-label", "Minimize the call view", 1, "iconb", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-down-left-and-up-right-to-center"], ["role", "menu", "aria-label", "Interface settings", 1, "gear-pop", 3, "click"], [1, "gp-h"], [1, "gp-div"], ["type", "button", 1, "gp-link"], [1, "gp-row"], [1, "gp-l"], ["role", "radiogroup", "aria-label", "Interface density", 1, "gp-seg"], ["type", "button", "role", "radio", 3, "on"], [1, "gp-note"], ["type", "button", "role", "radio", 3, "click"], ["type", "button", 1, "gp-link", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", 3, "ngClass"]], template: function RealtimeAgentBannerComponent_Template(rf, ctx) { if (rf & 1) {
461
519
  i0.ɵɵelementStart(0, "div", 0);
462
- i0.ɵɵconditionalCreate(1, RealtimeAgentBannerComponent_Conditional_1_Template, 18, 5)(2, RealtimeAgentBannerComponent_Conditional_2_Template, 11, 5)(3, RealtimeAgentBannerComponent_Conditional_3_Template, 22, 12);
520
+ i0.ɵɵconditionalCreate(1, RealtimeAgentBannerComponent_Conditional_1_Template, 18, 5)(2, RealtimeAgentBannerComponent_Conditional_2_Template, 7, 4)(3, RealtimeAgentBannerComponent_Conditional_3_Template, 15, 9);
463
521
  i0.ɵɵelementEnd();
464
522
  } if (rf & 2) {
465
523
  i0.ɵɵclassProp("banner--review", ctx.ReviewMode)("banner--compact", ctx.Compact && !ctx.ReviewMode);
@@ -469,12 +527,14 @@ export class RealtimeAgentBannerComponent {
469
527
  }
470
528
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RealtimeAgentBannerComponent, [{
471
529
  type: Component,
472
- args: [{ standalone: true, selector: 'mj-realtime-agent-banner', imports: [CommonModule], template: "<div class=\"banner\" [class.banner--review]=\"ReviewMode\" [class.banner--compact]=\"Compact && !ReviewMode\">\n @if (ReviewMode) {\n <!-- SESSION REVIEW: static orb \u00B7 name \u00B7 review badge \u00B7 started\u2192closed \u00B7 close-reason chip,\n with the review's exit actions up here in the header bar (Start live leads, Close trails). -->\n <div class=\"agent-orb agent-orb--review\" aria-hidden=\"true\"></div>\n\n <div class=\"banner__id\">\n <span class=\"banner__name\">Voice for {{ AgentName }}</span>\n <span class=\"pill pill--review\"><i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i> Session review</span>\n @if (ReviewRangeLabel) {\n <span class=\"banner__for banner__range\">{{ ReviewRangeLabel }}</span>\n }\n @if (ReviewCloseReasonLabel) {\n <span class=\"pill pill--close-reason\" [title]=\"'Close reason: ' + ReviewCloseReason\">{{ ReviewCloseReasonLabel }}</span>\n }\n @if (ShowOpenSession) {\n <button type=\"button\" class=\"dev-link\" (click)=\"OpenSession()\"\n title=\"Open the agent session record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Open session</span>\n </button>\n }\n </div>\n\n <div class=\"banner__state banner__state--review\">\n <i class=\"fa-solid fa-box-archive\" aria-hidden=\"true\"></i>\n <span class=\"banner__state-label banner__state-label--review\">Reviewing past session</span>\n </div>\n\n <div class=\"bar-actions\">\n @if (ShowStartLive) {\n <button type=\"button\" class=\"start-live-pill\" (click)=\"StartLiveRequested.emit()\"\n title=\"Resume this session as a new live call\">\n <i class=\"fa-solid fa-phone\" aria-hidden=\"true\"></i>\n <span>Start live session</span>\n </button>\n }\n <button type=\"button\" class=\"iconb\" (click)=\"CloseRequested.emit()\"\n title=\"Close review\" aria-label=\"Close session review\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n } @else if (Compact) {\n <!-- COMPACT (Calm Orb \u00B7 overlay): a tiny identity + state row only. No duplicate orb,\n no state pill, no headphones / gear / expand \u2014 the body shows the big orb + name +\n state, and the lean dock owns the actions. Minimize stays reachable here. -->\n <div class=\"banner__id banner__id--compact\">\n <span class=\"banner__avatar\" aria-hidden=\"true\">{{ AgentName.charAt(0) }}</span>\n <span class=\"banner__name banner__name--compact\">{{ AgentName }}</span>\n <span class=\"banner__state-chip\">\n @if (IsBusy(State)) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <span class=\"banner__state-dot\" [attr.data-state]=\"OrbState(State)\" aria-hidden=\"true\"></span>\n }\n <span class=\"banner__state-chip-label\">{{ StateLabel(State) }}</span>\n </span>\n </div>\n\n @if (ShowMinimize) {\n <button type=\"button\" class=\"iconb banner__minimize--compact\" (click)=\"MinimizeRequested.emit()\"\n title=\"Hide the call view \u2014 the call stays live\"\n aria-label=\"Minimize the call view\">\n <i class=\"fa-solid fa-minus\" aria-hidden=\"true\"></i>\n </button>\n }\n } @else {\n <div class=\"agent-orb\" [attr.data-state]=\"OrbState(State)\" aria-hidden=\"true\"></div>\n\n <div class=\"banner__id\">\n <span class=\"banner__name\">Voice for {{ AgentName }}</span>\n <span class=\"pill pill--sage\"><i class=\"fa-solid fa-feather\" aria-hidden=\"true\"></i> Co-Agent</span>\n <span class=\"banner__for\">speaking as <b>{{ AgentName }}</b></span>\n @if (ModelName) {\n <span class=\"banner__model\" [title]=\"'Realtime voice model: ' + ModelName\">\u00B7 {{ ModelName }}</span>\n }\n @if (ShowOpenSession) {\n <button type=\"button\" class=\"dev-link\" (click)=\"OpenSession()\"\n title=\"Open the agent session record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Open session</span>\n </button>\n }\n </div>\n\n <div class=\"banner__state\" [class.banner__state--busy]=\"IsBusy(State)\">\n @if (IsBusy(State)) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <div class=\"waveform\" [class.waveform--idle]=\"State !== 'speaking'\" aria-hidden=\"true\">\n <span></span><span></span><span></span><span></span>\n <span></span><span></span><span></span><span></span>\n </div>\n }\n <span class=\"banner__state-label\">{{ StateLabel(State) }}</span>\n </div>\n\n <!-- Disclosure-gated app-bar action cluster: STATE + WINDOW-CHROME only. Call actions\n (Mute / Captions / Details / Type / End) live in the bottom dock \u2014 the single home for\n each control. Captions & End were removed from here (they were exact duplicates of the\n dock's), and the standalone \"pure audio\" headphones was folded into the gear's Density =\n Simple. What remains up here is non-duplicated chrome: the gear (density + dev links) and\n Minimize. -->\n <div class=\"bar-actions\">\n @if (ShowGear) {\n <button type=\"button\" class=\"iconb\" [class.iconb--on]=\"GearOpen || DevMode\"\n (click)=\"ToggleGear($event)\"\n title=\"Interface density &amp; developer links\"\n [attr.aria-expanded]=\"GearOpen\">\n <i class=\"fa-solid fa-gear\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (ShowMinimize) {\n <button type=\"button\" class=\"iconb\" (click)=\"MinimizeRequested.emit()\"\n title=\"Hide the call view \u2014 the call stays live\"\n aria-label=\"Minimize the call view\">\n <i class=\"fa-solid fa-down-left-and-up-right-to-center\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n\n <!-- Gear popover: interface density (the disclosure escape hatch) + developer links. -->\n @if (GearOpen) {\n <div class=\"gear-pop\" (click)=\"$event.stopPropagation()\" role=\"menu\" aria-label=\"Interface settings\">\n <div class=\"gp-h\">Interface</div>\n @if (ShowDensityPicker) {\n <div class=\"gp-row\">\n <span class=\"gp-l\">Density</span>\n <div class=\"gp-seg\" role=\"radiogroup\" aria-label=\"Interface density\">\n @for (d of Densities; track d.Key) {\n <button type=\"button\" [class.on]=\"Density === d.Key\"\n (click)=\"SelectDensity(d.Key)\"\n [attr.aria-checked]=\"Density === d.Key\" role=\"radio\">{{ d.Label }}</button>\n }\n </div>\n </div>\n <div class=\"gp-note\">Simple returns to the pure-audio surface. Auto grows the console as you use it.</div>\n <div class=\"gp-div\"></div>\n }\n <button type=\"button\" class=\"gp-link\" (click)=\"ToggleDev()\" [attr.aria-pressed]=\"DevMode\">\n <i class=\"fa-solid\" [ngClass]=\"DevMode ? 'fa-toggle-on' : 'fa-toggle-off'\" aria-hidden=\"true\"></i>\n Developer links {{ DevMode ? 'on' : 'off' }}\n </button>\n </div>\n }\n }\n</div>\n", styles: [":host {\n display: block;\n --sage: var(--mj-color-violet-400, #a78bfa);\n --sage-bg: color-mix(in srgb, var(--mj-color-violet-400, #a78bfa) 14%, transparent);\n --sage-border: color-mix(in srgb, var(--mj-color-violet-400, #a78bfa) 45%, transparent);\n}\n\n/* The UNIFIED APP-BAR (Redesign A): orb \u00B7 name \u00B7 Co-Agent pill \u00B7 \"speaking as\" \u00B7\n state pill \u00B7 disclosure-gated action cluster (captions / gear / minimize / End). */\n.banner {\n position: relative; /* anchors the gear popover */\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 16px 10px 22px;\n border-bottom: 1px solid var(--mj-border-default);\n background: linear-gradient(180deg, color-mix(in srgb, var(--mj-brand-primary) 10%, transparent), transparent);\n flex-shrink: 0;\n}\n\n.banner__id {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n white-space: nowrap;\n overflow: hidden;\n}\n.banner__name {\n font-size: 14.5px;\n font-weight: 700;\n letter-spacing: -0.01em;\n color: var(--mj-text-primary);\n flex-shrink: 0;\n}\n.banner__for {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex-shrink: 5; /* gives way before the name/pill, after the model suffix */\n}\n.banner__for b {\n color: var(--mj-text-secondary);\n}\n/* Subtle realtime-model suffix (e.g. \"\u00B7 GPT Realtime 2\") in the identity line. */\n.banner__model {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 10; /* first to give way when the banner narrows */\n min-width: 0;\n}\n\n.banner__state {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 12px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n.banner__state--busy {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-status-warning);\n}\n.banner__state--busy .fa-spinner {\n color: var(--mj-status-warning);\n}\n.banner__state-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-brand-accent, var(--mj-brand-primary));\n}\n.banner__state--busy .banner__state-label {\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n}\n\n/* ---------- Glowing agent orb ---------- */\n.agent-orb {\n --orb-size: 34px;\n width: var(--orb-size);\n height: var(--orb-size);\n border-radius: 50%;\n position: relative;\n flex-shrink: 0;\n background: radial-gradient(circle at 35% 30%,\n var(--mj-brand-accent, var(--mj-brand-primary)),\n var(--mj-brand-primary) 60%,\n var(--mj-brand-primary-active, var(--mj-brand-primary)));\n box-shadow:\n 0 0 0 6px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent),\n 0 0 30px color-mix(in srgb, var(--mj-brand-primary) 45%, transparent);\n}\n.agent-orb::after {\n content: \"\";\n position: absolute;\n inset: -4px;\n border-radius: 50%;\n border: 2px solid color-mix(in srgb, var(--mj-brand-accent, var(--mj-brand-primary)) 40%, transparent);\n animation: orb-ring 2.4s ease-out infinite;\n}\n.agent-orb[data-state=\"speaking\"] {\n animation: orb-bob 0.9s ease-in-out infinite;\n}\n.agent-orb[data-state=\"listening\"] {\n box-shadow:\n 0 0 0 6px color-mix(in srgb, var(--mj-status-success) 16%, transparent),\n 0 0 30px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n background: radial-gradient(circle at 35% 30%,\n color-mix(in srgb, var(--mj-status-success) 60%, white), var(--mj-brand-primary) 65%);\n}\n.agent-orb[data-state=\"thinking\"] {\n box-shadow:\n 0 0 0 6px color-mix(in srgb, var(--mj-status-warning) 14%, transparent),\n 0 0 26px color-mix(in srgb, var(--mj-status-warning) 35%, transparent);\n}\n\n@keyframes orb-ring { 0% { transform: scale(1); opacity: .6 } 100% { transform: scale(1.5); opacity: 0 } }\n@keyframes orb-bob { 0%, 100% { transform: translateY(0) } 50% { transform: translateY(-3px) } }\n\n/* ---------- Audio-reactive mode ----------\n The overlay's rAF meter loop writes --voice-out / --voice-in + data attributes on\n .call-overlay; custom properties INHERIT into this component and :host-context()\n reaches the ancestor's attributes \u2014 so the app-bar orb rides the SAME live signal as\n the hero (scaled subtler at app-bar size). Un-metered sessions keep the keyframes. */\n:host-context(.call-overlay[data-audio-live='true']) .agent-orb:not(.agent-orb--review) {\n animation: none;\n transform: scale(calc(1 + var(--voice-out, 0) * 0.14));\n transition: transform 70ms linear;\n}\n:host-context(.call-overlay[data-audio-live='true']) .agent-orb:not(.agent-orb--review)::after {\n animation: none;\n opacity: calc(0.15 + var(--voice-out, 0) * 0.85);\n}\n:host-context(.call-overlay[data-audio-live='true'][data-voice-dir='user']) .agent-orb:not(.agent-orb--review) {\n box-shadow:\n 0 0 0 6px color-mix(in srgb, var(--mj-status-success) 16%, transparent),\n 0 0 30px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n background: radial-gradient(circle at 35% 30%,\n color-mix(in srgb, var(--mj-status-success) 60%, white), var(--mj-brand-primary) 65%);\n}\n\n/* ---------- Voice activity waveform ---------- */\n.waveform {\n display: flex;\n align-items: center;\n gap: 3px;\n height: 18px;\n}\n.waveform span {\n width: 3px;\n border-radius: 3px;\n background: var(--mj-brand-primary);\n animation: wave 1.1s ease-in-out infinite;\n}\n.waveform span:nth-child(1) { height: 30%; animation-delay: 0s }\n.waveform span:nth-child(2) { height: 65%; animation-delay: .1s }\n.waveform span:nth-child(3) { height: 100%; animation-delay: .2s }\n.waveform span:nth-child(4) { height: 55%; animation-delay: .3s }\n.waveform span:nth-child(5) { height: 85%; animation-delay: .15s }\n.waveform span:nth-child(6) { height: 40%; animation-delay: .25s }\n.waveform span:nth-child(7) { height: 70%; animation-delay: .05s }\n.waveform span:nth-child(8) { height: 35%; animation-delay: .35s }\n.waveform--idle span {\n animation: none;\n height: 18% !important;\n background: var(--mj-text-disabled);\n}\n@keyframes wave { 0%, 100% { transform: scaleY(.4) } 50% { transform: scaleY(1) } }\n\n.pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 10px;\n border-radius: var(--mj-radius-full, 9999px);\n font-size: 11.5px;\n font-weight: 600;\n border: 1px solid transparent;\n line-height: 1.4;\n}\n.pill i { font-size: 10px; }\n.pill--sage {\n background: var(--sage-bg);\n color: var(--mj-color-violet-300, var(--mj-text-secondary));\n border-color: var(--sage-border);\n}\n\n/* ---------- Session review variant ---------- */\n.banner--review {\n background: linear-gradient(180deg, color-mix(in srgb, var(--mj-text-muted) 10%, transparent), transparent);\n}\n/* Static orb: no pulse ring, dimmed glow \u2014 the session is history, nothing is live. */\n.agent-orb--review {\n box-shadow: 0 0 0 6px color-mix(in srgb, var(--mj-text-muted) 12%, transparent);\n background: radial-gradient(circle at 35% 30%,\n color-mix(in srgb, var(--mj-text-muted) 55%, var(--mj-bg-surface)),\n var(--mj-text-muted) 65%);\n}\n.agent-orb--review::after {\n animation: none;\n border-color: color-mix(in srgb, var(--mj-text-muted) 30%, transparent);\n}\n.pill--review {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-text-link, var(--mj-brand-primary));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n}\n.pill--close-reason {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-default);\n}\n.banner__range {\n flex-shrink: 3;\n}\n.banner__state--review {\n background: var(--mj-bg-surface-card);\n}\n.banner__state--review i {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n.banner__state-label--review {\n color: var(--mj-text-secondary);\n}\n\n/* Gear-gated developer link to the live agent session record */\n.dev-link {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 9px;\n border-radius: var(--mj-radius-full, 9999px);\n border: 1px dashed var(--mj-border-strong);\n background: transparent;\n color: var(--mj-text-muted);\n font-family: inherit;\n font-size: 10.5px;\n font-weight: 700;\n white-space: nowrap;\n cursor: pointer;\n transition: color 140ms ease, border-color 140ms ease, background 140ms ease;\n}\n.dev-link:hover {\n color: var(--mj-text-link, var(--mj-brand-primary));\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n.dev-link i {\n font-size: 9px;\n}\n\n/* ---------- App-bar action cluster (disclosure-gated; Redesign A) ---------- */\n.bar-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n.iconb {\n width: 34px;\n height: 34px;\n border-radius: var(--mj-radius-md, 8px);\n display: grid;\n place-items: center;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 13px;\n transition: all 140ms ease;\n}\n.iconb:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n background: var(--mj-bg-surface-hover);\n}\n.iconb--on {\n background: color-mix(in srgb, var(--mj-brand-primary) 16%, transparent);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-accent, var(--mj-brand-primary));\n}\n.bar-sep {\n width: 1px;\n height: 26px;\n background: var(--mj-border-default);\n}\n.end-pill {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n padding: 8px 18px;\n font-family: inherit;\n font-size: 13px;\n font-weight: 700;\n white-space: nowrap;\n border-radius: var(--mj-radius-full, 9999px);\n border: 1px solid var(--mj-status-error);\n background: var(--mj-status-error);\n color: var(--mj-text-inverse, #fff);\n cursor: pointer;\n box-shadow: 0 4px 16px color-mix(in srgb, var(--mj-status-error) 35%, transparent);\n transition: filter 140ms ease;\n}\n.end-pill:hover {\n filter: brightness(0.92);\n}\n.start-live-pill {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n padding: 8px 18px;\n font-family: inherit;\n font-size: 13px;\n font-weight: 700;\n white-space: nowrap;\n border-radius: var(--mj-radius-full, 9999px);\n border: 1px solid var(--mj-brand-primary);\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n cursor: pointer;\n box-shadow: 0 4px 16px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n transition: filter 140ms ease;\n}\n.start-live-pill:hover {\n filter: brightness(1.05);\n}\n\n/* ---------- Gear popover: density escape hatch + developer links ---------- */\n.gear-pop {\n position: absolute;\n top: calc(100% + 8px);\n right: 14px;\n z-index: 70;\n width: 268px;\n border: 1px solid var(--mj-border-strong);\n border-radius: var(--mj-radius-lg, 12px);\n background: var(--mj-bg-surface-elevated);\n box-shadow: var(--mj-shadow-xl, 0 12px 32px rgba(0, 0, 0, 0.18));\n padding: 12px 14px 10px;\n animation: gear-pop-in 160ms ease;\n}\n@keyframes gear-pop-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.gp-h {\n font-size: 10.5px;\n font-weight: 800;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n margin-bottom: 9px;\n}\n.gp-row {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.gp-l {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n.gp-seg {\n display: inline-flex;\n flex: 1;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface);\n padding: 2px;\n gap: 2px;\n}\n.gp-seg button {\n flex: 1;\n border: 0;\n background: transparent;\n color: var(--mj-text-muted);\n font-family: inherit;\n font-size: 11px;\n font-weight: 700;\n padding: 4px 0;\n border-radius: 6px;\n cursor: pointer;\n transition: all 120ms ease;\n}\n.gp-seg button.on {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n}\n.gp-note {\n font-size: 10.5px;\n color: var(--mj-text-muted);\n line-height: 1.45;\n margin-top: 8px;\n}\n.gp-div {\n height: 1px;\n background: var(--mj-border-default);\n margin: 10px -14px;\n}\n.gp-link {\n display: flex;\n width: 100%;\n align-items: center;\n gap: 9px;\n padding: 6px 2px;\n border: 0;\n background: transparent;\n color: var(--mj-text-secondary);\n font-family: inherit;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n text-align: left;\n}\n.gp-link:hover {\n color: var(--mj-text-primary);\n}\n.gp-link i {\n width: 16px;\n text-align: center;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n.gp-link:hover i {\n color: var(--mj-brand-accent, var(--mj-brand-primary));\n}\n\n/* ============================================================= COMPACT (Calm Orb \u00B7 overlay)\n A tiny identity + state row only \u2014 the body owns the big orb + name + state, and the lean\n dock owns the actions. No duplicate orb / state pill / headphones / gear / expand here. */\n.banner--compact {\n gap: 10px;\n padding: 12px 14px;\n background: transparent;\n border-bottom: none;\n}\n.banner__id--compact {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 9px;\n overflow: hidden;\n}\n.banner__avatar {\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n font-size: 11px;\n font-weight: 800;\n color: var(--mj-text-inverse);\n background: radial-gradient(circle at 35% 30%,\n color-mix(in srgb, var(--mj-brand-primary) 60%, white), var(--mj-brand-primary) 65%);\n}\n.banner__name--compact {\n font-size: 13px;\n font-weight: 700;\n letter-spacing: -0.01em;\n color: var(--mj-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.banner__state-chip {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n padding: 4px 10px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n font-size: 11.5px;\n font-weight: 600;\n color: var(--mj-text-muted);\n}\n.banner__state-chip-label {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 130px;\n}\n.banner__state-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--mj-status-success);\n box-shadow: 0 0 8px color-mix(in srgb, var(--mj-status-success) 70%, transparent);\n}\n.banner__state-dot[data-state=\"speaking\"] {\n background: var(--mj-brand-primary);\n box-shadow: 0 0 8px color-mix(in srgb, var(--mj-brand-primary) 70%, transparent);\n animation: compact-dot-blink 0.9s infinite;\n}\n.banner__state-dot[data-state=\"thinking\"] {\n background: var(--mj-status-warning);\n box-shadow: 0 0 8px color-mix(in srgb, var(--mj-status-warning) 70%, transparent);\n}\n@keyframes compact-dot-blink { 50% { opacity: 0.35; } }\n/* Minimize is the only control left in the compact bar \u2014 render it round + de-emphasized. */\n.banner__minimize--compact {\n flex-shrink: 0;\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: transparent;\n border-color: transparent;\n color: var(--mj-text-muted);\n}\n.banner__minimize--compact:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-default);\n}\n"] }]
530
+ args: [{ standalone: true, selector: 'mj-realtime-agent-banner', imports: [CommonModule], template: "<div class=\"banner\" [class.banner--review]=\"ReviewMode\" [class.banner--compact]=\"Compact && !ReviewMode\">\n @if (ReviewMode) {\n <!-- SESSION REVIEW: static orb \u00B7 name \u00B7 review badge \u00B7 started\u2192closed \u00B7 close-reason chip,\n with the review's exit actions up here in the header bar (Start live leads, Close trails). -->\n <div class=\"agent-orb agent-orb--review\" aria-hidden=\"true\"></div>\n\n <div class=\"banner__id\">\n <span class=\"banner__name\">Voice for {{ AgentName }}</span>\n <span class=\"pill pill--review\"><i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i> Session review</span>\n @if (ReviewRangeLabel) {\n <span class=\"banner__for banner__range\">{{ ReviewRangeLabel }}</span>\n }\n @if (ReviewCloseReasonLabel) {\n <span class=\"pill pill--close-reason\" [title]=\"'Close reason: ' + ReviewCloseReason\">{{ ReviewCloseReasonLabel }}</span>\n }\n @if (ShowOpenSession) {\n <button type=\"button\" class=\"dev-link\" (click)=\"OpenSession()\"\n title=\"Open the agent session record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Open session</span>\n </button>\n }\n </div>\n\n <div class=\"banner__state banner__state--review\">\n <i class=\"fa-solid fa-box-archive\" aria-hidden=\"true\"></i>\n <span class=\"banner__state-label banner__state-label--review\">Reviewing past session</span>\n </div>\n\n <div class=\"bar-actions\">\n @if (ShowStartLive) {\n <button type=\"button\" class=\"start-live-pill\" (click)=\"StartLiveRequested.emit()\"\n title=\"Resume this session as a new live call\">\n <i class=\"fa-solid fa-phone\" aria-hidden=\"true\"></i>\n <span>Start live session</span>\n </button>\n }\n <button type=\"button\" class=\"iconb\" (click)=\"CloseRequested.emit()\"\n title=\"Close review\" aria-label=\"Close session review\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </div>\n } @else if (Compact) {\n <!-- COMPACT (Calm Orb \u00B7 overlay): a tiny identity + state row only. No duplicate orb,\n no state pill, no headphones / gear / expand \u2014 the body shows the big orb + name +\n state, and the lean dock owns the actions. Minimize stays reachable here. -->\n <div class=\"banner__id banner__id--compact\">\n <span class=\"banner__avatar\" aria-hidden=\"true\">{{ AgentName.charAt(0) }}</span>\n <span class=\"banner__name banner__name--compact\">{{ AgentName }}</span>\n @if (!HideState) {\n <span class=\"banner__state-chip\">\n @if (IsBusy(State)) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <span class=\"banner__state-dot\" [attr.data-state]=\"OrbState(State)\" aria-hidden=\"true\"></span>\n }\n <span class=\"banner__state-chip-label\">{{ StateLabel(State) }}</span>\n </span>\n }\n </div>\n\n @if (ShowMinimize) {\n <button type=\"button\" class=\"iconb banner__minimize--compact\" (click)=\"MinimizeRequested.emit()\"\n title=\"Hide the call view \u2014 the call stays live\"\n aria-label=\"Minimize the call view\">\n <i class=\"fa-solid fa-minus\" aria-hidden=\"true\"></i>\n </button>\n }\n } @else {\n <div class=\"agent-orb\" [attr.data-state]=\"OrbState(State)\" aria-hidden=\"true\"></div>\n\n <div class=\"banner__id\">\n <span class=\"banner__name\">Voice for {{ AgentName }}</span>\n <span class=\"pill pill--sage\"><i class=\"fa-solid fa-feather\" aria-hidden=\"true\"></i> Co-Agent</span>\n @if (!HideState) {\n <span class=\"banner__for\">speaking as <b>{{ AgentName }}</b></span>\n }\n @if (ModelName) {\n <span class=\"banner__model\" [title]=\"'Realtime voice model: ' + ModelName\">\u00B7 {{ ModelName }}</span>\n }\n @if (ShowOpenSession) {\n <button type=\"button\" class=\"dev-link\" (click)=\"OpenSession()\"\n title=\"Open the agent session record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Open session</span>\n </button>\n }\n </div>\n\n @if (!HideState) {\n <div class=\"banner__state\" [class.banner__state--busy]=\"IsBusy(State)\">\n @if (IsBusy(State)) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <div class=\"waveform\" [class.waveform--idle]=\"State !== 'speaking'\" aria-hidden=\"true\">\n <span></span><span></span><span></span><span></span>\n <span></span><span></span><span></span><span></span>\n </div>\n }\n <span class=\"banner__state-label\">{{ StateLabel(State) }}</span>\n </div>\n }\n\n <!-- Disclosure-gated app-bar action cluster: STATE + WINDOW-CHROME only. Call actions\n (Mute / Captions / Details / Type / End) live in the bottom dock \u2014 the single home for\n each control. Captions & End were removed from here (they were exact duplicates of the\n dock's), and the standalone \"pure audio\" headphones was folded into the gear's Density =\n Simple. What remains up here is non-duplicated chrome: the gear (density + dev links) and\n Minimize. -->\n <div class=\"bar-actions\">\n @if (ShowGear) {\n <button type=\"button\" class=\"iconb\" [class.iconb--on]=\"GearOpen || DevMode\"\n (click)=\"ToggleGear($event)\"\n title=\"Interface density &amp; developer links\"\n [attr.aria-expanded]=\"GearOpen\">\n <i class=\"fa-solid fa-gear\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (ShowMinimize) {\n <button type=\"button\" class=\"iconb\" (click)=\"MinimizeRequested.emit()\"\n title=\"Hide the call view \u2014 the call stays live\"\n aria-label=\"Minimize the call view\">\n <i class=\"fa-solid fa-down-left-and-up-right-to-center\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n\n <!-- Gear popover: interface density (the disclosure escape hatch) + developer links. -->\n @if (GearOpen) {\n <div class=\"gear-pop\" (click)=\"$event.stopPropagation()\" role=\"menu\" aria-label=\"Interface settings\">\n <div class=\"gp-h\">Interface</div>\n @if (ShowDensityPicker) {\n <div class=\"gp-row\">\n <span class=\"gp-l\">Density</span>\n <div class=\"gp-seg\" role=\"radiogroup\" aria-label=\"Interface density\">\n @for (d of Densities; track d.Key) {\n <button type=\"button\" [class.on]=\"Density === d.Key\"\n (click)=\"SelectDensity(d.Key)\"\n [attr.aria-checked]=\"Density === d.Key\" role=\"radio\">{{ d.Label }}</button>\n }\n </div>\n </div>\n <div class=\"gp-note\">Simple returns to the pure-audio surface. Auto grows the console as you use it.</div>\n }\n @if (ShowDensityPicker && AllowDevLinks) {\n <div class=\"gp-div\"></div>\n }\n @if (AllowDevLinks) {\n <button type=\"button\" class=\"gp-link\" (click)=\"ToggleDev()\" [attr.aria-pressed]=\"DevMode\">\n <i class=\"fa-solid\" [ngClass]=\"DevMode ? 'fa-toggle-on' : 'fa-toggle-off'\" aria-hidden=\"true\"></i>\n Developer links {{ DevMode ? 'on' : 'off' }}\n </button>\n }\n </div>\n }\n }\n</div>\n", styles: [":host {\n display: block;\n --sage: var(--mj-color-violet-400, #a78bfa);\n --sage-bg: color-mix(in srgb, var(--mj-color-violet-400, #a78bfa) 14%, transparent);\n --sage-border: color-mix(in srgb, var(--mj-color-violet-400, #a78bfa) 45%, transparent);\n}\n\n/* The UNIFIED APP-BAR (Redesign A): orb \u00B7 name \u00B7 Co-Agent pill \u00B7 \"speaking as\" \u00B7\n state pill \u00B7 disclosure-gated action cluster (captions / gear / minimize / End). */\n.banner {\n position: relative; /* anchors the gear popover */\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 16px 10px 22px;\n border-bottom: 1px solid var(--mj-border-default);\n background: linear-gradient(180deg, color-mix(in srgb, var(--mj-brand-primary) 10%, transparent), transparent);\n flex-shrink: 0;\n}\n\n.banner__id {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n white-space: nowrap;\n overflow: hidden;\n}\n.banner__name {\n font-size: 14.5px;\n font-weight: 700;\n letter-spacing: -0.01em;\n color: var(--mj-text-primary);\n flex-shrink: 0;\n}\n.banner__for {\n font-size: 11.5px;\n color: var(--mj-text-muted);\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex-shrink: 5; /* gives way before the name/pill, after the model suffix */\n}\n.banner__for b {\n color: var(--mj-text-secondary);\n}\n/* Subtle realtime-model suffix (e.g. \"\u00B7 GPT Realtime 2\") in the identity line. */\n.banner__model {\n font-size: 11px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n flex-shrink: 10; /* first to give way when the banner narrows */\n min-width: 0;\n}\n\n.banner__state {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 12px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n.banner__state--busy {\n background: var(--mj-status-warning-bg);\n border-color: var(--mj-status-warning);\n}\n.banner__state--busy .fa-spinner {\n color: var(--mj-status-warning);\n}\n.banner__state-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-brand-accent, var(--mj-brand-primary));\n}\n.banner__state--busy .banner__state-label {\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n}\n\n/* ---------- Glowing agent orb ---------- */\n.agent-orb {\n --orb-size: 34px;\n width: var(--orb-size);\n height: var(--orb-size);\n border-radius: 50%;\n position: relative;\n flex-shrink: 0;\n background: radial-gradient(circle at 35% 30%,\n var(--mj-brand-accent, var(--mj-brand-primary)),\n var(--mj-brand-primary) 60%,\n var(--mj-brand-primary-active, var(--mj-brand-primary)));\n box-shadow:\n 0 0 0 6px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent),\n 0 0 30px color-mix(in srgb, var(--mj-brand-primary) 45%, transparent);\n}\n.agent-orb::after {\n content: \"\";\n position: absolute;\n inset: -4px;\n border-radius: 50%;\n border: 2px solid color-mix(in srgb, var(--mj-brand-accent, var(--mj-brand-primary)) 40%, transparent);\n animation: orb-ring 2.4s ease-out infinite;\n}\n.agent-orb[data-state=\"speaking\"] {\n animation: orb-bob 0.9s ease-in-out infinite;\n}\n.agent-orb[data-state=\"listening\"] {\n box-shadow:\n 0 0 0 6px color-mix(in srgb, var(--mj-status-success) 16%, transparent),\n 0 0 30px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n background: radial-gradient(circle at 35% 30%,\n color-mix(in srgb, var(--mj-status-success) 60%, white), var(--mj-brand-primary) 65%);\n}\n.agent-orb[data-state=\"thinking\"] {\n box-shadow:\n 0 0 0 6px color-mix(in srgb, var(--mj-status-warning) 14%, transparent),\n 0 0 26px color-mix(in srgb, var(--mj-status-warning) 35%, transparent);\n}\n\n@keyframes orb-ring { 0% { transform: scale(1); opacity: .6 } 100% { transform: scale(1.5); opacity: 0 } }\n@keyframes orb-bob { 0%, 100% { transform: translateY(0) } 50% { transform: translateY(-3px) } }\n\n/* ---------- Audio-reactive mode ----------\n The overlay's rAF meter loop writes --voice-out / --voice-in + data attributes on\n .call-overlay; custom properties INHERIT into this component and :host-context()\n reaches the ancestor's attributes \u2014 so the app-bar orb rides the SAME live signal as\n the hero (scaled subtler at app-bar size). Un-metered sessions keep the keyframes. */\n:host-context(.call-overlay[data-audio-live='true']) .agent-orb:not(.agent-orb--review) {\n animation: none;\n transform: scale(calc(1 + var(--voice-out, 0) * 0.14));\n transition: transform 70ms linear;\n}\n:host-context(.call-overlay[data-audio-live='true']) .agent-orb:not(.agent-orb--review)::after {\n animation: none;\n opacity: calc(0.15 + var(--voice-out, 0) * 0.85);\n}\n:host-context(.call-overlay[data-audio-live='true'][data-voice-dir='user']) .agent-orb:not(.agent-orb--review) {\n box-shadow:\n 0 0 0 6px color-mix(in srgb, var(--mj-status-success) 16%, transparent),\n 0 0 30px color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n background: radial-gradient(circle at 35% 30%,\n color-mix(in srgb, var(--mj-status-success) 60%, white), var(--mj-brand-primary) 65%);\n}\n\n/* ---------- Voice activity waveform ---------- */\n.waveform {\n display: flex;\n align-items: center;\n gap: 3px;\n height: 18px;\n}\n.waveform span {\n width: 3px;\n border-radius: 3px;\n background: var(--mj-brand-primary);\n animation: wave 1.1s ease-in-out infinite;\n}\n.waveform span:nth-child(1) { height: 30%; animation-delay: 0s }\n.waveform span:nth-child(2) { height: 65%; animation-delay: .1s }\n.waveform span:nth-child(3) { height: 100%; animation-delay: .2s }\n.waveform span:nth-child(4) { height: 55%; animation-delay: .3s }\n.waveform span:nth-child(5) { height: 85%; animation-delay: .15s }\n.waveform span:nth-child(6) { height: 40%; animation-delay: .25s }\n.waveform span:nth-child(7) { height: 70%; animation-delay: .05s }\n.waveform span:nth-child(8) { height: 35%; animation-delay: .35s }\n.waveform--idle span {\n animation: none;\n height: 18% !important;\n background: var(--mj-text-disabled);\n}\n@keyframes wave { 0%, 100% { transform: scaleY(.4) } 50% { transform: scaleY(1) } }\n\n.pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 3px 10px;\n border-radius: var(--mj-radius-full, 9999px);\n font-size: 11.5px;\n font-weight: 600;\n border: 1px solid transparent;\n line-height: 1.4;\n}\n.pill i { font-size: 10px; }\n.pill--sage {\n background: var(--sage-bg);\n color: var(--mj-color-violet-300, var(--mj-text-secondary));\n border-color: var(--sage-border);\n}\n\n/* ---------- Session review variant ---------- */\n.banner--review {\n background: linear-gradient(180deg, color-mix(in srgb, var(--mj-text-muted) 10%, transparent), transparent);\n}\n/* Static orb: no pulse ring, dimmed glow \u2014 the session is history, nothing is live. */\n.agent-orb--review {\n box-shadow: 0 0 0 6px color-mix(in srgb, var(--mj-text-muted) 12%, transparent);\n background: radial-gradient(circle at 35% 30%,\n color-mix(in srgb, var(--mj-text-muted) 55%, var(--mj-bg-surface)),\n var(--mj-text-muted) 65%);\n}\n.agent-orb--review::after {\n animation: none;\n border-color: color-mix(in srgb, var(--mj-text-muted) 30%, transparent);\n}\n.pill--review {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n color: var(--mj-text-link, var(--mj-brand-primary));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n}\n.pill--close-reason {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-default);\n}\n.banner__range {\n flex-shrink: 3;\n}\n.banner__state--review {\n background: var(--mj-bg-surface-card);\n}\n.banner__state--review i {\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n.banner__state-label--review {\n color: var(--mj-text-secondary);\n}\n\n/* Gear-gated developer link to the live agent session record */\n.dev-link {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 3px 9px;\n border-radius: var(--mj-radius-full, 9999px);\n border: 1px dashed var(--mj-border-strong);\n background: transparent;\n color: var(--mj-text-muted);\n font-family: inherit;\n font-size: 10.5px;\n font-weight: 700;\n white-space: nowrap;\n cursor: pointer;\n transition: color 140ms ease, border-color 140ms ease, background 140ms ease;\n}\n.dev-link:hover {\n color: var(--mj-text-link, var(--mj-brand-primary));\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n.dev-link i {\n font-size: 9px;\n}\n\n/* ---------- App-bar action cluster (disclosure-gated; Redesign A) ---------- */\n.bar-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n.iconb {\n width: 34px;\n height: 34px;\n border-radius: var(--mj-radius-md, 8px);\n display: grid;\n place-items: center;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 13px;\n transition: all 140ms ease;\n}\n.iconb:hover {\n color: var(--mj-text-primary);\n border-color: var(--mj-border-strong);\n background: var(--mj-bg-surface-hover);\n}\n.iconb--on {\n background: color-mix(in srgb, var(--mj-brand-primary) 16%, transparent);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-accent, var(--mj-brand-primary));\n}\n.bar-sep {\n width: 1px;\n height: 26px;\n background: var(--mj-border-default);\n}\n.end-pill {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n padding: 8px 18px;\n font-family: inherit;\n font-size: 13px;\n font-weight: 700;\n white-space: nowrap;\n border-radius: var(--mj-radius-full, 9999px);\n border: 1px solid var(--mj-status-error);\n background: var(--mj-status-error);\n color: var(--mj-text-inverse, #fff);\n cursor: pointer;\n box-shadow: 0 4px 16px color-mix(in srgb, var(--mj-status-error) 35%, transparent);\n transition: filter 140ms ease;\n}\n.end-pill:hover {\n filter: brightness(0.92);\n}\n.start-live-pill {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n padding: 8px 18px;\n font-family: inherit;\n font-size: 13px;\n font-weight: 700;\n white-space: nowrap;\n border-radius: var(--mj-radius-full, 9999px);\n border: 1px solid var(--mj-brand-primary);\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n cursor: pointer;\n box-shadow: 0 4px 16px color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n transition: filter 140ms ease;\n}\n.start-live-pill:hover {\n filter: brightness(1.05);\n}\n\n/* ---------- Gear popover: density escape hatch + developer links ---------- */\n.gear-pop {\n position: absolute;\n top: calc(100% + 8px);\n right: 14px;\n z-index: 70;\n width: 268px;\n border: 1px solid var(--mj-border-strong);\n border-radius: var(--mj-radius-lg, 12px);\n background: var(--mj-bg-surface-elevated);\n box-shadow: var(--mj-shadow-xl, 0 12px 32px rgba(0, 0, 0, 0.18));\n padding: 12px 14px 10px;\n animation: gear-pop-in 160ms ease;\n}\n@keyframes gear-pop-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.gp-h {\n font-size: 10.5px;\n font-weight: 800;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n margin-bottom: 9px;\n}\n.gp-row {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n.gp-l {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n.gp-seg {\n display: inline-flex;\n flex: 1;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface);\n padding: 2px;\n gap: 2px;\n}\n.gp-seg button {\n flex: 1;\n border: 0;\n background: transparent;\n color: var(--mj-text-muted);\n font-family: inherit;\n font-size: 11px;\n font-weight: 700;\n padding: 4px 0;\n border-radius: 6px;\n cursor: pointer;\n transition: all 120ms ease;\n}\n.gp-seg button.on {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n}\n.gp-note {\n font-size: 10.5px;\n color: var(--mj-text-muted);\n line-height: 1.45;\n margin-top: 8px;\n}\n.gp-div {\n height: 1px;\n background: var(--mj-border-default);\n margin: 10px -14px;\n}\n.gp-link {\n display: flex;\n width: 100%;\n align-items: center;\n gap: 9px;\n padding: 6px 2px;\n border: 0;\n background: transparent;\n color: var(--mj-text-secondary);\n font-family: inherit;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n text-align: left;\n}\n.gp-link:hover {\n color: var(--mj-text-primary);\n}\n.gp-link i {\n width: 16px;\n text-align: center;\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n.gp-link:hover i {\n color: var(--mj-brand-accent, var(--mj-brand-primary));\n}\n\n/* ============================================================= COMPACT (Calm Orb \u00B7 overlay)\n A tiny identity + state row only \u2014 the body owns the big orb + name + state, and the lean\n dock owns the actions. No duplicate orb / state pill / headphones / gear / expand here. */\n.banner--compact {\n gap: 10px;\n padding: 12px 14px;\n background: transparent;\n border-bottom: none;\n}\n.banner__id--compact {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 9px;\n overflow: hidden;\n}\n.banner__avatar {\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: grid;\n place-items: center;\n font-size: 11px;\n font-weight: 800;\n color: var(--mj-text-inverse);\n background: radial-gradient(circle at 35% 30%,\n color-mix(in srgb, var(--mj-brand-primary) 60%, white), var(--mj-brand-primary) 65%);\n}\n.banner__name--compact {\n font-size: 13px;\n font-weight: 700;\n letter-spacing: -0.01em;\n color: var(--mj-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.banner__state-chip {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n padding: 4px 10px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n font-size: 11.5px;\n font-weight: 600;\n color: var(--mj-text-muted);\n}\n.banner__state-chip-label {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 130px;\n}\n.banner__state-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--mj-status-success);\n box-shadow: 0 0 8px color-mix(in srgb, var(--mj-status-success) 70%, transparent);\n}\n.banner__state-dot[data-state=\"speaking\"] {\n background: var(--mj-brand-primary);\n box-shadow: 0 0 8px color-mix(in srgb, var(--mj-brand-primary) 70%, transparent);\n animation: compact-dot-blink 0.9s infinite;\n}\n.banner__state-dot[data-state=\"thinking\"] {\n background: var(--mj-status-warning);\n box-shadow: 0 0 8px color-mix(in srgb, var(--mj-status-warning) 70%, transparent);\n}\n@keyframes compact-dot-blink { 50% { opacity: 0.35; } }\n/* Minimize is the only control left in the compact bar \u2014 render it round + de-emphasized. */\n.banner__minimize--compact {\n flex-shrink: 0;\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: transparent;\n border-color: transparent;\n color: var(--mj-text-muted);\n}\n.banner__minimize--compact:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-default);\n}\n"] }]
473
531
  }], null, { State: [{
474
532
  type: Input,
475
533
  args: [{ required: true }]
476
534
  }], Compact: [{
477
535
  type: Input
536
+ }], HideState: [{
537
+ type: Input
478
538
  }], AgentName: [{
479
539
  type: Input
480
540
  }], ErrorLabel: [{
@@ -497,6 +557,8 @@ export class RealtimeAgentBannerComponent {
497
557
  type: Input
498
558
  }], ShowDensityPicker: [{
499
559
  type: Input
560
+ }], AllowDevLinks: [{
561
+ type: Input
500
562
  }], ShowMinimize: [{
501
563
  type: Input
502
564
  }], ShowStartLive: [{