@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
@@ -71,80 +71,84 @@ function RealtimeSessionOverlayComponent_Conditional_0_Conditional_9_Template(rf
71
71
  i0.ɵɵelementEnd();
72
72
  } }
73
73
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_1_Template(rf, ctx) { if (rf & 1) {
74
- i0.ɵɵelement(0, "mj-realtime-agent-orb", 32);
75
- i0.ɵɵelementStart(1, "div", 33);
74
+ i0.ɵɵelement(0, "mj-realtime-agent-orb", 31);
75
+ i0.ɵɵelementStart(1, "div", 32);
76
76
  i0.ɵɵelement(2, "span")(3, "span")(4, "span")(5, "span")(6, "span")(7, "span")(8, "span")(9, "span")(10, "span");
77
77
  i0.ɵɵelementEnd();
78
78
  } if (rf & 2) {
79
- const state_r5 = i0.ɵɵnextContext(2);
79
+ const state_r4 = i0.ɵɵnextContext(2);
80
80
  const ctx_r1 = i0.ɵɵnextContext();
81
- i0.ɵɵproperty("State", ctx_r1.HeroOrbState(state_r5));
81
+ i0.ɵɵproperty("State", ctx_r1.HeroOrbState(state_r4));
82
82
  } }
83
83
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_4_Conditional_3_Template(rf, ctx) { if (rf & 1) {
84
- i0.ɵɵelementStart(0, "span", 36);
84
+ i0.ɵɵelementStart(0, "span", 35);
85
85
  i0.ɵɵtext(1);
86
86
  i0.ɵɵelementEnd();
87
87
  } if (rf & 2) {
88
- const caption_r6 = i0.ɵɵnextContext();
88
+ const caption_r5 = i0.ɵɵnextContext();
89
89
  i0.ɵɵadvance();
90
- i0.ɵɵtextInterpolate1("", caption_r6.Speaker, ":");
90
+ i0.ɵɵtextInterpolate1("", caption_r5.Speaker, ":");
91
91
  } }
92
92
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_4_Template(rf, ctx) { if (rf & 1) {
93
- i0.ɵɵelementStart(0, "p", 28)(1, "span", 34)(2, "span", 35);
94
- i0.ɵɵconditionalCreate(3, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_4_Conditional_3_Template, 2, 1, "span", 36);
93
+ i0.ɵɵelementStart(0, "p", 28)(1, "span", 33)(2, "span", 34);
94
+ i0.ɵɵconditionalCreate(3, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_4_Conditional_3_Template, 2, 1, "span", 35);
95
95
  i0.ɵɵtext(4);
96
96
  i0.ɵɵelementEnd()()();
97
97
  } if (rf & 2) {
98
- const caption_r6 = ctx;
98
+ const caption_r5 = ctx;
99
99
  i0.ɵɵadvance(3);
100
- i0.ɵɵconditional(caption_r6.Speaker ? 3 : -1);
100
+ i0.ɵɵconditional(caption_r5.Speaker ? 3 : -1);
101
101
  i0.ɵɵadvance();
102
- i0.ɵɵtextInterpolate1(" ", caption_r6.Text, " ");
102
+ i0.ɵɵtextInterpolate1(" ", caption_r5.Text, " ");
103
103
  } }
104
104
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_5_Template(rf, ctx) { if (rf & 1) {
105
- i0.ɵɵelementStart(0, "div", 37);
105
+ i0.ɵɵelementStart(0, "div", 36);
106
106
  i0.ɵɵtext(1);
107
107
  i0.ɵɵelementEnd();
108
- i0.ɵɵelementStart(2, "div", 38);
108
+ i0.ɵɵelementStart(2, "div", 37);
109
109
  i0.ɵɵtext(3);
110
110
  i0.ɵɵelementEnd();
111
111
  } if (rf & 2) {
112
- const state_r5 = i0.ɵɵnextContext(2);
112
+ const state_r4 = i0.ɵɵnextContext(2);
113
113
  const ctx_r1 = i0.ɵɵnextContext();
114
114
  i0.ɵɵadvance();
115
115
  i0.ɵɵtextInterpolate(ctx_r1.AgentName);
116
116
  i0.ɵɵadvance(2);
117
- i0.ɵɵtextInterpolate(ctx_r1.HeroStateLabel(state_r5));
117
+ i0.ɵɵtextInterpolate(ctx_r1.HeroStateLabel(state_r4));
118
118
  } }
119
119
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_6_Template(rf, ctx) { if (rf & 1) {
120
120
  i0.ɵɵelementStart(0, "span", 29);
121
121
  i0.ɵɵtext(1);
122
122
  i0.ɵɵelementEnd();
123
123
  } if (rf & 2) {
124
- const state_r5 = i0.ɵɵnextContext(2);
124
+ const state_r4 = i0.ɵɵnextContext(2);
125
125
  const ctx_r1 = i0.ɵɵnextContext();
126
126
  i0.ɵɵadvance();
127
- i0.ɵɵtextInterpolate(ctx_r1.HeroStateLabel(state_r5));
127
+ i0.ɵɵtextInterpolate(ctx_r1.HeroStateLabel(state_r4));
128
+ } }
129
+ function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_7_Template(rf, ctx) { if (rf & 1) {
130
+ const _r6 = i0.ɵɵgetCurrentView();
131
+ i0.ɵɵelementStart(0, "button", 38);
132
+ i0.ɵɵlistener("click", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnTextReveal()); });
133
+ i0.ɵɵelement(1, "i", 39);
134
+ i0.ɵɵtext(2, " Show the conversation ");
135
+ i0.ɵɵelementEnd();
128
136
  } }
129
137
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Template(rf, ctx) { if (rf & 1) {
130
- const _r4 = i0.ɵɵgetCurrentView();
131
138
  i0.ɵɵelementStart(0, "div", 26);
132
139
  i0.ɵɵconditionalCreate(1, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_1_Template, 11, 1);
133
140
  i0.ɵɵelementStart(2, "div", 27, 3);
134
141
  i0.ɵɵconditionalCreate(4, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_4_Template, 5, 2, "p", 28);
135
142
  i0.ɵɵelementEnd();
136
143
  i0.ɵɵconditionalCreate(5, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_5_Template, 4, 2)(6, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_6_Template, 2, 1, "span", 29);
137
- i0.ɵɵelementStart(7, "button", 30);
138
- i0.ɵɵlistener("click", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnTextReveal()); });
139
- i0.ɵɵelement(8, "i", 31);
140
- i0.ɵɵtext(9, " Show the conversation ");
141
- i0.ɵɵelementEnd()();
144
+ i0.ɵɵconditionalCreate(7, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Conditional_7_Template, 3, 0, "button", 30);
145
+ i0.ɵɵelementEnd();
142
146
  } if (rf & 2) {
143
147
  let tmp_11_0;
144
- const state_r5 = i0.ɵɵnextContext();
148
+ const state_r4 = i0.ɵɵnextContext();
145
149
  const ctx_r1 = i0.ɵɵnextContext();
146
150
  i0.ɵɵclassProp("hero--presenting", ctx_r1.PresenterOnStage);
147
- i0.ɵɵattribute("data-state", state_r5);
151
+ i0.ɵɵattribute("data-state", state_r4);
148
152
  i0.ɵɵadvance();
149
153
  i0.ɵɵconditional(!ctx_r1.PresenterOnStage ? 1 : -1);
150
154
  i0.ɵɵadvance();
@@ -153,39 +157,41 @@ function RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Template(r
153
157
  i0.ɵɵconditional((tmp_11_0 = ctx_r1.ShowAvatarCaptions && ctx_r1.AvatarCaption) ? 4 : -1, tmp_11_0);
154
158
  i0.ɵɵadvance();
155
159
  i0.ɵɵconditional(!ctx_r1.PresenterOnStage ? 5 : 6);
160
+ i0.ɵɵadvance(2);
161
+ i0.ɵɵconditional(ctx_r1.Ui.allowTextReveal && (ctx_r1.PresenterOnStage || !ctx_r1.Ui.showCaptionsControl) ? 7 : -1);
156
162
  } }
157
163
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_11_Template(rf, ctx) { if (rf & 1) {
158
164
  const _r7 = i0.ɵɵgetCurrentView();
159
- i0.ɵɵelementStart(0, "mj-realtime-session-thread", 39);
165
+ i0.ɵɵelementStart(0, "mj-realtime-session-thread", 40);
160
166
  i0.ɵɵlistener("OpenRunRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_11_Template_mj_realtime_session_thread_OpenRunRequested_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnOpenRunRequested($event)); })("OpenArtifactRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_11_Template_mj_realtime_session_thread_OpenArtifactRequested_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnOpenArtifactRequested($event)); })("CancelRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_11_Template_mj_realtime_session_thread_CancelRequested_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnCancelDelegation($event)); });
161
167
  i0.ɵɵelementEnd();
162
168
  } if (rf & 2) {
163
169
  const ctx_r1 = i0.ɵɵnextContext(2);
164
- i0.ɵɵproperty("State", ctx_r1.State)("AgentName", ctx_r1.AgentName)("UserName", (ctx_r1.CurrentUser == null ? null : ctx_r1.CurrentUser.Name) || "You")("ShowCaptions", ctx_r1.IsReviewing ? true : ctx_r1.ShowCaptions)("DevMode", ctx_r1.DevMode);
170
+ i0.ɵɵproperty("State", ctx_r1.State)("AgentName", ctx_r1.AgentName)("UserName", (ctx_r1.CurrentUser == null ? null : ctx_r1.CurrentUser.Name) || "You")("ShowCaptions", ctx_r1.IsReviewing ? true : ctx_r1.ShowCaptions)("DevMode", ctx_r1.Ui.showDevLinks);
165
171
  } }
166
172
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Conditional_1_Template(rf, ctx) { if (rf & 1) {
167
173
  i0.ɵɵelement(0, "mj-realtime-channel-strip");
168
174
  } }
169
175
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template(rf, ctx) { if (rf & 1) {
170
176
  const _r8 = i0.ɵɵgetCurrentView();
171
- i0.ɵɵelementStart(0, "mj-realtime-perception-chip", 40);
177
+ i0.ɵɵelementStart(0, "mj-realtime-perception-chip", 41);
172
178
  i0.ɵɵlistener("SourceToggled", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_perception_chip_SourceToggled_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnVideoSourceToggled($event)); })("SourcePicked", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_perception_chip_SourcePicked_0_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnVideoSourcePicked($event)); });
173
179
  i0.ɵɵelementEnd();
174
180
  i0.ɵɵconditionalCreate(1, RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Conditional_1_Template, 1, 0, "mj-realtime-channel-strip");
175
- i0.ɵɵelementStart(2, "mj-realtime-composer", 41);
181
+ i0.ɵɵelementStart(2, "mj-realtime-composer", 42);
176
182
  i0.ɵɵlistener("OpenChanged", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_OpenChanged_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnComposerOpenChanged($event)); })("CameraToggled", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_CameraToggled_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnCameraToggled($event)); })("ShareRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_ShareRequested_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnShareRequested($event)); })("StopShareRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_StopShareRequested_2_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnStopShareRequested()); })("DeviceSelected", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_DeviceSelected_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnDeviceSelected($event)); })("CaptionsToggled", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_CaptionsToggled_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnCaptionsToggled($event)); })("DetailsToggled", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_DetailsToggled_2_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnDetailsToggled()); })("MuteChanged", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_MuteChanged_2_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnComposerMuteChanged($event)); })("EndRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template_mj_realtime_composer_EndRequested_2_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnEndCall()); });
177
183
  i0.ɵɵelementEnd();
178
184
  } if (rf & 2) {
179
185
  const ctx_r1 = i0.ɵɵnextContext(2);
180
- i0.ɵɵproperty("Sources", ctx_r1.VideoSources);
186
+ i0.ɵɵproperty("Sources", ctx_r1.VisibleVideoSources);
181
187
  i0.ɵɵadvance();
182
188
  i0.ɵɵconditional(ctx_r1.ChannelStripVisible ? 1 : -1);
183
189
  i0.ɵɵadvance();
184
- i0.ɵɵproperty("Open", ctx_r1.ComposerOpen)("Compact", ctx_r1.Ui.compact && ctx_r1.Ui.chrome === "orb")("CaptionsOn", ctx_r1.ShowCaptions)("IsMuted", ctx_r1.Muted)("ShowCamera", ctx_r1.CaptureOffers.Camera)("ShowShare", ctx_r1.CaptureOffers.Screen)("CameraOn", ctx_r1.CameraOn)("Sharing", ctx_r1.Sharing)("SharePanels", ctx_r1.SharePanels)("Devices", ctx_r1.CallDevices)("SelectedMicrophoneID", ctx_r1.SelectedMicrophoneID)("SelectedCameraID", ctx_r1.SelectedCameraID)("ShowDetails", ctx_r1.ShowDetailsControl)("DetailsOn", ctx_r1.DetailsPeek);
190
+ i0.ɵɵproperty("Open", ctx_r1.ComposerOpen)("Compact", ctx_r1.Ui.chrome === "orb" || ctx_r1.Ui.compact)("AllowTyping", ctx_r1.Ui.allowTyping)("ShowEnd", ctx_r1.Ui.showEnd)("ShowCaptionsControl", ctx_r1.Ui.showCaptionsControl)("CaptionsOn", ctx_r1.ShowCaptions)("IsMuted", ctx_r1.Muted)("ShowCamera", ctx_r1.CaptureOffers.Camera)("ShowShare", ctx_r1.CaptureOffers.Screen)("CameraOn", ctx_r1.CameraOn)("Sharing", ctx_r1.Sharing)("SharePanels", ctx_r1.SharePanels)("Devices", ctx_r1.CallDevices)("SelectedMicrophoneID", ctx_r1.SelectedMicrophoneID)("SelectedCameraID", ctx_r1.SelectedCameraID)("ShowDetails", ctx_r1.ShowDetailsControl)("DetailsOn", ctx_r1.DetailsPeek);
185
191
  } }
186
192
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Conditional_0_Template(rf, ctx) { if (rf & 1) {
187
193
  const _r10 = i0.ɵɵgetCurrentView();
188
- i0.ɵɵelementStart(0, "div", 45);
194
+ i0.ɵɵelementStart(0, "div", 46);
189
195
  i0.ɵɵlistener("mousedown", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Conditional_0_Template_div_mousedown_0_listener($event) { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnPanelResizeStart($event)); })("dblclick", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Conditional_0_Template_div_dblclick_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnPanelResizeReset()); });
190
196
  i0.ɵɵelementEnd();
191
197
  } if (rf & 2) {
@@ -194,8 +200,8 @@ function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Conditiona
194
200
  } }
195
201
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template(rf, ctx) { if (rf & 1) {
196
202
  const _r9 = i0.ɵɵgetCurrentView();
197
- i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Conditional_0_Template, 1, 2, "div", 42);
198
- i0.ɵɵelementStart(1, "div", 43)(2, "mj-realtime-surface-tabs", 44);
203
+ i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Conditional_0_Template, 1, 2, "div", 43);
204
+ i0.ɵɵelementStart(1, "div", 44)(2, "mj-realtime-surface-tabs", 45);
199
205
  i0.ɵɵlistener("OpenRunRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template_mj_realtime_surface_tabs_OpenRunRequested_2_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnOpenRunRequested($event)); })("CollapsedChange", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template_mj_realtime_surface_tabs_CollapsedChange_2_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnPanelCollapsedChange($event)); })("WideChanged", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template_mj_realtime_surface_tabs_WideChanged_2_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnPanelWideChanged($event)); })("ActiveChannelChange", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template_mj_realtime_surface_tabs_ActiveChannelChange_2_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnActiveChannelChange($event)); })("ChannelSlotChange", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template_mj_realtime_surface_tabs_ChannelSlotChange_2_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnChannelSlotChange($event)); })("MoveRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template_mj_realtime_surface_tabs_MoveRequested_2_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnMoveRequested($event)); })("ResetLayoutRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template_mj_realtime_surface_tabs_ResetLayoutRequested_2_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnResetLayout()); });
200
206
  i0.ɵɵelementEnd()();
201
207
  } if (rf & 2) {
@@ -204,11 +210,11 @@ function RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template(r
204
210
  i0.ɵɵadvance();
205
211
  i0.ɵɵstyleProp("width", ctx_r1.PanelAreaSize, "px");
206
212
  i0.ɵɵadvance();
207
- i0.ɵɵproperty("State", ctx_r1.State)("DevMode", ctx_r1.DevMode)("CurrentUser", ctx_r1.CurrentUser)("EnvironmentID", ctx_r1.EnvironmentID)("ShowActivityTab", ctx_r1.ShowActivityTab)("ExtraArtifacts", ctx_r1.ReviewArtifacts)("Collapsed", ctx_r1.PanelCollapsed)("SurfacePlacements", ctx_r1.SurfaceStage.Placements)("AllowedPlacements", ctx_r1.SurfaceStage.AllowedPlacements);
213
+ i0.ɵɵproperty("State", ctx_r1.State)("DevMode", ctx_r1.Ui.showDevLinks)("CurrentUser", ctx_r1.CurrentUser)("EnvironmentID", ctx_r1.EnvironmentID)("ShowActivityTab", ctx_r1.ShowActivityTab)("ExtraArtifacts", ctx_r1.ReviewArtifacts)("Collapsed", ctx_r1.PanelCollapsed)("SurfacePlacements", ctx_r1.SurfaceStage.Placements)("AllowedPlacements", ctx_r1.SurfaceStage.AllowedPlacements);
208
214
  } }
209
215
  function RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditional_0_Conditional_2_Template(rf, ctx) { if (rf & 1) {
210
216
  const _r11 = i0.ɵɵgetCurrentView();
211
- i0.ɵɵelementStart(0, "mj-media-move-menu", 49);
217
+ i0.ɵɵelementStart(0, "mj-media-move-menu", 50);
212
218
  i0.ɵɵlistener("MoveRequested", function RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditional_0_Conditional_2_Template_mj_media_move_menu_MoveRequested_0_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnMoveRequested($event)); })("ResetLayoutRequested", function RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditional_0_Conditional_2_Template_mj_media_move_menu_ResetLayoutRequested_0_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r1.OnResetLayout()); });
213
219
  i0.ɵɵelementEnd();
214
220
  } if (rf & 2) {
@@ -218,9 +224,9 @@ function RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditiona
218
224
  i0.ɵɵproperty("Key", key_r13)("Title", plugin_r12.TabTitle)("Allowed", ctx_r1.SurfaceStage.AllowedFor(key_r13));
219
225
  } }
220
226
  function RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditional_0_Template(rf, ctx) { if (rf & 1) {
221
- i0.ɵɵelementStart(0, "div", 46);
222
- i0.ɵɵelement(1, "mj-realtime-channel-pane", 47);
223
- i0.ɵɵconditionalCreate(2, RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditional_0_Conditional_2_Template, 1, 3, "mj-media-move-menu", 48);
227
+ i0.ɵɵelementStart(0, "div", 47);
228
+ i0.ɵɵelement(1, "mj-realtime-channel-pane", 48);
229
+ i0.ɵɵconditionalCreate(2, RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditional_0_Conditional_2_Template, 1, 3, "mj-media-move-menu", 49);
224
230
  i0.ɵɵelementEnd();
225
231
  } if (rf & 2) {
226
232
  const plugin_r12 = ctx;
@@ -235,7 +241,7 @@ function RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditiona
235
241
  i0.ɵɵconditional(placement_r16 === "stage" && plugin_r12.ShowsAgentVideo ? 2 : -1);
236
242
  } }
237
243
  function RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Template(rf, ctx) { if (rf & 1) {
238
- i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditional_0_Template, 3, 7, "div", 46);
244
+ i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Conditional_0_Template, 3, 7, "div", 47);
239
245
  } if (rf & 2) {
240
246
  let tmp_9_0;
241
247
  const key_r13 = ctx.$implicit;
@@ -244,7 +250,7 @@ function RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Template(r
244
250
  } }
245
251
  function RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Conditional_0_Template(rf, ctx) { if (rf & 1) {
246
252
  const _r17 = i0.ɵɵgetCurrentView();
247
- i0.ɵɵelementStart(0, "mj-media-move-menu", 51);
253
+ i0.ɵɵelementStart(0, "mj-media-move-menu", 52);
248
254
  i0.ɵɵlistener("MoveRequested", function RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Conditional_0_Template_mj_media_move_menu_MoveRequested_0_listener($event) { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnMoveRequested($event)); })("ResetLayoutRequested", function RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Conditional_0_Template_mj_media_move_menu_ResetLayoutRequested_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnResetLayout()); });
249
255
  i0.ɵɵelementEnd();
250
256
  } if (rf & 2) {
@@ -253,7 +259,7 @@ function RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Conditiona
253
259
  i0.ɵɵproperty("Key", key_r18)("Title", ctx.TabTitle)("Allowed", ctx_r1.SurfaceStage.AllowedFor(key_r18));
254
260
  } }
255
261
  function RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Template(rf, ctx) { if (rf & 1) {
256
- i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Conditional_0_Template, 1, 3, "mj-media-move-menu", 50);
262
+ i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Conditional_0_Template, 1, 3, "mj-media-move-menu", 51);
257
263
  } if (rf & 2) {
258
264
  let tmp_7_0;
259
265
  const key_r18 = ctx.$implicit;
@@ -261,7 +267,7 @@ function RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Template(r
261
267
  i0.ɵɵconditional((tmp_7_0 = ctx_r1.SurfaceStage.PluginFor(key_r18)) ? 0 : -1, tmp_7_0);
262
268
  } }
263
269
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_5_Template(rf, ctx) { if (rf & 1) {
264
- i0.ɵɵelementStart(0, "span", 55);
270
+ i0.ɵɵelementStart(0, "span", 56);
265
271
  i0.ɵɵtext(1);
266
272
  i0.ɵɵelementEnd();
267
273
  } if (rf & 2) {
@@ -270,7 +276,7 @@ function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditiona
270
276
  } }
271
277
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_10_Template(rf, ctx) { if (rf & 1) {
272
278
  const _r20 = i0.ɵɵgetCurrentView();
273
- i0.ɵɵelementStart(0, "mj-media-move-menu", 63);
279
+ i0.ɵɵelementStart(0, "mj-media-move-menu", 62);
274
280
  i0.ɵɵlistener("MoveRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_10_Template_mj_media_move_menu_MoveRequested_0_listener($event) { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnMoveRequested($event)); })("ResetLayoutRequested", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_10_Template_mj_media_move_menu_ResetLayoutRequested_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnResetLayout()); });
275
281
  i0.ɵɵelementEnd();
276
282
  } if (rf & 2) {
@@ -278,52 +284,62 @@ function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditiona
278
284
  const ctx_r1 = i0.ɵɵnextContext(3);
279
285
  i0.ɵɵproperty("Key", stagePlugin_r21.ChannelName)("Title", stagePlugin_r21.TabTitle)("Allowed", ctx_r1.SurfaceStage.AllowedFor(stagePlugin_r21.ChannelName));
280
286
  } }
287
+ function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_11_Template(rf, ctx) { if (rf & 1) {
288
+ const _r22 = i0.ɵɵgetCurrentView();
289
+ i0.ɵɵelementStart(0, "button", 63);
290
+ i0.ɵɵlistener("click", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_11_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.OnFocusPillEnd()); });
291
+ i0.ɵɵelement(1, "i", 64);
292
+ i0.ɵɵelementEnd();
293
+ } }
281
294
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Template(rf, ctx) { if (rf & 1) {
282
295
  const _r19 = i0.ɵɵgetCurrentView();
283
296
  i0.ɵɵelementStart(0, "div", 20);
284
- i0.ɵɵelement(1, "span", 52);
285
- i0.ɵɵelementStart(2, "span", 53)(3, "span", 54);
297
+ i0.ɵɵelement(1, "span", 53);
298
+ i0.ɵɵelementStart(2, "span", 54)(3, "span", 55);
286
299
  i0.ɵɵtext(4);
287
300
  i0.ɵɵelementEnd();
288
- i0.ɵɵconditionalCreate(5, RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_5_Template, 2, 1, "span", 55);
301
+ i0.ɵɵconditionalCreate(5, RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_5_Template, 2, 1, "span", 56);
289
302
  i0.ɵɵelementEnd();
290
- i0.ɵɵelementStart(6, "button", 56);
303
+ i0.ɵɵelementStart(6, "button", 57);
291
304
  i0.ɵɵlistener("click", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnFocusPillMute()); });
292
- i0.ɵɵelement(7, "i", 57);
305
+ i0.ɵɵelement(7, "i", 58);
293
306
  i0.ɵɵelementEnd();
294
- i0.ɵɵelementStart(8, "button", 58);
307
+ i0.ɵɵelementStart(8, "button", 57);
295
308
  i0.ɵɵlistener("click", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnFocusPillExit()); });
296
309
  i0.ɵɵelement(9, "i", 59);
297
310
  i0.ɵɵelementEnd();
298
311
  i0.ɵɵconditionalCreate(10, RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_10_Template, 1, 3, "mj-media-move-menu", 60);
299
- i0.ɵɵelementStart(11, "button", 61);
300
- i0.ɵɵlistener("click", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnFocusPillEnd()); });
301
- i0.ɵɵelement(12, "i", 62);
302
- i0.ɵɵelementEnd()();
312
+ i0.ɵɵconditionalCreate(11, RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Conditional_11_Template, 2, 0, "button", 61);
313
+ i0.ɵɵelementEnd();
303
314
  } if (rf & 2) {
304
315
  let tmp_8_0;
305
- let tmp_14_0;
306
- const state_r5 = i0.ɵɵnextContext();
316
+ let tmp_16_0;
317
+ const state_r4 = i0.ɵɵnextContext();
307
318
  const ctx_r1 = i0.ɵɵnextContext();
308
319
  i0.ɵɵadvance();
309
- i0.ɵɵattribute("data-state", state_r5);
320
+ i0.ɵɵattribute("data-state", state_r4);
310
321
  i0.ɵɵadvance(3);
311
322
  i0.ɵɵtextInterpolate1("Voice for ", ctx_r1.AgentName);
312
323
  i0.ɵɵadvance();
313
- i0.ɵɵconditional((tmp_8_0 = ctx_r1.FocusStateLabel(state_r5)) ? 5 : -1, tmp_8_0);
324
+ i0.ɵɵconditional((tmp_8_0 = ctx_r1.FocusStateLabel(state_r4)) ? 5 : -1, tmp_8_0);
314
325
  i0.ɵɵadvance();
315
326
  i0.ɵɵclassProp("board-focus-pill__btn--active", ctx_r1.FocusPillMuted);
316
327
  i0.ɵɵproperty("title", ctx_r1.FocusPillMuted ? "Unmute" : "Mute");
317
328
  i0.ɵɵattribute("aria-label", ctx_r1.FocusPillMuted ? "Unmute microphone" : "Mute microphone");
318
329
  i0.ɵɵadvance();
319
330
  i0.ɵɵclassProp("fa-microphone", !ctx_r1.FocusPillMuted)("fa-microphone-slash", ctx_r1.FocusPillMuted);
320
- i0.ɵɵadvance(3);
321
- i0.ɵɵconditional((tmp_14_0 = ctx_r1.StagePlugin) ? 10 : -1, tmp_14_0);
331
+ i0.ɵɵadvance();
332
+ i0.ɵɵproperty("title", ctx_r1.Ui.allowTextReveal ? "Show thread" : "Back to the call");
333
+ i0.ɵɵattribute("aria-label", ctx_r1.Ui.allowTextReveal ? "Show the conversation thread" : "Leave focus mode and return to the call");
334
+ i0.ɵɵadvance(2);
335
+ i0.ɵɵconditional((tmp_16_0 = ctx_r1.StagePlugin) ? 10 : -1, tmp_16_0);
336
+ i0.ɵɵadvance();
337
+ i0.ɵɵconditional(ctx_r1.Ui.showEnd ? 11 : -1);
322
338
  } }
323
339
  function RealtimeSessionOverlayComponent_Conditional_0_Conditional_20_Template(rf, ctx) { if (rf & 1) {
324
- const _r22 = i0.ɵɵgetCurrentView();
325
- i0.ɵɵelementStart(0, "mj-realtime-camera-check-card", 64);
326
- i0.ɵɵlistener("Confirmed", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_20_Template_mj_realtime_camera_check_card_Confirmed_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnCameraCheckConfirmed()); })("Declined", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_20_Template_mj_realtime_camera_check_card_Declined_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnCameraCheckDeclined()); });
340
+ const _r23 = i0.ɵɵgetCurrentView();
341
+ i0.ɵɵelementStart(0, "mj-realtime-camera-check-card", 65);
342
+ i0.ɵɵlistener("Confirmed", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_20_Template_mj_realtime_camera_check_card_Confirmed_0_listener() { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnCameraCheckConfirmed()); })("Declined", function RealtimeSessionOverlayComponent_Conditional_0_Conditional_20_Template_mj_realtime_camera_check_card_Declined_0_listener() { i0.ɵɵrestoreView(_r23); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnCameraCheckDeclined()); });
327
343
  i0.ɵɵelementEnd();
328
344
  } if (rf & 2) {
329
345
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -340,55 +356,55 @@ function RealtimeSessionOverlayComponent_Conditional_0_Template(rf, ctx) { if (r
340
356
  i0.ɵɵconditionalCreate(6, RealtimeSessionOverlayComponent_Conditional_0_Conditional_6_Template, 3, 1, "div", 10);
341
357
  i0.ɵɵconditionalCreate(7, RealtimeSessionOverlayComponent_Conditional_0_Conditional_7_Template, 2, 2, "div", 11);
342
358
  i0.ɵɵelementStart(8, "div", 12);
343
- i0.ɵɵconditionalCreate(9, RealtimeSessionOverlayComponent_Conditional_0_Conditional_9_Template, 2, 0, "div", 13)(10, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Template, 10, 8, "div", 14)(11, RealtimeSessionOverlayComponent_Conditional_0_Conditional_11_Template, 1, 5, "mj-realtime-session-thread", 15);
359
+ i0.ɵɵconditionalCreate(9, RealtimeSessionOverlayComponent_Conditional_0_Conditional_9_Template, 2, 0, "div", 13)(10, RealtimeSessionOverlayComponent_Conditional_0_Conditional_10_Template, 8, 9, "div", 14)(11, RealtimeSessionOverlayComponent_Conditional_0_Conditional_11_Template, 1, 5, "mj-realtime-session-thread", 15);
344
360
  i0.ɵɵelementEnd();
345
361
  i0.ɵɵelementStart(12, "div", 16, 2);
346
- i0.ɵɵconditionalCreate(14, RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template, 3, 16);
362
+ i0.ɵɵconditionalCreate(14, RealtimeSessionOverlayComponent_Conditional_0_Conditional_14_Template, 3, 19);
347
363
  i0.ɵɵelementEnd()();
348
364
  i0.ɵɵconditionalCreate(15, RealtimeSessionOverlayComponent_Conditional_0_Conditional_15_Template, 3, 12);
349
365
  i0.ɵɵelementStart(16, "mj-media-stage", 17);
350
366
  i0.ɵɵlistener("PipRectChange", function RealtimeSessionOverlayComponent_Conditional_0_Template_mj_media_stage_PipRectChange_16_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnPipRectChange($event)); });
351
367
  i0.ɵɵtemplate(17, RealtimeSessionOverlayComponent_Conditional_0_ng_template_17_Template, 1, 1, "ng-template", 18)(18, RealtimeSessionOverlayComponent_Conditional_0_ng_template_18_Template, 1, 1, "ng-template", 19);
352
368
  i0.ɵɵelementEnd();
353
- i0.ɵɵconditionalCreate(19, RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Template, 13, 12, "div", 20);
369
+ i0.ɵɵconditionalCreate(19, RealtimeSessionOverlayComponent_Conditional_0_Conditional_19_Template, 12, 15, "div", 20);
354
370
  i0.ɵɵconditionalCreate(20, RealtimeSessionOverlayComponent_Conditional_0_Conditional_20_Template, 1, 3, "mj-realtime-camera-check-card", 21);
355
371
  i0.ɵɵelementEnd();
356
372
  } if (rf & 2) {
357
- let tmp_25_0;
358
- let tmp_40_0;
359
- const state_r5 = ctx;
360
- const callControls_r23 = i0.ɵɵreference(13);
373
+ let tmp_27_0;
374
+ let tmp_42_0;
375
+ const state_r4 = ctx;
376
+ const callControls_r24 = i0.ɵɵreference(13);
361
377
  const ctx_r1 = i0.ɵɵnextContext();
362
378
  i0.ɵɵclassProp("call-overlay--hidden", ctx_r1.Hidden)("call-overlay--review", ctx_r1.IsReviewing)("board-focus", ctx_r1.ChannelFocusMode);
363
379
  i0.ɵɵattribute("aria-label", ctx_r1.IsReviewing ? "Past session review" : "Live voice session");
364
380
  i0.ɵɵadvance(2);
365
- i0.ɵɵproperty("State", state_r5)("Compact", !ctx_r1.IsReviewing && ctx_r1.Ui.compact && ctx_r1.Ui.chrome === "orb")("AgentName", ctx_r1.AgentName)("ErrorLabel", ctx_r1.CallEndLabel)("ModelName", ctx_r1.IsReviewing ? null : i0.ɵɵpipeBind1(3, 40, ctx_r1.ModelName$))("DevMode", ctx_r1.DevMode)("SessionID", ctx_r1.IsReviewing ? ctx_r1.ReviewSessionID : ctx_r1.SessionID)("ReviewMode", ctx_r1.IsReviewing)("ReviewStartedAt", ctx_r1.ReviewStartedAt)("ReviewClosedAt", ctx_r1.ReviewClosedAt)("ReviewCloseReason", ctx_r1.ReviewCloseReason)("ShowGear", !ctx_r1.IsReviewing && ctx_r1.Ui.showGear)("ShowDensityPicker", ctx_r1.Ui.showDensityPicker)("ShowMinimize", !ctx_r1.IsReviewing && ctx_r1.Ui.showMinimize)("ShowStartLive", ctx_r1.AllowStartLive)("Density", ctx_r1.Disclosure.Milestones.Density);
381
+ i0.ɵɵproperty("State", state_r4)("Compact", !ctx_r1.IsReviewing && ctx_r1.Ui.compact && ctx_r1.Ui.chrome === "orb")("HideState", ctx_r1.ShowHero && !ctx_r1.PresenterOnStage)("AgentName", ctx_r1.AgentName)("ErrorLabel", ctx_r1.CallEndLabel)("ModelName", ctx_r1.IsReviewing ? null : i0.ɵɵpipeBind1(3, 42, ctx_r1.ModelName$))("DevMode", ctx_r1.Ui.showDevLinks)("AllowDevLinks", ctx_r1.AllowDevLinks)("SessionID", ctx_r1.IsReviewing ? ctx_r1.ReviewSessionID : ctx_r1.SessionID)("ReviewMode", ctx_r1.IsReviewing)("ReviewStartedAt", ctx_r1.ReviewStartedAt)("ReviewClosedAt", ctx_r1.ReviewClosedAt)("ReviewCloseReason", ctx_r1.ReviewCloseReason)("ShowGear", !ctx_r1.IsReviewing && ctx_r1.Ui.showGear)("ShowDensityPicker", ctx_r1.Ui.showDensityPicker)("ShowMinimize", !ctx_r1.IsReviewing && ctx_r1.Ui.showMinimize)("ShowStartLive", ctx_r1.AllowStartLive)("Density", ctx_r1.Disclosure.Milestones.Density);
366
382
  i0.ɵɵadvance(2);
367
- i0.ɵɵconditional((tmp_25_0 = ctx_r1.MicrophoneNotice) ? 4 : -1, tmp_25_0);
383
+ i0.ɵɵconditional((tmp_27_0 = ctx_r1.MicrophoneNotice) ? 4 : -1, tmp_27_0);
368
384
  i0.ɵɵadvance();
369
385
  i0.ɵɵconditional(ctx_r1.AvatarNotice ? 5 : -1);
370
386
  i0.ɵɵadvance();
371
- i0.ɵɵconditional(!ctx_r1.IsReviewing && ctx_r1.State.Narration && !ctx_r1.State.ActiveCallId && ctx_r1.Disclosure.ShowThread ? 6 : -1);
387
+ i0.ɵɵconditional(!ctx_r1.IsReviewing && ctx_r1.State.Narration && !ctx_r1.State.ActiveCallId && ctx_r1.Ui.showThread ? 6 : -1);
372
388
  i0.ɵɵadvance();
373
389
  i0.ɵɵconditional(!ctx_r1.ShowHero ? 7 : -1);
374
390
  i0.ɵɵadvance();
375
- i0.ɵɵclassProp("call-body--hero", ctx_r1.ShowHero && !ctx_r1.ShowConnectingScreen(state_r5));
391
+ i0.ɵɵclassProp("call-body--hero", ctx_r1.ShowHero && !ctx_r1.ShowConnectingScreen(state_r4));
376
392
  i0.ɵɵadvance();
377
- i0.ɵɵconditional(ctx_r1.ShowConnectingScreen(state_r5) ? 9 : ctx_r1.ShowHero ? 10 : 11);
393
+ i0.ɵɵconditional(ctx_r1.ShowConnectingScreen(state_r4) ? 9 : ctx_r1.ShowHero ? 10 : ctx_r1.Ui.showThread ? 11 : -1);
378
394
  i0.ɵɵadvance(5);
379
395
  i0.ɵɵconditional(!ctx_r1.IsReviewing ? 14 : -1);
380
396
  i0.ɵɵadvance();
381
397
  i0.ɵɵconditional(ctx_r1.ShowPanelArea ? 15 : -1);
382
398
  i0.ɵɵadvance();
383
- i0.ɵɵproperty("Surfaces", ctx_r1.SurfaceStage.Surfaces)("TabSlot", (ctx_r1.StageSlot == null ? null : ctx_r1.StageSlot.Element) ?? null)("StageSlot", ctx_r1.StageSurfaceSlot)("ActiveTabKey", (ctx_r1.StageSlot == null ? null : ctx_r1.StageSlot.Key) ?? null)("PipRects", ctx_r1.PipRects)("PipKeepClear", callControls_r23);
399
+ i0.ɵɵproperty("Surfaces", ctx_r1.SurfaceStage.Surfaces)("TabSlot", (ctx_r1.StageSlot == null ? null : ctx_r1.StageSlot.Element) ?? null)("StageSlot", ctx_r1.StageSurfaceSlot)("ActiveTabKey", (ctx_r1.StageSlot == null ? null : ctx_r1.StageSlot.Key) ?? null)("PipRects", ctx_r1.PipRects)("PipKeepClear", callControls_r24);
384
400
  i0.ɵɵadvance(3);
385
401
  i0.ɵɵconditional(!ctx_r1.IsReviewing && ctx_r1.ChannelFocusMode ? 19 : -1);
386
402
  i0.ɵɵadvance();
387
- i0.ɵɵconditional((tmp_40_0 = ctx_r1.CameraCheck) ? 20 : -1, tmp_40_0);
403
+ i0.ɵɵconditional((tmp_42_0 = ctx_r1.CameraCheck) ? 20 : -1, tmp_42_0);
388
404
  } }
389
405
  function RealtimeSessionOverlayComponent_ng_template_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
390
- i0.ɵɵelementStart(0, "div", 65);
391
- i0.ɵɵelement(1, "mj-realtime-whiteboard", 66);
406
+ i0.ɵɵelementStart(0, "div", 66);
407
+ i0.ɵɵelement(1, "mj-realtime-whiteboard", 67);
392
408
  i0.ɵɵelementEnd();
393
409
  } if (rf & 2) {
394
410
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -396,15 +412,15 @@ function RealtimeSessionOverlayComponent_ng_template_2_Conditional_0_Template(rf
396
412
  i0.ɵɵproperty("State", ctx)("AgentName", ctx_r1.AgentName)("ReadOnly", true);
397
413
  } }
398
414
  function RealtimeSessionOverlayComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) {
399
- i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_ng_template_2_Conditional_0_Template, 2, 3, "div", 65);
415
+ i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_ng_template_2_Conditional_0_Template, 2, 3, "div", 66);
400
416
  } if (rf & 2) {
401
417
  let tmp_3_0;
402
418
  const ctx_r1 = i0.ɵɵnextContext();
403
419
  i0.ɵɵconditional((tmp_3_0 = ctx_r1.ReviewWhiteboard) ? 0 : -1, tmp_3_0);
404
420
  } }
405
421
  function RealtimeSessionOverlayComponent_ng_template_4_Template(rf, ctx) { if (rf & 1) {
406
- i0.ɵɵelementStart(0, "div", 67);
407
- i0.ɵɵelement(1, "mj-storage-media-player", 68);
422
+ i0.ɵɵelementStart(0, "div", 68);
423
+ i0.ɵɵelement(1, "mj-storage-media-player", 69);
408
424
  i0.ɵɵelementEnd();
409
425
  } if (rf & 2) {
410
426
  const ctx_r1 = i0.ɵɵnextContext();
@@ -502,6 +518,18 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
502
518
  * this version doesn't know, such as a newer server's, in place of `AVATAR_NOTICE_CALL_UNKNOWN_REASON_TEXT`.
503
519
  */
504
520
  AvatarNoticeLabels = null;
521
+ /**
522
+ * Whether the top "Audio only: this voice model can't show an avatar" notice banner is shown when
523
+ * an audio-only call connects. Default `false` so standard voice sessions stay calm and uncluttered
524
+ * unless a host explicitly opts into showing avatar capability notices.
525
+ */
526
+ ShowAvatarNotice = false;
527
+ /**
528
+ * Whether the bottom "Agent can see" perception chip is always shown even when only background channel
529
+ * bridges exist. Default `false`: the chip is only shown when the user actively captures their camera or
530
+ * screen ({@link CameraOn} / {@link Sharing}), or when explicitly enabled via `[ShowPerceptionChip]="true"`.
531
+ */
532
+ ShowPerceptionChip = false;
505
533
  // ── Declarative UI configuration (host controls every aspect of the surface) ──
506
534
  //
507
535
  // Each input is a thin, PascalCase setter over a private slot in {@link _uiInputs}.
@@ -538,15 +566,27 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
538
566
  */
539
567
  set Compact(value) { this.setUiInput('compact', value); }
540
568
  get Compact() { return this._uiInputs.compact; }
541
- /** Fade non-essential controls when the session is idle (orb chrome only). Default `true`. */
542
- set AutoHideControls(value) { this.setUiInput('autoHideControls', value); }
543
- get AutoHideControls() { return this._uiInputs.autoHideControls; }
569
+ /**
570
+ * @deprecated No-op since 6.2: the idle fade was never implemented. Kept so existing bindings compile.
571
+ */
572
+ set AutoHideControls(value) { void value; }
573
+ get AutoHideControls() { return undefined; }
544
574
  /**
545
575
  * May the user reveal the transcript at all? `false` makes the widget a pure voice orb
546
576
  * with no path to text (and never graduates to a console in `'auto'`). Default `true`.
547
577
  */
548
578
  set AllowTextReveal(value) { this.setUiInput('allowTextReveal', value); }
549
579
  get AllowTextReveal() { return this._uiInputs.allowTextReveal; }
580
+ /**
581
+ * May the user type into the live session? Default `true`. Mirrors {@link RealtimeUiInputs.allowTyping}.
582
+ *
583
+ * Invariant: `false` removes every road to the composer (the strip's Type button, the lean sheet's Type
584
+ * button, the type-to-compose hotkey, and a programmatic open) and nothing else. It does not touch the
585
+ * transcript, captions, the surface panel or the channel strip. `AllowTextReveal=false` implies
586
+ * `AllowTyping=false`. Turning it off while the dock is open closes the dock; the draft is kept.
587
+ */
588
+ set AllowTyping(value) { this.setUiInput('allowTyping', value); }
589
+ get AllowTyping() { return this._uiInputs.allowTyping; }
550
590
  /** Show the captions toggle. Default `true`. */
551
591
  set ShowCaptionsControl(value) { this.setUiInput('showCaptionsControl', value); }
552
592
  get ShowCaptionsControl() { return this._uiInputs.showCaptionsControl; }
@@ -657,7 +697,8 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
657
697
  /**
658
698
  * A generic hook fired when ANY control is invoked — even one the host hid via inputs
659
699
  * and re-rendered itself. Lets a host observe/react to the full control surface from a
660
- * single binding.
700
+ * single binding. An open of the typing box that first reveals the conversation reports
701
+ * `'captions'` and `'reveal-text'` before `'type'`.
661
702
  */
662
703
  ControlInvoked = new EventEmitter();
663
704
  realtime = inject(RealtimeSessionService);
@@ -888,7 +929,7 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
888
929
  }
889
930
  /** Whether captions run over the agent's video: they are on, and the video presents in the hero. */
890
931
  get ShowAvatarCaptions() {
891
- return this.ShowCaptions && this.ShowHero && this.PresenterOnStage;
932
+ return this._ui.allowTextReveal && this.ShowCaptions && this.ShowHero && this.PresenterOnStage;
892
933
  }
893
934
  /**
894
935
  * Whether the call body shows the connecting screen for `state`: while the call connects, outside review, unless the
@@ -989,11 +1030,11 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
989
1030
  avatarNoticeTimer = null;
990
1031
  /**
991
1032
  * Why this live call shows no avatar its agent asked for, while the notice shows: from the moment the call connects
992
- * until the user dismisses it or it hides itself. `null` otherwise, and always in review.
1033
+ * until the user dismisses it or it hides itself. `null` otherwise, when {@link ShowAvatarNotice} is off, and always in review.
993
1034
  */
994
1035
  get AvatarNotice() {
995
1036
  const notice = this.avatarNotice;
996
- return notice && notice !== this.avatarNoticeDone && !this.IsReviewing ? notice : null;
1037
+ return this.ShowAvatarNotice && notice && notice !== this.avatarNoticeDone && !this.IsReviewing ? notice : null;
997
1038
  }
998
1039
  /**
999
1040
  * The notice's line, in the host's words when it gave some ({@link AvatarNoticeLabels}); a notice without a reason (one
@@ -1033,6 +1074,21 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
1033
1074
  }
1034
1075
  /** The video sources the agent can or could see right now (see {@link RealtimeSessionService.VideoSources$}). */
1035
1076
  VideoSources = [];
1077
+ /**
1078
+ * The video sources surfaced to `<mj-realtime-perception-chip>`.
1079
+ * By default (`ShowPerceptionChip = false`), the chip only appears when the user has an active camera or
1080
+ * screen capture (`CameraOn`, `Sharing`, or an enabled `'camera'` / `'screen'` source), preventing
1081
+ * background channel bridges from cluttering pure-voice calls.
1082
+ */
1083
+ get VisibleVideoSources() {
1084
+ const hasUserCapture = this.CameraOn ||
1085
+ this.Sharing ||
1086
+ this.VideoSources.some((s) => (s.Kind === 'camera' || s.Kind === 'screen') && s.Enabled);
1087
+ if (!this.ShowPerceptionChip && !hasUserCapture) {
1088
+ return [];
1089
+ }
1090
+ return this.VideoSources;
1091
+ }
1036
1092
  /** The user's camera and screen share (see {@link RealtimeSessionService.Captures$}). */
1037
1093
  CaptureStates = REALTIME_CAPTURES_OFF;
1038
1094
  /** Which captures the call offers (see {@link RealtimeSessionService.CaptureOffers$}); the composer shows Camera and Share from it. */
@@ -1310,7 +1366,6 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
1310
1366
  // only asking for the conversation opens the thread.
1311
1367
  TextRevealed: this.ShowCaptions && (this.conversationShown || !this.PresenterOnStage),
1312
1368
  DisclosureShowThread: disclosure.ShowThread,
1313
- DisclosureShowComposer: disclosure.ShowComposer,
1314
1369
  DisclosureShowPanel: disclosure.ShowPanel,
1315
1370
  DisclosureShowGear: disclosure.ShowGear,
1316
1371
  // A surface to populate: the on-demand Details peek, or review (always has a surface).
@@ -1333,6 +1388,10 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
1333
1388
  const next = ResolveRealtimeUi(this.mergedUiInputs, this.buildSignals());
1334
1389
  const prevChrome = this._ui.chrome;
1335
1390
  this._ui = next;
1391
+ // The host just took typing away: close an open dock (the composer keeps its draft).
1392
+ if (!next.allowTyping && this.ComposerOpen) {
1393
+ this.ComposerOpen = false;
1394
+ }
1336
1395
  if (next.chrome !== prevChrome) {
1337
1396
  this.ChromeChanged.emit(next.chrome);
1338
1397
  }
@@ -1433,15 +1492,22 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
1433
1492
  }
1434
1493
  /**
1435
1494
  * Resizing is meaningless while collapsed or when the surface fills (focus mode), and a
1436
- * host may hard-disable it via `[AllowResize]="false"` — in review the resolver's
1437
- * `allowResize` is false (no live surface to resize), so this also reads the host flag
1438
- * directly (defaulting to the historical `true`) rather than the resolved value, keeping
1439
- * drag available in review exactly as before.
1495
+ * host may hard-disable it via `[AllowResize]="false"`. The resolver has no resize output,
1496
+ * so this reads the host flag directly (defaulting to the historical `true`), which keeps
1497
+ * drag available in review too.
1440
1498
  */
1441
1499
  get PanelResizeDisabled() {
1442
1500
  const hostAllows = this.mergedUiInputs.allowResize ?? DEFAULT_REALTIME_UI_INPUTS.allowResize;
1443
1501
  return this.PanelCollapsed || this.ChannelFocusMode || !hostAllows;
1444
1502
  }
1503
+ /**
1504
+ * The host's ceiling on developer links (`[ShowDevLinks]` / the bag), for the banner's gear toggle. Not the
1505
+ * resolved `Ui.showDevLinks`: that one is already ANDed with {@link DevMode}, which the toggle itself sets, so
1506
+ * binding it would hide the toggle until it was on.
1507
+ */
1508
+ get AllowDevLinks() {
1509
+ return this.mergedUiInputs.showDevLinks ?? DEFAULT_REALTIME_UI_INPUTS.showDevLinks;
1510
+ }
1445
1511
  OnPanelCollapsedChange(collapsed) {
1446
1512
  this.PanelCollapsed = collapsed;
1447
1513
  this.cdr.markForCheck();
@@ -1597,16 +1663,19 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
1597
1663
  get ShowPanelArea() {
1598
1664
  return this._ui.showSurfacePanel || this.IsReviewing;
1599
1665
  }
1600
- /** The Details (tabs) toggle is offered while live — it's the panel's one door. */
1666
+ /**
1667
+ * The Details (tabs) toggle is offered while live — it's the panel's one door — unless the host turned the surface
1668
+ * panel off. Reads the host ceiling, not the resolved {@link Ui.showSurfacePanel}: that one also needs the panel to be
1669
+ * earned, and Details is what earns it (same shape as {@link AllowDevLinks}).
1670
+ */
1601
1671
  get ShowDetailsControl() {
1602
- return !this.IsReviewing;
1672
+ return !this.IsReviewing && (this.mergedUiInputs.showSurfacePanel ?? DEFAULT_REALTIME_UI_INPUTS.showSurfacePanel);
1603
1673
  }
1604
1674
  /**
1605
- * Whether the active-channels strip renders. Preserves the historical disclosure gate
1606
- * (level 2+, {@link RealtimeDisclosureModel.ShowComposer}) AND honours the host's
1607
- * `[ShowChannels]` input + the resolver's focus rule: a host that sets `[ShowChannels]`
1608
- * false hard-disables the strip, and channel-focus mode hides it. The strip component
1609
- * itself self-hides when no channels are active, so this stays decluttered.
1675
+ * Whether the active-channels strip renders: the resolved {@link Ui.showChannelStrip}, which
1676
+ * honours the host's `[ShowChannels]` input (false hard-disables the strip), needs an active
1677
+ * channel and console chrome, and hides it in channel-focus mode. The strip component itself
1678
+ * self-hides when no channels are active, so this stays decluttered.
1610
1679
  */
1611
1680
  get ChannelStripVisible() {
1612
1681
  // Reads the RESOLVED Ui.showChannelStrip flag — which already ANDs the host's
@@ -1843,6 +1912,9 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
1843
1912
  }
1844
1913
  /** The hero's "Show the conversation" affordance — turns the text preference on, and opens the thread even over the agent's video. */
1845
1914
  OnTextReveal() {
1915
+ if (!this._ui.allowTextReveal) {
1916
+ return;
1917
+ }
1846
1918
  this.conversationShown = true;
1847
1919
  this.OnCaptionsToggled(true);
1848
1920
  this.TextRevealed.emit();
@@ -1894,7 +1966,7 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
1894
1966
  * keyboard-capturing surface (the remote-browser canvas) already holds focus.
1895
1967
  */
1896
1968
  OnDocumentKeydown(event) {
1897
- if (this.Hidden || this.IsReviewing || !this.realtime.IsActive) {
1969
+ if (this.Hidden || this.IsReviewing || !this.realtime.IsActive || !this._ui.allowTyping) {
1898
1970
  return;
1899
1971
  }
1900
1972
  if (event.metaKey || event.ctrlKey || event.altKey) {
@@ -1940,10 +2012,30 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
1940
2012
  * The composer dock opened (strip Type control / type-to-compose keystroke) or closed (the
1941
2013
  * dock's hide control). Opening raises the 'engaged' milestone for the cross-session ratchet —
1942
2014
  * but the dock itself stays a per-session, user-owned toggle either way.
2015
+ *
2016
+ * Invariant: the typing box is open only while the conversation is readable — a participant must
2017
+ * see what they type (Caliber). Readable = the thread is shown AND captions are on: a console keeps
2018
+ * the thread with captions off, but the thread then hides every caption turn. (While the agent's
2019
+ * video presents in the hero, captions run over the video instead, and the thread waits for an
2020
+ * explicit reveal.) So an open while the conversation is unreadable reveals it first, through the
2021
+ * same path as the hero's "Show the conversation" ({@link OnTextReveal}: captions on and persisted,
2022
+ * {@link TextRevealed} emitted). Every road to the box (Type buttons, the hotkey, a programmatic
2023
+ * open) funnels through here; {@link OnCaptionsToggled} holds the other half.
1943
2024
  */
1944
2025
  OnComposerOpenChanged(open) {
2026
+ // The host disallows typing: refuse any open (closing is always allowed). Checked before the reveal,
2027
+ // so a refused open reveals nothing.
2028
+ if (open && !this._ui.allowTyping) {
2029
+ return;
2030
+ }
2031
+ if (open && !(this._ui.showThread && this.ShowCaptions)) {
2032
+ this.OnTextReveal();
2033
+ }
1945
2034
  this.ComposerOpen = open;
1946
2035
  if (open) {
2036
+ // Opening the box asks for the conversation, like "Show the conversation": pin the thread, so the agent's video
2037
+ // arriving later (which keeps the hero for captions alone) does not hide it under an open box.
2038
+ this.conversationShown = true;
1947
2039
  this.Disclosure.Raise('engaged'); // emits Changed$ → recomputeUi()
1948
2040
  this.ControlInvoked.emit('type');
1949
2041
  setTimeout(() => this.composer?.FocusInput());
@@ -2112,14 +2204,26 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
2112
2204
  * The captions toggle = the persisted text-vs-orb switch: on → the thread renders
2113
2205
  * (raising the text disclosure milestone); off → the orb hero owns the screen again,
2114
2206
  * at any level. Persisted per-user so the choice survives refresh and devices.
2207
+ *
2208
+ * Invariant: the typing box is open only while the conversation is readable (thread shown AND
2209
+ * captions on) — a participant must see what they type (Caliber). So turning captions off closes an
2210
+ * open box, in a console too, where the thread stays but hides its caption turns; the composer instance
2211
+ * is kept, so its draft survives and comes back with the next open. Every captions road (the CC
2212
+ * buttons, {@link SetCaptions}, {@link ToggleCaptions}) funnels through here;
2213
+ * {@link OnComposerOpenChanged} holds the other half.
2115
2214
  */
2116
2215
  OnCaptionsToggled(on) {
2216
+ // The host disallows text: refuse turning captions on (nothing persisted or emitted). Off is always allowed.
2217
+ if (on && !this._ui.allowTextReveal) {
2218
+ return;
2219
+ }
2117
2220
  this.ShowCaptions = on;
2118
2221
  if (on) {
2119
2222
  this.Disclosure.Raise('text'); // emits Changed$ → recomputeUi()
2120
2223
  }
2121
2224
  else {
2122
2225
  this.conversationShown = false;
2226
+ this.ComposerOpen = false;
2123
2227
  }
2124
2228
  this.persistCaptionsPref();
2125
2229
  this.ControlInvoked.emit('captions');
@@ -2428,7 +2532,7 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
2428
2532
  /**
2429
2533
  * Reveal the transcript programmatically — the imperative twin of the orb's "Show the
2430
2534
  * conversation" affordance. Raises the text disclosure level, turns captions on, and
2431
- * emits {@link TextRevealed}.
2535
+ * emits {@link TextRevealed}. Does nothing when the host disallows text (`AllowTextReveal=false`).
2432
2536
  */
2433
2537
  RevealText() {
2434
2538
  this.OnTextReveal();
@@ -2459,7 +2563,8 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
2459
2563
  }
2460
2564
  /**
2461
2565
  * Set captions (the text-vs-orb preference) to an explicit state. Persisted per-user;
2462
- * turning them on also raises the text disclosure level.
2566
+ * turning them on also raises the text disclosure level. Turning them on does nothing when
2567
+ * the host disallows text (`AllowTextReveal=false`); turning them off is always allowed.
2463
2568
  *
2464
2569
  * @param on whether captions/text should be shown.
2465
2570
  */
@@ -2532,8 +2637,8 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
2532
2637
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.presenterSlotRef = _t.first);
2533
2638
  } }, hostBindings: function RealtimeSessionOverlayComponent_HostBindings(rf, ctx) { if (rf & 1) {
2534
2639
  i0.ɵɵlistener("keydown", function RealtimeSessionOverlayComponent_keydown_HostBindingHandler($event) { return ctx.OnDocumentKeydown($event); }, i0.ɵɵresolveDocument);
2535
- } }, inputs: { Hidden: "Hidden", AgentName: "AgentName", CurrentUser: "CurrentUser", EnvironmentID: "EnvironmentID", AvatarNoticeLabels: "AvatarNoticeLabels", Chrome: "Chrome", ConsoleBreakpointPx: "ConsoleBreakpointPx", Compact: "Compact", AutoHideControls: "AutoHideControls", AllowTextReveal: "AllowTextReveal", ShowCaptionsControl: "ShowCaptionsControl", ShowDensityPicker: "ShowDensityPicker", ShowMinimize: "ShowMinimize", ShowEnd: "ShowEnd", ShowSurfacePanel: "ShowSurfacePanel", ShowChannels: "ShowChannels", ShowActivityRail: "ShowActivityRail", ShowDevLinks: "ShowDevLinks", AllowResize: "AllowResize", UiConfig: "UiConfig", ReviewData: "ReviewData", AllowStartLive: "AllowStartLive" }, outputs: { Ended: "Ended", NavigateRequest: "NavigateRequest", StartLiveRequested: "StartLiveRequested", ReviewClosed: "ReviewClosed", Minimized: "Minimized", TextRevealed: "TextRevealed", ChromeChanged: "ChromeChanged", ConnectionStateChanged: "ConnectionStateChanged", MuteChanged: "MuteChanged", DensityChanged: "DensityChanged", SurfacePanelResized: "SurfacePanelResized", ControlInvoked: "ControlInvoked" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 6, vars: 3, consts: [["reviewBoardTpl", ""], ["recordingTpl", ""], ["callControls", ""], ["presenterSlot", ""], ["role", "region", 1, "call-overlay", 3, "call-overlay--hidden", "call-overlay--review", "board-focus"], ["role", "region", 1, "call-overlay"], [1, "call-main"], [3, "OpenSessionRequested", "DevModeToggled", "DensityChanged", "MinimizeRequested", "StartLiveRequested", "CloseRequested", "State", "Compact", "AgentName", "ErrorLabel", "ModelName", "DevMode", "SessionID", "ReviewMode", "ReviewStartedAt", "ReviewClosedAt", "ReviewCloseReason", "ShowGear", "ShowDensityPicker", "ShowMinimize", "ShowStartLive", "Density"], ["Variant", "warning", "Size", "sm", "Icon", "fa-solid fa-microphone-slash", 1, "call-microphone-notice", 3, "Message"], ["Variant", "info", "Size", "sm", "Icon", "fa-solid fa-video-slash", "Dismissible", "", 1, "call-avatar-notice", 3, "Message"], ["role", "status", "aria-live", "polite", 1, "banner-live-note"], [1, "call-presenter", 3, "call-presenter--on"], [1, "call-body"], [1, "call-connecting"], ["role", "status", "aria-live", "polite", 1, "hero", 3, "hero--presenting"], [3, "State", "AgentName", "UserName", "ShowCaptions", "DevMode"], [1, "call-controls"], [1, "call-stage", 3, "PipRectChange", "Surfaces", "TabSlot", "StageSlot", "ActiveTabKey", "PipRects", "PipKeepClear"], ["mjMediaStageSurface", ""], ["mjMediaStagePipActions", ""], ["role", "status", "aria-label", "Live call (board focus)", 1, "board-focus-pill"], [3, "Camera", "AgentName", "Switch"], ["Variant", "info", "Size", "sm", "Icon", "fa-solid fa-video-slash", "Dismissible", "", 1, "call-avatar-notice", 3, "Dismissed", "Message"], ["aria-hidden", "true", 1, "fa-solid", "fa-comment-dots"], [1, "call-presenter"], ["text", "Connecting to the live session\u2026", "size", "medium"], ["role", "status", "aria-live", "polite", 1, "hero"], [1, "hero__presenter"], ["aria-hidden", "true", 1, "hero__caption"], [1, "hero__sr"], ["type", "button", "title", "Show the conversation as text", 1, "hero__reveal", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-closed-captioning"], [1, "hero__orb", 3, "State"], ["aria-hidden", "true", 1, "hero__eq"], [1, "hero__caption-window"], [1, "hero__caption-lines"], [1, "hero__caption-speaker"], [1, "hero__name"], [1, "hero__sub"], [3, "OpenRunRequested", "OpenArtifactRequested", "CancelRequested", "State", "AgentName", "UserName", "ShowCaptions", "DevMode"], [3, "SourceToggled", "SourcePicked", "Sources"], [3, "OpenChanged", "CameraToggled", "ShareRequested", "StopShareRequested", "DeviceSelected", "CaptionsToggled", "DetailsToggled", "MuteChanged", "EndRequested", "Open", "Compact", "CaptionsOn", "IsMuted", "ShowCamera", "ShowShare", "CameraOn", "Sharing", "SharePanels", "Devices", "SelectedMicrophoneID", "SelectedCameraID", "ShowDetails", "DetailsOn"], ["role", "separator", "aria-orientation", "vertical", "aria-label", "Resize the surface panel (double-click to reset)", "title", "Drag to resize \u2022 double-click to reset", 1, "call-resizer", 3, "call-resizer--active"], [1, "call-panel"], [3, "OpenRunRequested", "CollapsedChange", "WideChanged", "ActiveChannelChange", "ChannelSlotChange", "MoveRequested", "ResetLayoutRequested", "State", "DevMode", "CurrentUser", "EnvironmentID", "ShowActivityTab", "ExtraArtifacts", "Collapsed", "SurfacePlacements", "AllowedPlacements"], ["role", "separator", "aria-orientation", "vertical", "aria-label", "Resize the surface panel (double-click to reset)", "title", "Drag to resize \u2022 double-click to reset", 1, "call-resizer", 3, "mousedown", "dblclick"], ["role", "region", 1, "stage-frame", 3, "mjSharePanel", "mjSharePanelIcon"], [3, "Plugin", "Visible", "Placement"], ["Placement", "stage", 1, "stage-presenter-move", 3, "Key", "Title", "Allowed"], ["Placement", "stage", 1, "stage-presenter-move", 3, "MoveRequested", "ResetLayoutRequested", "Key", "Title", "Allowed"], ["Placement", "pip", 3, "Key", "Title", "Allowed"], ["Placement", "pip", 3, "MoveRequested", "ResetLayoutRequested", "Key", "Title", "Allowed"], ["aria-hidden", "true", 1, "board-focus-pill__orb"], [1, "board-focus-pill__text"], [1, "board-focus-pill__name"], [1, "board-focus-pill__state"], ["type", "button", 1, "board-focus-pill__btn", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-solid"], ["type", "button", "title", "Show thread", "aria-label", "Show the conversation thread", 1, "board-focus-pill__btn", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-table-columns"], ["Placement", "stage", 3, "Key", "Title", "Allowed"], ["type", "button", "title", "End call", "aria-label", "End the call", 1, "board-focus-pill__btn", "board-focus-pill__btn--end", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-phone-slash"], ["Placement", "stage", 3, "MoveRequested", "ResetLayoutRequested", "Key", "Title", "Allowed"], [3, "Confirmed", "Declined", "Camera", "AgentName", "Switch"], [1, "review-board-host"], [3, "State", "AgentName", "ReadOnly"], [1, "review-recording-host"], [3, "FileID", "Transcript", "Provider"]], template: function RealtimeSessionOverlayComponent_Template(rf, ctx) { if (rf & 1) {
2536
- i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_Conditional_0_Template, 21, 42, "div", 4);
2640
+ } }, inputs: { Hidden: "Hidden", AgentName: "AgentName", CurrentUser: "CurrentUser", EnvironmentID: "EnvironmentID", AvatarNoticeLabels: "AvatarNoticeLabels", ShowAvatarNotice: "ShowAvatarNotice", ShowPerceptionChip: "ShowPerceptionChip", Chrome: "Chrome", ConsoleBreakpointPx: "ConsoleBreakpointPx", Compact: "Compact", AutoHideControls: "AutoHideControls", AllowTextReveal: "AllowTextReveal", AllowTyping: "AllowTyping", ShowCaptionsControl: "ShowCaptionsControl", ShowDensityPicker: "ShowDensityPicker", ShowMinimize: "ShowMinimize", ShowEnd: "ShowEnd", ShowSurfacePanel: "ShowSurfacePanel", ShowChannels: "ShowChannels", ShowActivityRail: "ShowActivityRail", ShowDevLinks: "ShowDevLinks", AllowResize: "AllowResize", UiConfig: "UiConfig", ReviewData: "ReviewData", AllowStartLive: "AllowStartLive" }, outputs: { Ended: "Ended", NavigateRequest: "NavigateRequest", StartLiveRequested: "StartLiveRequested", ReviewClosed: "ReviewClosed", Minimized: "Minimized", TextRevealed: "TextRevealed", ChromeChanged: "ChromeChanged", ConnectionStateChanged: "ConnectionStateChanged", MuteChanged: "MuteChanged", DensityChanged: "DensityChanged", SurfacePanelResized: "SurfacePanelResized", ControlInvoked: "ControlInvoked" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 6, vars: 3, consts: [["reviewBoardTpl", ""], ["recordingTpl", ""], ["callControls", ""], ["presenterSlot", ""], ["role", "region", 1, "call-overlay", 3, "call-overlay--hidden", "call-overlay--review", "board-focus"], ["role", "region", 1, "call-overlay"], [1, "call-main"], [3, "OpenSessionRequested", "DevModeToggled", "DensityChanged", "MinimizeRequested", "StartLiveRequested", "CloseRequested", "State", "Compact", "HideState", "AgentName", "ErrorLabel", "ModelName", "DevMode", "AllowDevLinks", "SessionID", "ReviewMode", "ReviewStartedAt", "ReviewClosedAt", "ReviewCloseReason", "ShowGear", "ShowDensityPicker", "ShowMinimize", "ShowStartLive", "Density"], ["Variant", "warning", "Size", "sm", "Icon", "fa-solid fa-microphone-slash", 1, "call-microphone-notice", 3, "Message"], ["Variant", "info", "Size", "sm", "Icon", "fa-solid fa-video-slash", "Dismissible", "", 1, "call-avatar-notice", 3, "Message"], ["role", "status", "aria-live", "polite", 1, "banner-live-note"], [1, "call-presenter", 3, "call-presenter--on"], [1, "call-body"], [1, "call-connecting"], ["role", "status", "aria-live", "polite", 1, "hero", 3, "hero--presenting"], [3, "State", "AgentName", "UserName", "ShowCaptions", "DevMode"], [1, "call-controls"], [1, "call-stage", 3, "PipRectChange", "Surfaces", "TabSlot", "StageSlot", "ActiveTabKey", "PipRects", "PipKeepClear"], ["mjMediaStageSurface", ""], ["mjMediaStagePipActions", ""], ["role", "status", "aria-label", "Live call (board focus)", 1, "board-focus-pill"], [3, "Camera", "AgentName", "Switch"], ["Variant", "info", "Size", "sm", "Icon", "fa-solid fa-video-slash", "Dismissible", "", 1, "call-avatar-notice", 3, "Dismissed", "Message"], ["aria-hidden", "true", 1, "fa-solid", "fa-comment-dots"], [1, "call-presenter"], ["text", "Connecting to the live session\u2026", "size", "medium"], ["role", "status", "aria-live", "polite", 1, "hero"], [1, "hero__presenter"], ["aria-hidden", "true", 1, "hero__caption"], [1, "hero__sr"], ["type", "button", "title", "Show the conversation as text", 1, "hero__reveal"], [1, "hero__orb", 3, "State"], ["aria-hidden", "true", 1, "hero__eq"], [1, "hero__caption-window"], [1, "hero__caption-lines"], [1, "hero__caption-speaker"], [1, "hero__name"], [1, "hero__sub"], ["type", "button", "title", "Show the conversation as text", 1, "hero__reveal", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-closed-captioning"], [3, "OpenRunRequested", "OpenArtifactRequested", "CancelRequested", "State", "AgentName", "UserName", "ShowCaptions", "DevMode"], [3, "SourceToggled", "SourcePicked", "Sources"], [3, "OpenChanged", "CameraToggled", "ShareRequested", "StopShareRequested", "DeviceSelected", "CaptionsToggled", "DetailsToggled", "MuteChanged", "EndRequested", "Open", "Compact", "AllowTyping", "ShowEnd", "ShowCaptionsControl", "CaptionsOn", "IsMuted", "ShowCamera", "ShowShare", "CameraOn", "Sharing", "SharePanels", "Devices", "SelectedMicrophoneID", "SelectedCameraID", "ShowDetails", "DetailsOn"], ["role", "separator", "aria-orientation", "vertical", "aria-label", "Resize the surface panel (double-click to reset)", "title", "Drag to resize \u2022 double-click to reset", 1, "call-resizer", 3, "call-resizer--active"], [1, "call-panel"], [3, "OpenRunRequested", "CollapsedChange", "WideChanged", "ActiveChannelChange", "ChannelSlotChange", "MoveRequested", "ResetLayoutRequested", "State", "DevMode", "CurrentUser", "EnvironmentID", "ShowActivityTab", "ExtraArtifacts", "Collapsed", "SurfacePlacements", "AllowedPlacements"], ["role", "separator", "aria-orientation", "vertical", "aria-label", "Resize the surface panel (double-click to reset)", "title", "Drag to resize \u2022 double-click to reset", 1, "call-resizer", 3, "mousedown", "dblclick"], ["role", "region", 1, "stage-frame", 3, "mjSharePanel", "mjSharePanelIcon"], [3, "Plugin", "Visible", "Placement"], ["Placement", "stage", 1, "stage-presenter-move", 3, "Key", "Title", "Allowed"], ["Placement", "stage", 1, "stage-presenter-move", 3, "MoveRequested", "ResetLayoutRequested", "Key", "Title", "Allowed"], ["Placement", "pip", 3, "Key", "Title", "Allowed"], ["Placement", "pip", 3, "MoveRequested", "ResetLayoutRequested", "Key", "Title", "Allowed"], ["aria-hidden", "true", 1, "board-focus-pill__orb"], [1, "board-focus-pill__text"], [1, "board-focus-pill__name"], [1, "board-focus-pill__state"], ["type", "button", 1, "board-focus-pill__btn", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-solid"], ["aria-hidden", "true", 1, "fa-solid", "fa-table-columns"], ["Placement", "stage", 3, "Key", "Title", "Allowed"], ["type", "button", "title", "End call", "aria-label", "End the call", 1, "board-focus-pill__btn", "board-focus-pill__btn--end"], ["Placement", "stage", 3, "MoveRequested", "ResetLayoutRequested", "Key", "Title", "Allowed"], ["type", "button", "title", "End call", "aria-label", "End the call", 1, "board-focus-pill__btn", "board-focus-pill__btn--end", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-phone-slash"], [3, "Confirmed", "Declined", "Camera", "AgentName", "Switch"], [1, "review-board-host"], [3, "State", "AgentName", "ReadOnly"], [1, "review-recording-host"], [3, "FileID", "Transcript", "Provider"]], template: function RealtimeSessionOverlayComponent_Template(rf, ctx) { if (rf & 1) {
2641
+ i0.ɵɵconditionalCreate(0, RealtimeSessionOverlayComponent_Conditional_0_Template, 21, 44, "div", 4);
2537
2642
  i0.ɵɵpipe(1, "async");
2538
2643
  i0.ɵɵtemplate(2, RealtimeSessionOverlayComponent_ng_template_2_Template, 1, 1, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor)(4, RealtimeSessionOverlayComponent_ng_template_4_Template, 2, 3, "ng-template", null, 1, i0.ɵɵtemplateRefExtractor);
2539
2644
  } if (rf & 2) {
@@ -2580,7 +2685,7 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
2580
2685
  RealtimeWhiteboardBoardComponent,
2581
2686
  MJStorageMediaPlayerComponent,
2582
2687
  MJAlertComponent
2583
- ], template: "@if (ConnectionState$ | async; as state) {\n <div class=\"call-overlay\"\n [class.call-overlay--hidden]=\"Hidden\"\n [class.call-overlay--review]=\"IsReviewing\"\n [class.board-focus]=\"ChannelFocusMode\"\n role=\"region\" [attr.aria-label]=\"IsReviewing ? 'Past session review' : 'Live voice session'\">\n\n <!-- PROGRESSIVE DISCLOSURE (the console that grows with you \u2014 Redesign A Progressive):\n level 0 is PURE AUDIO (the hero orb owns the main column; no thread, no composer;\n the strip's Details control peeks at the panels on demand); level 1 reveals the\n caption thread + captions control + type-to-type hint; level 2+ docks the composer\n and keeps the surface panel. CONTENT NEVER FLIPS THE CONSOLE OPEN: finished\n artifacts land as glowing unfocused tabs; the ONE auto-reveal is a channel's\n first agent activity (e.g. the first whiteboard write), which opens the panel as\n a peek with that tab focused \u2014 the left column stays exactly as it was.\n REVIEW always renders the full console. -->\n <div class=\"call-main\">\n <!-- The UNIFIED APP-BAR: identity + state + every session action (Redesign A). -->\n <mj-realtime-agent-banner\n [State]=\"state\"\n [Compact]=\"!IsReviewing && Ui.compact && Ui.chrome === 'orb'\"\n [AgentName]=\"AgentName\"\n [ErrorLabel]=\"CallEndLabel\"\n [ModelName]=\"IsReviewing ? null : (ModelName$ | async)\"\n [DevMode]=\"DevMode\"\n [SessionID]=\"IsReviewing ? ReviewSessionID : SessionID\"\n [ReviewMode]=\"IsReviewing\"\n [ReviewStartedAt]=\"ReviewStartedAt\"\n [ReviewClosedAt]=\"ReviewClosedAt\"\n [ReviewCloseReason]=\"ReviewCloseReason\"\n [ShowGear]=\"!IsReviewing && Ui.showGear\"\n [ShowDensityPicker]=\"Ui.showDensityPicker\"\n [ShowMinimize]=\"!IsReviewing && Ui.showMinimize\"\n [ShowStartLive]=\"AllowStartLive\"\n [Density]=\"Disclosure.Milestones.Density\"\n (OpenSessionRequested)=\"OnOpenSessionRequested($event)\"\n (DevModeToggled)=\"OnDevModeToggled($event)\"\n (DensityChanged)=\"OnDensityChanged($event)\"\n (MinimizeRequested)=\"OnMinimize()\"\n (StartLiveRequested)=\"OnStartLive()\"\n (CloseRequested)=\"OnReviewClose()\">\n </mj-realtime-agent-banner>\n\n <!-- No microphone works: the call lost its microphone, so the agent hears nothing until the user picks one in the\n device menu. It stays for as long as that lasts, with no dismiss button, and goes once a microphone is on.\n Never in review. -->\n @if (MicrophoneNotice; as message) {\n <mj-alert class=\"call-microphone-notice\"\n Variant=\"warning\"\n Size=\"sm\"\n Icon=\"fa-solid fa-microphone-slash\"\n [Message]=\"message\">\n </mj-alert>\n }\n\n <!-- Why the call shows no avatar its agent asked for: once per call, from the moment it connects, until the user\n dismisses it or it hides itself after 10 s. Never in review. -->\n @if (AvatarNotice) {\n <mj-alert class=\"call-avatar-notice\"\n Variant=\"info\"\n Size=\"sm\"\n Icon=\"fa-solid fa-video-slash\"\n [Message]=\"AvatarNoticeMessage\"\n Dismissible\n (Dismissed)=\"OnAvatarNoticeDismissed()\">\n </mj-alert>\n }\n\n <!-- Ephemeral narration with no active working card to anchor to \u2192 under the banner -->\n @if (!IsReviewing && State.Narration && !State.ActiveCallId && Disclosure.ShowThread) {\n <div class=\"banner-live-note\" role=\"status\" aria-live=\"polite\">\n <i class=\"fa-solid fa-comment-dots\" aria-hidden=\"true\"></i>\n {{ State.Narration }}\n </div>\n }\n\n <!-- The agent's place above the thread in the console: the agent's video (the Avatar) lies over it while it presents.\n Outside the scrolling body, so it stays in view as the conversation grows. -->\n @if (!ShowHero) {\n <div class=\"call-presenter\" [class.call-presenter--on]=\"PresenterOnStage\" #presenterSlot></div>\n }\n\n <!-- While the call connects, the connecting screen takes the body, except from a hero the agent's video presents in:\n a resume on a new connection keeps that hero, so the video keeps its place and its last frame. -->\n <div class=\"call-body\" [class.call-body--hero]=\"ShowHero && !ShowConnectingScreen(state)\">\n @if (ShowConnectingScreen(state)) {\n <div class=\"call-connecting\">\n <mj-loading text=\"Connecting to the live session\u2026\" size=\"medium\"></mj-loading>\n </div>\n } @else if (ShowHero) {\n <!-- PURE-AUDIO HERO (level 0): the orb IS the interface \u2014 it breathes with the\n audio inside expanding sound-wave rings; nothing to read, nothing to configure. -->\n <div class=\"hero\" [class.hero--presenting]=\"PresenterOnStage\" [attr.data-state]=\"state\" role=\"status\" aria-live=\"polite\">\n @if (!PresenterOnStage) {\n <mj-realtime-agent-orb class=\"hero__orb\" [State]=\"HeroOrbState(state)\"></mj-realtime-agent-orb>\n <div class=\"hero__eq\" aria-hidden=\"true\">\n <span></span><span></span><span></span><span></span><span></span>\n <span></span><span></span><span></span><span></span>\n </div>\n }\n <!-- The agent's place in the hero: the agent's video (the Avatar) lies over it while it presents. With\n captions on, the newest caption runs over the video's lower third, as subtitles do. Hidden from\n assistive technology: the conversation, a click away, is the accessible transcript, and this live\n region would read every word as it arrives. -->\n <div class=\"hero__presenter\" [class.hero__presenter--on]=\"PresenterOnStage\" #presenterSlot>\n @if (ShowAvatarCaptions && AvatarCaption; as caption) {\n <p class=\"hero__caption\" aria-hidden=\"true\">\n <span class=\"hero__caption-window\">\n <span class=\"hero__caption-lines\">\n @if (caption.Speaker) {\n <span class=\"hero__caption-speaker\">{{ caption.Speaker }}:</span>\n }\n {{ caption.Text }}\n </span>\n </span>\n </p>\n }\n </div>\n @if (!PresenterOnStage) {\n <div class=\"hero__name\">{{ AgentName }}</div>\n <div class=\"hero__sub\">{{ HeroStateLabel(state) }}</div>\n } @else {\n <!-- The agent's tile names it and says what it is doing; this live region still says it for screen readers. -->\n <span class=\"hero__sr\">{{ HeroStateLabel(state) }}</span>\n }\n <button type=\"button\" class=\"hero__reveal\" (click)=\"OnTextReveal()\"\n title=\"Show the conversation as text\">\n <i class=\"fa-solid fa-closed-captioning\" aria-hidden=\"true\"></i>\n Show the conversation\n </button>\n </div>\n } @else {\n <mj-realtime-session-thread\n [State]=\"State\"\n [AgentName]=\"AgentName\"\n [UserName]=\"CurrentUser?.Name || 'You'\"\n [ShowCaptions]=\"IsReviewing ? true : ShowCaptions\"\n [DevMode]=\"DevMode\"\n (OpenRunRequested)=\"OnOpenRunRequested($event)\"\n (OpenArtifactRequested)=\"OnOpenArtifactRequested($event)\"\n (CancelRequested)=\"OnCancelDelegation($event)\">\n </mj-realtime-session-thread>\n }\n </div>\n\n <!-- The call's controls along the foot of the column. The stage starts its picture-in-picture boxes clear of\n them, so a camera or a shared screen never opens over End call (#5408). Empty, so with no size, in review. -->\n <div class=\"call-controls\" #callControls>\n @if (!IsReviewing) {\n <!-- \"Agent can see\": what the agent is looking at, with a switch per source. Always shown while any\n video source exists (a privacy indicator is never gated behind the disclosure ladder). -->\n <mj-realtime-perception-chip [Sources]=\"VideoSources\"\n (SourceToggled)=\"OnVideoSourceToggled($event)\"\n (SourcePicked)=\"OnVideoSourcePicked($event)\">\n </mj-realtime-perception-chip>\n\n <!-- Active channels (earned with the console at level 2+, host-gated via [ShowChannels]).\n The strip component self-hides when there are no active channels. -->\n @if (ChannelStripVisible) {\n <mj-realtime-channel-strip></mj-realtime-channel-strip>\n }\n\n <!-- The BOTTOM DOCK: phone-call strip \u21C4 fused minis+composer \u2014 the user's own\n two-way toggle (Type opens, hide closes), never level-forced. -->\n <mj-realtime-composer\n [Open]=\"ComposerOpen\"\n [Compact]=\"Ui.compact && Ui.chrome === 'orb'\"\n (OpenChanged)=\"OnComposerOpenChanged($event)\"\n [CaptionsOn]=\"ShowCaptions\"\n [IsMuted]=\"Muted\"\n [ShowCamera]=\"CaptureOffers.Camera\"\n [ShowShare]=\"CaptureOffers.Screen\"\n [CameraOn]=\"CameraOn\"\n [Sharing]=\"Sharing\"\n [SharePanels]=\"SharePanels\"\n [Devices]=\"CallDevices\"\n [SelectedMicrophoneID]=\"SelectedMicrophoneID\"\n [SelectedCameraID]=\"SelectedCameraID\"\n (CameraToggled)=\"OnCameraToggled($event)\"\n (ShareRequested)=\"OnShareRequested($event)\"\n (StopShareRequested)=\"OnStopShareRequested()\"\n (DeviceSelected)=\"OnDeviceSelected($event)\"\n [ShowDetails]=\"ShowDetailsControl\"\n [DetailsOn]=\"DetailsPeek\"\n (CaptionsToggled)=\"OnCaptionsToggled($event)\"\n (DetailsToggled)=\"OnDetailsToggled()\"\n (MuteChanged)=\"OnComposerMuteChanged($event)\"\n (EndRequested)=\"OnEndCall()\">\n </mj-realtime-composer>\n }\n </div>\n </div>\n\n <!-- RIGHT: TABBED SURFACE PANEL \u2014 disclosure-gated: it EXISTS once earned (level 2+,\n which the first delegation forces), peeked on demand via the strip's Details\n control, or always in review. Slides in from the right when it arrives \u2014 the\n panel's arrival IS the progress cue. -->\n @if (ShowPanelArea) {\n <!-- Resize handle (hidden while the panel is collapsed or a channel holds focus). -->\n @if (!PanelResizeDisabled) {\n <div class=\"call-resizer\"\n [class.call-resizer--active]=\"IsPanelResizing\"\n role=\"separator\" aria-orientation=\"vertical\"\n aria-label=\"Resize the surface panel (double-click to reset)\"\n title=\"Drag to resize \u2022 double-click to reset\"\n (mousedown)=\"OnPanelResizeStart($event)\"\n (dblclick)=\"OnPanelResizeReset()\"></div>\n }\n\n <div class=\"call-panel\" [style.width.px]=\"PanelAreaSize\">\n <mj-realtime-surface-tabs\n [State]=\"State\"\n [DevMode]=\"DevMode\"\n [CurrentUser]=\"CurrentUser\"\n [EnvironmentID]=\"EnvironmentID\"\n [ShowActivityTab]=\"ShowActivityTab\"\n [ExtraArtifacts]=\"ReviewArtifacts\"\n (OpenRunRequested)=\"OnOpenRunRequested($event)\"\n [Collapsed]=\"PanelCollapsed\"\n (CollapsedChange)=\"OnPanelCollapsedChange($event)\"\n (WideChanged)=\"OnPanelWideChanged($event)\"\n (ActiveChannelChange)=\"OnActiveChannelChange($event)\"\n (ChannelSlotChange)=\"OnChannelSlotChange($event)\"\n [SurfacePlacements]=\"SurfaceStage.Placements\"\n [AllowedPlacements]=\"SurfaceStage.AllowedPlacements\"\n (MoveRequested)=\"OnMoveRequested($event)\"\n (ResetLayoutRequested)=\"OnResetLayout()\">\n </mj-realtime-surface-tabs>\n </div>\n }\n\n <!-- THE STAGE: every channel surface lives here, in one layer over the overlay. A surface\n is created the first time it is seen, lies over its tab's slot while that tab is\n active, fills the overlay while its channel holds focus (or, for the agent's video,\n lies in the agent's place in the call), and otherwise waits out of sight \u2014 so\n collapsing the panel, switching tabs or entering focus never reloads it.\n The pane tells each channel when its surface goes out of sight, so it can pause.\n A channel that opts in (SurfaceShareable, such as the whiteboard) marks its frame as a panel the Share menu\n offers under \"This panel\" while it is on screen. A picture-in-picture box the user has not moved starts\n clear of the call's controls. -->\n <mj-media-stage class=\"call-stage\"\n [Surfaces]=\"SurfaceStage.Surfaces\"\n [TabSlot]=\"StageSlot?.Element ?? null\"\n [StageSlot]=\"StageSurfaceSlot\"\n [ActiveTabKey]=\"StageSlot?.Key ?? null\"\n [PipRects]=\"PipRects\"\n [PipKeepClear]=\"callControls\"\n (PipRectChange)=\"OnPipRectChange($event)\">\n <ng-template mjMediaStageSurface let-key let-visible=\"Visible\" let-placement=\"Placement\">\n @if (SurfaceStage.PluginFor(key); as plugin) {\n <div class=\"stage-frame\" role=\"region\" [attr.aria-label]=\"plugin.TabTitle\"\n [mjSharePanel]=\"plugin.SurfaceShareable ? plugin.TabTitle : null\" [mjSharePanelIcon]=\"plugin.TabIcon\">\n <mj-realtime-channel-pane [Plugin]=\"plugin\" [Visible]=\"visible\" [Placement]=\"placement\"></mj-realtime-channel-pane>\n <!-- A surface presenting the agent has no focus pill, so its \"Move to\u2026\" menu rides on it. -->\n @if (placement === 'stage' && plugin.ShowsAgentVideo) {\n <mj-media-move-menu\n class=\"stage-presenter-move\"\n [Key]=\"key\"\n [Title]=\"plugin.TabTitle\"\n Placement=\"stage\"\n [Allowed]=\"SurfaceStage.AllowedFor(key)\"\n (MoveRequested)=\"OnMoveRequested($event)\"\n (ResetLayoutRequested)=\"OnResetLayout()\">\n </mj-media-move-menu>\n }\n </div>\n }\n </ng-template>\n <!-- A picture-in-picture box's bar carries the same \"Move to\u2026\" menu. -->\n <ng-template mjMediaStagePipActions let-key>\n @if (SurfaceStage.PluginFor(key); as plugin) {\n <mj-media-move-menu\n [Key]=\"key\"\n [Title]=\"plugin.TabTitle\"\n Placement=\"pip\"\n [Allowed]=\"SurfaceStage.AllowedFor(key)\"\n (MoveRequested)=\"OnMoveRequested($event)\"\n (ResetLayoutRequested)=\"OnResetLayout()\">\n </mj-media-move-menu>\n }\n </ng-template>\n </mj-media-stage>\n\n <!-- FOCUS floating call pill: the main column is hidden, so the live call's\n identity + state + mute / show-thread / end controls ride over the surface. -->\n @if (!IsReviewing && ChannelFocusMode) {\n <div class=\"board-focus-pill\" role=\"status\" aria-label=\"Live call (board focus)\">\n <span class=\"board-focus-pill__orb\" [attr.data-state]=\"state\" aria-hidden=\"true\"></span>\n <span class=\"board-focus-pill__text\">\n <span class=\"board-focus-pill__name\">Voice for {{ AgentName }}</span>\n @if (FocusStateLabel(state); as label) {\n <span class=\"board-focus-pill__state\">{{ label }}</span>\n }\n </span>\n <button type=\"button\" class=\"board-focus-pill__btn\"\n [class.board-focus-pill__btn--active]=\"FocusPillMuted\"\n (click)=\"OnFocusPillMute()\"\n [title]=\"FocusPillMuted ? 'Unmute' : 'Mute'\"\n [attr.aria-label]=\"FocusPillMuted ? 'Unmute microphone' : 'Mute microphone'\">\n <i class=\"fa-solid\" [class.fa-microphone]=\"!FocusPillMuted\" [class.fa-microphone-slash]=\"FocusPillMuted\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"board-focus-pill__btn\"\n (click)=\"OnFocusPillExit()\"\n title=\"Show thread\" aria-label=\"Show the conversation thread\">\n <i class=\"fa-solid fa-table-columns\" aria-hidden=\"true\"></i>\n </button>\n @if (StagePlugin; as stagePlugin) {\n <mj-media-move-menu\n [Key]=\"stagePlugin.ChannelName\"\n [Title]=\"stagePlugin.TabTitle\"\n Placement=\"stage\"\n [Allowed]=\"SurfaceStage.AllowedFor(stagePlugin.ChannelName)\"\n (MoveRequested)=\"OnMoveRequested($event)\"\n (ResetLayoutRequested)=\"OnResetLayout()\">\n </mj-media-move-menu>\n }\n <button type=\"button\" class=\"board-focus-pill__btn board-focus-pill__btn--end\"\n (click)=\"OnFocusPillEnd()\"\n title=\"End call\" aria-label=\"End the call\">\n <i class=\"fa-solid fa-phone-slash\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n\n <!-- THE CAMERA CHECK: the first time the user turns the camera on in a call, they see it, and can pick another\n camera, before the agent does. Until they choose, the camera's own box says it is waiting. -->\n @if (CameraCheck; as camera) {\n <mj-realtime-camera-check-card\n [Camera]=\"camera\"\n [AgentName]=\"AgentName\"\n [Switch]=\"SwitchCheckedCamera\"\n (Confirmed)=\"OnCameraCheckConfirmed()\"\n (Declined)=\"OnCameraCheckDeclined()\">\n </mj-realtime-camera-check-card>\n }\n\n </div>\n}\n\n<!-- SESSION REVIEW whiteboard pane body: the reviewed session's saved board, rehydrated\n locally (WhiteboardState.FromJSON) and rendered READ-ONLY (pan/zoom only). Registered\n as a template-based channel tab ONLY when a parseable Whiteboard state exists. -->\n<ng-template #reviewBoardTpl>\n @if (ReviewWhiteboard; as board) {\n <!-- The board host positions itself absolutely \u2014 give it a filling, positioned frame. -->\n <div class=\"review-board-host\">\n <mj-realtime-whiteboard\n [State]=\"board\"\n [AgentName]=\"AgentName\"\n [ReadOnly]=\"true\">\n </mj-realtime-whiteboard>\n </div>\n }\n</ng-template>\n\n<!-- SESSION REVIEW recording pane body: the reviewed session's recorded audio synced to its\n transcript, replayed via the shared storage media player (click-to-seek transcript + playhead\n highlight). Registered as a template-based channel tab ONLY when the reviewed session carries a\n RecordingFileID; the player resolves the authenticated audio itself from that file id. -->\n<ng-template #recordingTpl>\n <div class=\"review-recording-host\">\n <mj-storage-media-player\n [FileID]=\"ReviewRecordingFileID\"\n [Transcript]=\"ReviewCues\"\n [Provider]=\"Provider\">\n </mj-storage-media-player>\n </div>\n</ng-template>\n", styles: [":host {\n display: contents;\n}\n\n/* Fills the conversation panel IN PLACE: the chat area host provides the positioned\n context (position:relative on .chat-area) and this covers it edge to edge \u2014 header,\n thread and composer included. Opaque-ish page surface with a slight blur so the\n conversation underneath reads as \"paused\", not as an app-wide modal. */\n.call-overlay {\n position: absolute;\n inset: 0;\n z-index: 50;\n display: flex;\n background: color-mix(in srgb, var(--mj-bg-page) 94%, transparent);\n backdrop-filter: blur(8px);\n overflow: hidden;\n}\n\n/* Minimized: hidden (NOT destroyed) so the shell's session/view state survives while\n the host shows its floating \"on call\" pill. The audio session is untouched. */\n.call-overlay--hidden {\n display: none;\n}\n\n/* MAIN column: banner (top) \u2192 scrolling thread \u2192 channel strip \u2192 composer \u2192 controls.\n The 420px floor keeps the call column readable while the panel is dragged wide\n (the drag clamp's 70% cap is the other guard). */\n.call-main {\n flex: 1;\n min-width: 420px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* The call's controls at the foot of the column: the \"Agent can see\" chip, the channel strip and the composer. The\n stage starts its picture-in-picture boxes above this box, so it is never squeezed below its content's height. */\n.call-controls {\n flex: none;\n}\n\n.call-body {\n flex: 1;\n overflow-y: auto;\n padding: 16px 22px;\n min-height: 0;\n scrollbar-width: thin;\n scrollbar-color: var(--mj-border-strong) transparent;\n}\n.call-body::-webkit-scrollbar {\n width: 6px;\n}\n.call-body::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n\n.call-connecting {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n min-height: 160px;\n}\n\n/* ---------- PURE-AUDIO HERO (disclosure level 0) ----------\n The orb IS the interface: it breathes with the audio inside expanding sound-wave\n rings, with a small voice equalizer underneath. Nothing to read, nothing to\n configure \u2014 text, panels and the composer are revealed later (or peeked on demand). */\n.call-body--hero {\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n}\n.hero {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n animation: hero-in 420ms cubic-bezier(0.2, 0.8, 0.3, 1);\n}\n@keyframes hero-in {\n from { opacity: 0; transform: scale(0.94); }\n to { opacity: 1; transform: scale(1); }\n}\n/* The orb (mj-realtime-agent-orb) at hero scale. */\n.hero__orb {\n margin-bottom: 4px;\n}\n/* Voice equalizer: lively while the agent speaks, near-still otherwise. */\n.hero__eq {\n display: flex;\n align-items: center;\n gap: 4px;\n height: 30px;\n margin-bottom: 6px;\n}\n.hero__eq span {\n width: 4px;\n height: 8px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-brand-accent, var(--mj-brand-primary));\n opacity: 0.55;\n}\n.hero[data-state='speaking'] .hero__eq span {\n animation: hero-eq 1.05s ease-in-out infinite;\n}\n.hero__eq span:nth-child(1) { animation-delay: 0s; }\n.hero__eq span:nth-child(2) { animation-delay: 0.14s; }\n.hero__eq span:nth-child(3) { animation-delay: 0.28s; }\n.hero__eq span:nth-child(4) { animation-delay: 0.07s; }\n.hero__eq span:nth-child(5) { animation-delay: 0.21s; }\n.hero__eq span:nth-child(6) { animation-delay: 0.35s; }\n.hero__eq span:nth-child(7) { animation-delay: 0.1s; }\n.hero__eq span:nth-child(8) { animation-delay: 0.24s; }\n.hero__eq span:nth-child(9) { animation-delay: 0.03s; }\n@keyframes hero-eq {\n 0%, 100% { height: 7px; opacity: 0.6; }\n 50% { height: 28px; opacity: 1; }\n}\n/* ---------- the agent's place while its video presents (the Avatar) ----------\n The stage lays the agent's video over these boxes; each has a size only while the video presents. Portrait, as\n avatar video is (Google's samples are 704x1280). */\n.hero--presenting {\n height: 100%;\n min-height: 0;\n}\n.hero__presenter,\n.call-presenter {\n display: none;\n}\n.hero__presenter--on {\n display: block;\n position: relative;\n container-type: size;\n flex: 1 1 auto;\n min-height: 160px;\n max-height: 520px;\n aspect-ratio: 3 / 4;\n margin-bottom: 8px;\n}\n/* Captions over the agent's video, as subtitles: the newest two lines, over the lower third and clear of the tile's\n footer. Above the stage (z-index 1), where the video is. Light on a dark band in both themes, like the tile's chips. */\n.hero__caption {\n position: absolute;\n left: 6%;\n right: 6%;\n bottom: 16%;\n z-index: 2;\n margin: 0;\n padding: 6px 10px;\n border-radius: var(--mj-radius-md);\n background: rgba(0, 0, 0, 0.6);\n color: rgba(255, 255, 255, 0.95);\n font-size: 0.95rem;\n line-height: 1.4;\n text-align: center;\n}\n/* Two lines, the newest: older ones leave through the top. The window clips, not the padded band, so nothing of an\n older line shows in the padding. */\n.hero__caption-window {\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n max-height: 2.8em;\n overflow: hidden;\n}\n.hero__caption-speaker {\n font-weight: 600;\n}\n/* A small tile (a short window): one smaller line, so the video still shows. */\n@container (max-height: 240px) {\n .hero__caption {\n bottom: 22%;\n padding: 3px 6px;\n font-size: 0.75rem;\n }\n .hero__caption-window {\n max-height: 1.4em;\n }\n}\n/* In the console it sits above the scrolling thread, so it stays in view as the conversation grows. Wide enough for\n the tile's \"AI-generated video\" label on one line. */\n.call-presenter--on {\n display: block;\n flex: none;\n align-self: center;\n height: 200px;\n aspect-ratio: 4 / 5;\n margin-top: 12px;\n}\n.hero__name {\n font-size: 19px;\n font-weight: 800;\n letter-spacing: -0.01em;\n color: var(--mj-text-primary);\n}\n.hero__sub {\n font-size: 12.5px;\n color: var(--mj-text-muted);\n}\n/* The hero's state for screen readers only, while the agent's tile shows it. */\n.hero__sr {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n/* ---------- AUDIO-REACTIVE MODE (data-audio-live, set by the rAF meter loop) ----------\n With real audio metering the visuals stop acting and start REACTING: the EQ renders the\n true spectrum (--eq-1..9), and [data-voice-dir] colors it by who is speaking (agent =\n brand, user = green). The orb (mj-realtime-agent-orb) reads the same attributes and the\n smoothed output envelope (--voice-out) itself. Without metering (driver attached no\n meters) the attribute stays 'false' and the turn-state keyframe animations stay in charge. */\n/* True-spectrum EQ: per-bar heights from the meter's bins. */\n.call-overlay[data-audio-live='true'] .hero__eq span {\n animation: none;\n transition: height 70ms linear, opacity 120ms linear;\n}\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(1) { height: calc(6px + var(--eq-1, 0) * 24px); opacity: calc(0.45 + var(--eq-1, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(2) { height: calc(6px + var(--eq-2, 0) * 24px); opacity: calc(0.45 + var(--eq-2, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(3) { height: calc(6px + var(--eq-3, 0) * 24px); opacity: calc(0.45 + var(--eq-3, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(4) { height: calc(6px + var(--eq-4, 0) * 24px); opacity: calc(0.45 + var(--eq-4, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(5) { height: calc(6px + var(--eq-5, 0) * 24px); opacity: calc(0.45 + var(--eq-5, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(6) { height: calc(6px + var(--eq-6, 0) * 24px); opacity: calc(0.45 + var(--eq-6, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(7) { height: calc(6px + var(--eq-7, 0) * 24px); opacity: calc(0.45 + var(--eq-7, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(8) { height: calc(6px + var(--eq-8, 0) * 24px); opacity: calc(0.45 + var(--eq-8, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(9) { height: calc(6px + var(--eq-9, 0) * 24px); opacity: calc(0.45 + var(--eq-9, 0) * 0.55); }\n.call-overlay[data-audio-live='true'][data-voice-dir='user'] .hero__eq span {\n background: var(--mj-status-success);\n}\n\n/* The quiet first reveal: show the conversation as text (raises disclosure to level 1). */\n.hero__reveal {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-top: 18px;\n padding: 6px 14px;\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: 11.5px;\n font-weight: 600;\n cursor: pointer;\n transition: color 140ms ease, border-color 140ms ease, background 140ms ease;\n}\n.hero__reveal:hover {\n color: var(--mj-text-secondary);\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n.hero__reveal i {\n font-size: 11px;\n}\n\n/* Ephemeral narration shown under the banner when no working card anchors it */\n.banner-live-note {\n display: flex;\n align-items: flex-start;\n gap: 7px;\n padding: 8px 22px 0;\n font-size: 12px;\n font-style: italic;\n color: var(--mj-text-muted);\n animation: overlay-note-in 220ms ease;\n}\n.banner-live-note i {\n font-size: 10px;\n margin-top: 3px;\n flex-shrink: 0;\n}\n@keyframes overlay-note-in {\n from { opacity: 0; transform: translateY(2px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* The call's notices under the banner (no microphone works; no avatar): mj-alert brings its own tint, border and text\n colours; this only places them. */\n.call-microphone-notice,\n.call-avatar-notice {\n flex-shrink: 0;\n margin: var(--mj-space-2) var(--mj-space-5) 0;\n}\n\n/* ---------- FOCUS-BOARD mode (whiteboard \"Focus board\" toggle) ----------\n The main call column collapses away entirely and the focused channel's surface fills\n the stage; a compact floating call pill keeps the live call reachable. */\n.call-overlay.board-focus .call-main {\n display: none;\n}\n\n/* ---------- the stage (every channel surface, in one layer) ----------\n mj-media-stage covers the overlay and places each surface itself. Above the panel it\n lays surfaces over, and above the call's controls, so its picture-in-picture boxes\n start clear of them (.call-controls); below the onboarding card (5), the menus of the\n dock and the chip (5) and the focus pill (60). */\n.call-stage {\n z-index: 1;\n}\n/* A surface's frame: fills the box the stage gives it. The surface component is created\n beside the pane host inside it, and sizes itself to it (height: 100%). */\n.stage-frame {\n position: relative;\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n/* The \"Move to\u2026\" menu on a surface that presents the agent, backed so it reads over video. Bottom right, in the\n tile's footer, which holds nothing there for the agent, so it never covers the tile's labels. */\n.stage-presenter-move {\n position: absolute;\n bottom: 4px;\n right: 6px;\n z-index: 1;\n border-radius: var(--mj-radius-full);\n background: color-mix(in srgb, var(--mj-bg-surface) 85%, transparent);\n}\n\n/* Floating call pill: orb + state + mute / show-thread / end (per the whiteboard mockup). */\n.board-focus-pill {\n position: absolute;\n left: 64px;\n top: 12px;\n z-index: 60;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 7px 9px 7px 12px;\n border-radius: var(--mj-radius-full, 999px);\n background: color-mix(in srgb, var(--mj-bg-surface-card) 92%, transparent);\n backdrop-filter: blur(8px);\n border: 1px solid var(--mj-border-strong);\n box-shadow: var(--mj-shadow-xl, 0 12px 32px rgba(0, 0, 0, 0.18));\n animation: overlay-note-in 220ms ease;\n}\n.board-focus-pill__orb {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n flex-shrink: 0;\n background: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.board-focus-pill__orb[data-state='speaking'],\n.board-focus-pill__orb[data-state='listening'] {\n animation: board-pill-pulse 1.6s ease-in-out infinite;\n}\n.board-focus-pill__orb[data-state='error'] {\n background: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 18%, transparent);\n}\n@keyframes board-pill-pulse {\n 0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent); }\n 50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--mj-brand-primary) 8%, transparent); }\n}\n.board-focus-pill__text {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.board-focus-pill__name {\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n color: var(--mj-text-primary);\n}\n.board-focus-pill__state {\n font-size: 10.5px;\n font-weight: 600;\n white-space: nowrap;\n color: var(--mj-brand-primary);\n}\n.board-focus-pill__btn {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n border: 1px solid var(--mj-border-strong);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 11px;\n display: grid;\n place-items: center;\n font-family: inherit;\n flex-shrink: 0;\n}\n.board-focus-pill__btn:hover {\n color: var(--mj-text-primary);\n}\n.board-focus-pill__btn--active {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n.board-focus-pill__btn--end {\n background: var(--mj-status-error);\n border-color: var(--mj-status-error);\n color: var(--mj-text-inverse, #fff);\n}\n\n/* ---------- Session review mode ---------- */\n/* Subtle archival tint so a glance says \"this is history, not a live call\". */\n.call-overlay--review {\n background:\n linear-gradient(180deg, color-mix(in srgb, var(--mj-text-muted) 4%, transparent), transparent 120px),\n var(--mj-bg-surface);\n}\n\n/* The review whiteboard pane body: the board component positions itself absolutely\n (inset: 0), so its template-based pane needs a filling, positioned frame. */\n.review-board-host {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n/* The review recording pane body: the evidence player fills its host (:host height:100%),\n so its template-based pane needs a filling, constrained frame. */\n.review-recording-host {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.review-recording-host mj-realtime-evidence-playback {\n flex: 1;\n min-height: 0;\n}\n\n/* ---------- flex layout (main column | resize handle | surface panel) ---------- */\n/* Token-styled resize handle: invisible until hover, brand-tinted while interacting.\n 7px hit target, col-resize cursor; removed (not rendered) while collapsed / focus. */\n.call-resizer {\n flex: 0 0 7px;\n width: 7px;\n cursor: col-resize;\n background: transparent;\n transition: background 140ms ease;\n}\n.call-resizer:hover,\n.call-resizer--active {\n background: color-mix(in srgb, var(--mj-brand-primary) 26%, transparent);\n}\n/* The surface panel: a plain fixed-width flex item (inline width set by the overlay;\n collapsed = the slim strip width). flex-shrink lets it yield to the call column's\n min-width on tight overlays; overflow hidden keeps the flex height chain intact so\n the panel's content scrolls internally. */\n.call-panel {\n flex: 0 1 auto;\n min-width: 0;\n display: flex;\n overflow: hidden;\n /* Disclosure-gated: the panel is CREATED when earned/peeked \u2014 its arrival slides in\n from the right so the reveal doubles as the progress cue. */\n animation: panel-in 420ms cubic-bezier(0.25, 0.8, 0.3, 1);\n}\n@keyframes panel-in {\n from { opacity: 0; transform: translateX(48px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.call-panel > * {\n flex: 1;\n min-width: 0;\n min-height: 0;\n}\n"] }]
2688
+ ], template: "@if (ConnectionState$ | async; as state) {\n <div class=\"call-overlay\"\n [class.call-overlay--hidden]=\"Hidden\"\n [class.call-overlay--review]=\"IsReviewing\"\n [class.board-focus]=\"ChannelFocusMode\"\n role=\"region\" [attr.aria-label]=\"IsReviewing ? 'Past session review' : 'Live voice session'\">\n\n <!-- PROGRESSIVE DISCLOSURE (the console that grows with you \u2014 Redesign A Progressive):\n level 0 is PURE AUDIO (the hero orb owns the main column; no thread, no composer;\n the strip's Details control peeks at the panels on demand); level 1 reveals the\n caption thread + captions control + type-to-type hint; level 2+ docks the composer\n and keeps the surface panel. CONTENT NEVER FLIPS THE CONSOLE OPEN: finished\n artifacts land as glowing unfocused tabs; the ONE auto-reveal is a channel's\n first agent activity (e.g. the first whiteboard write), which opens the panel as\n a peek with that tab focused \u2014 the left column stays exactly as it was.\n REVIEW always renders the full console. -->\n <div class=\"call-main\">\n <!-- The UNIFIED APP-BAR: identity + state + every session action (Redesign A). -->\n <mj-realtime-agent-banner\n [State]=\"state\"\n [Compact]=\"!IsReviewing && Ui.compact && Ui.chrome === 'orb'\"\n [HideState]=\"ShowHero && !PresenterOnStage\"\n [AgentName]=\"AgentName\"\n [ErrorLabel]=\"CallEndLabel\"\n [ModelName]=\"IsReviewing ? null : (ModelName$ | async)\"\n [DevMode]=\"Ui.showDevLinks\"\n [AllowDevLinks]=\"AllowDevLinks\"\n [SessionID]=\"IsReviewing ? ReviewSessionID : SessionID\"\n [ReviewMode]=\"IsReviewing\"\n [ReviewStartedAt]=\"ReviewStartedAt\"\n [ReviewClosedAt]=\"ReviewClosedAt\"\n [ReviewCloseReason]=\"ReviewCloseReason\"\n [ShowGear]=\"!IsReviewing && Ui.showGear\"\n [ShowDensityPicker]=\"Ui.showDensityPicker\"\n [ShowMinimize]=\"!IsReviewing && Ui.showMinimize\"\n [ShowStartLive]=\"AllowStartLive\"\n [Density]=\"Disclosure.Milestones.Density\"\n (OpenSessionRequested)=\"OnOpenSessionRequested($event)\"\n (DevModeToggled)=\"OnDevModeToggled($event)\"\n (DensityChanged)=\"OnDensityChanged($event)\"\n (MinimizeRequested)=\"OnMinimize()\"\n (StartLiveRequested)=\"OnStartLive()\"\n (CloseRequested)=\"OnReviewClose()\">\n </mj-realtime-agent-banner>\n\n <!-- No microphone works: the call lost its microphone, so the agent hears nothing until the user picks one in the\n device menu. It stays for as long as that lasts, with no dismiss button, and goes once a microphone is on.\n Never in review. -->\n @if (MicrophoneNotice; as message) {\n <mj-alert class=\"call-microphone-notice\"\n Variant=\"warning\"\n Size=\"sm\"\n Icon=\"fa-solid fa-microphone-slash\"\n [Message]=\"message\">\n </mj-alert>\n }\n\n <!-- Why the call shows no avatar its agent asked for: once per call, from the moment it connects, until the user\n dismisses it or it hides itself after 10 s. Never in review. -->\n @if (AvatarNotice) {\n <mj-alert class=\"call-avatar-notice\"\n Variant=\"info\"\n Size=\"sm\"\n Icon=\"fa-solid fa-video-slash\"\n [Message]=\"AvatarNoticeMessage\"\n Dismissible\n (Dismissed)=\"OnAvatarNoticeDismissed()\">\n </mj-alert>\n }\n\n <!-- Ephemeral narration with no active working card to anchor to \u2192 under the banner. It is conversation text, so it\n shows exactly while the thread does (Ui.showThread folds the host's text switch, the captions choice, console\n chrome and review) \u2014 never on the session's disclosure ratchet, which only goes up. -->\n @if (!IsReviewing && State.Narration && !State.ActiveCallId && Ui.showThread) {\n <div class=\"banner-live-note\" role=\"status\" aria-live=\"polite\">\n <i class=\"fa-solid fa-comment-dots\" aria-hidden=\"true\"></i>\n {{ State.Narration }}\n </div>\n }\n\n <!-- The agent's place above the thread in the console: the agent's video (the Avatar) lies over it while it presents.\n Outside the scrolling body, so it stays in view as the conversation grows. -->\n @if (!ShowHero) {\n <div class=\"call-presenter\" [class.call-presenter--on]=\"PresenterOnStage\" #presenterSlot></div>\n }\n\n <!-- While the call connects, the connecting screen takes the body, except from a hero the agent's video presents in:\n a resume on a new connection keeps that hero, so the video keeps its place and its last frame. -->\n <div class=\"call-body\" [class.call-body--hero]=\"ShowHero && !ShowConnectingScreen(state)\">\n @if (ShowConnectingScreen(state)) {\n <div class=\"call-connecting\">\n <mj-loading text=\"Connecting to the live session\u2026\" size=\"medium\"></mj-loading>\n </div>\n } @else if (ShowHero) {\n <!-- PURE-AUDIO HERO (level 0): the orb IS the interface \u2014 it breathes with the\n audio inside expanding sound-wave rings; nothing to read, nothing to configure. -->\n <div class=\"hero\" [class.hero--presenting]=\"PresenterOnStage\" [attr.data-state]=\"state\" role=\"status\" aria-live=\"polite\">\n @if (!PresenterOnStage) {\n <mj-realtime-agent-orb class=\"hero__orb\" [State]=\"HeroOrbState(state)\"></mj-realtime-agent-orb>\n <div class=\"hero__eq\" aria-hidden=\"true\">\n <span></span><span></span><span></span><span></span><span></span>\n <span></span><span></span><span></span><span></span>\n </div>\n }\n <!-- The agent's place in the hero: the agent's video (the Avatar) lies over it while it presents. With\n captions on, the newest caption runs over the video's lower third, as subtitles do. Hidden from\n assistive technology: the conversation, a click away, is the accessible transcript, and this live\n region would read every word as it arrives. -->\n <div class=\"hero__presenter\" [class.hero__presenter--on]=\"PresenterOnStage\" #presenterSlot>\n @if (ShowAvatarCaptions && AvatarCaption; as caption) {\n <p class=\"hero__caption\" aria-hidden=\"true\">\n <span class=\"hero__caption-window\">\n <span class=\"hero__caption-lines\">\n @if (caption.Speaker) {\n <span class=\"hero__caption-speaker\">{{ caption.Speaker }}:</span>\n }\n {{ caption.Text }}\n </span>\n </span>\n </p>\n }\n </div>\n @if (!PresenterOnStage) {\n <div class=\"hero__name\">{{ AgentName }}</div>\n <div class=\"hero__sub\">{{ HeroStateLabel(state) }}</div>\n } @else {\n <!-- The agent's tile names it and says what it is doing; this live region still says it for screen readers. -->\n <span class=\"hero__sr\">{{ HeroStateLabel(state) }}</span>\n }\n @if (Ui.allowTextReveal && (PresenterOnStage || !Ui.showCaptionsControl)) {\n <button type=\"button\" class=\"hero__reveal\" (click)=\"OnTextReveal()\"\n title=\"Show the conversation as text\">\n <i class=\"fa-solid fa-closed-captioning\" aria-hidden=\"true\"></i>\n Show the conversation\n </button>\n }\n </div>\n } @else if (Ui.showThread) {\n <mj-realtime-session-thread\n [State]=\"State\"\n [AgentName]=\"AgentName\"\n [UserName]=\"CurrentUser?.Name || 'You'\"\n [ShowCaptions]=\"IsReviewing ? true : ShowCaptions\"\n [DevMode]=\"Ui.showDevLinks\"\n (OpenRunRequested)=\"OnOpenRunRequested($event)\"\n (OpenArtifactRequested)=\"OnOpenArtifactRequested($event)\"\n (CancelRequested)=\"OnCancelDelegation($event)\">\n </mj-realtime-session-thread>\n }\n </div>\n\n <!-- The call's controls along the foot of the column. The stage starts its picture-in-picture boxes clear of\n them, so a camera or a shared screen never opens over End call (#5408). Empty, so with no size, in review. -->\n <div class=\"call-controls\" #callControls>\n @if (!IsReviewing) {\n <!-- \"Agent can see\": what the agent is looking at, with a switch per source. Shown while the user\n captures camera/screen (or when [ShowPerceptionChip]=\"true\"). -->\n <mj-realtime-perception-chip [Sources]=\"VisibleVideoSources\"\n (SourceToggled)=\"OnVideoSourceToggled($event)\"\n (SourcePicked)=\"OnVideoSourcePicked($event)\">\n </mj-realtime-perception-chip>\n\n <!-- Active channels (earned with the console at level 2+, host-gated via [ShowChannels]).\n The strip component self-hides when there are no active channels. -->\n @if (ChannelStripVisible) {\n <mj-realtime-channel-strip></mj-realtime-channel-strip>\n }\n\n <!-- The BOTTOM DOCK: phone-call strip \u21C4 fused minis+composer \u2014 the user's own\n two-way toggle (Type opens, hide closes), never level-forced. -->\n <mj-realtime-composer\n [Open]=\"ComposerOpen\"\n [Compact]=\"Ui.chrome === 'orb' || Ui.compact\"\n (OpenChanged)=\"OnComposerOpenChanged($event)\"\n [AllowTyping]=\"Ui.allowTyping\"\n [ShowEnd]=\"Ui.showEnd\"\n [ShowCaptionsControl]=\"Ui.showCaptionsControl\"\n [CaptionsOn]=\"ShowCaptions\"\n [IsMuted]=\"Muted\"\n [ShowCamera]=\"CaptureOffers.Camera\"\n [ShowShare]=\"CaptureOffers.Screen\"\n [CameraOn]=\"CameraOn\"\n [Sharing]=\"Sharing\"\n [SharePanels]=\"SharePanels\"\n [Devices]=\"CallDevices\"\n [SelectedMicrophoneID]=\"SelectedMicrophoneID\"\n [SelectedCameraID]=\"SelectedCameraID\"\n (CameraToggled)=\"OnCameraToggled($event)\"\n (ShareRequested)=\"OnShareRequested($event)\"\n (StopShareRequested)=\"OnStopShareRequested()\"\n (DeviceSelected)=\"OnDeviceSelected($event)\"\n [ShowDetails]=\"ShowDetailsControl\"\n [DetailsOn]=\"DetailsPeek\"\n (CaptionsToggled)=\"OnCaptionsToggled($event)\"\n (DetailsToggled)=\"OnDetailsToggled()\"\n (MuteChanged)=\"OnComposerMuteChanged($event)\"\n (EndRequested)=\"OnEndCall()\">\n </mj-realtime-composer>\n }\n </div>\n </div>\n\n <!-- RIGHT: TABBED SURFACE PANEL \u2014 disclosure-gated: it EXISTS once earned (level 2+,\n which the first delegation forces), peeked on demand via the strip's Details\n control, or always in review. Slides in from the right when it arrives \u2014 the\n panel's arrival IS the progress cue. -->\n @if (ShowPanelArea) {\n <!-- Resize handle (hidden while the panel is collapsed or a channel holds focus). -->\n @if (!PanelResizeDisabled) {\n <div class=\"call-resizer\"\n [class.call-resizer--active]=\"IsPanelResizing\"\n role=\"separator\" aria-orientation=\"vertical\"\n aria-label=\"Resize the surface panel (double-click to reset)\"\n title=\"Drag to resize \u2022 double-click to reset\"\n (mousedown)=\"OnPanelResizeStart($event)\"\n (dblclick)=\"OnPanelResizeReset()\"></div>\n }\n\n <div class=\"call-panel\" [style.width.px]=\"PanelAreaSize\">\n <mj-realtime-surface-tabs\n [State]=\"State\"\n [DevMode]=\"Ui.showDevLinks\"\n [CurrentUser]=\"CurrentUser\"\n [EnvironmentID]=\"EnvironmentID\"\n [ShowActivityTab]=\"ShowActivityTab\"\n [ExtraArtifacts]=\"ReviewArtifacts\"\n (OpenRunRequested)=\"OnOpenRunRequested($event)\"\n [Collapsed]=\"PanelCollapsed\"\n (CollapsedChange)=\"OnPanelCollapsedChange($event)\"\n (WideChanged)=\"OnPanelWideChanged($event)\"\n (ActiveChannelChange)=\"OnActiveChannelChange($event)\"\n (ChannelSlotChange)=\"OnChannelSlotChange($event)\"\n [SurfacePlacements]=\"SurfaceStage.Placements\"\n [AllowedPlacements]=\"SurfaceStage.AllowedPlacements\"\n (MoveRequested)=\"OnMoveRequested($event)\"\n (ResetLayoutRequested)=\"OnResetLayout()\">\n </mj-realtime-surface-tabs>\n </div>\n }\n\n <!-- THE STAGE: every channel surface lives here, in one layer over the overlay. A surface\n is created the first time it is seen, lies over its tab's slot while that tab is\n active, fills the overlay while its channel holds focus (or, for the agent's video,\n lies in the agent's place in the call), and otherwise waits out of sight \u2014 so\n collapsing the panel, switching tabs or entering focus never reloads it.\n The pane tells each channel when its surface goes out of sight, so it can pause.\n A channel that opts in (SurfaceShareable, such as the whiteboard) marks its frame as a panel the Share menu\n offers under \"This panel\" while it is on screen. A picture-in-picture box the user has not moved starts\n clear of the call's controls. -->\n <mj-media-stage class=\"call-stage\"\n [Surfaces]=\"SurfaceStage.Surfaces\"\n [TabSlot]=\"StageSlot?.Element ?? null\"\n [StageSlot]=\"StageSurfaceSlot\"\n [ActiveTabKey]=\"StageSlot?.Key ?? null\"\n [PipRects]=\"PipRects\"\n [PipKeepClear]=\"callControls\"\n (PipRectChange)=\"OnPipRectChange($event)\">\n <ng-template mjMediaStageSurface let-key let-visible=\"Visible\" let-placement=\"Placement\">\n @if (SurfaceStage.PluginFor(key); as plugin) {\n <div class=\"stage-frame\" role=\"region\" [attr.aria-label]=\"plugin.TabTitle\"\n [mjSharePanel]=\"plugin.SurfaceShareable ? plugin.TabTitle : null\" [mjSharePanelIcon]=\"plugin.TabIcon\">\n <mj-realtime-channel-pane [Plugin]=\"plugin\" [Visible]=\"visible\" [Placement]=\"placement\"></mj-realtime-channel-pane>\n <!-- A surface presenting the agent has no focus pill, so its \"Move to\u2026\" menu rides on it. -->\n @if (placement === 'stage' && plugin.ShowsAgentVideo) {\n <mj-media-move-menu\n class=\"stage-presenter-move\"\n [Key]=\"key\"\n [Title]=\"plugin.TabTitle\"\n Placement=\"stage\"\n [Allowed]=\"SurfaceStage.AllowedFor(key)\"\n (MoveRequested)=\"OnMoveRequested($event)\"\n (ResetLayoutRequested)=\"OnResetLayout()\">\n </mj-media-move-menu>\n }\n </div>\n }\n </ng-template>\n <!-- A picture-in-picture box's bar carries the same \"Move to\u2026\" menu. -->\n <ng-template mjMediaStagePipActions let-key>\n @if (SurfaceStage.PluginFor(key); as plugin) {\n <mj-media-move-menu\n [Key]=\"key\"\n [Title]=\"plugin.TabTitle\"\n Placement=\"pip\"\n [Allowed]=\"SurfaceStage.AllowedFor(key)\"\n (MoveRequested)=\"OnMoveRequested($event)\"\n (ResetLayoutRequested)=\"OnResetLayout()\">\n </mj-media-move-menu>\n }\n </ng-template>\n </mj-media-stage>\n\n <!-- FOCUS floating call pill: the main column is hidden, so the live call's\n identity + state + mute / show-thread / end controls ride over the surface. -->\n @if (!IsReviewing && ChannelFocusMode) {\n <div class=\"board-focus-pill\" role=\"status\" aria-label=\"Live call (board focus)\">\n <span class=\"board-focus-pill__orb\" [attr.data-state]=\"state\" aria-hidden=\"true\"></span>\n <span class=\"board-focus-pill__text\">\n <span class=\"board-focus-pill__name\">Voice for {{ AgentName }}</span>\n @if (FocusStateLabel(state); as label) {\n <span class=\"board-focus-pill__state\">{{ label }}</span>\n }\n </span>\n <button type=\"button\" class=\"board-focus-pill__btn\"\n [class.board-focus-pill__btn--active]=\"FocusPillMuted\"\n (click)=\"OnFocusPillMute()\"\n [title]=\"FocusPillMuted ? 'Unmute' : 'Mute'\"\n [attr.aria-label]=\"FocusPillMuted ? 'Unmute microphone' : 'Mute microphone'\">\n <i class=\"fa-solid\" [class.fa-microphone]=\"!FocusPillMuted\" [class.fa-microphone-slash]=\"FocusPillMuted\" aria-hidden=\"true\"></i>\n </button>\n <!-- The focus-mode exit, always offered: it is the only way off a focused surface. With text\n disallowed the column comes back as the orb hero, so it is labelled as a return to the call. -->\n <button type=\"button\" class=\"board-focus-pill__btn\"\n (click)=\"OnFocusPillExit()\"\n [title]=\"Ui.allowTextReveal ? 'Show thread' : 'Back to the call'\"\n [attr.aria-label]=\"Ui.allowTextReveal ? 'Show the conversation thread' : 'Leave focus mode and return to the call'\">\n <i class=\"fa-solid fa-table-columns\" aria-hidden=\"true\"></i>\n </button>\n @if (StagePlugin; as stagePlugin) {\n <mj-media-move-menu\n [Key]=\"stagePlugin.ChannelName\"\n [Title]=\"stagePlugin.TabTitle\"\n Placement=\"stage\"\n [Allowed]=\"SurfaceStage.AllowedFor(stagePlugin.ChannelName)\"\n (MoveRequested)=\"OnMoveRequested($event)\"\n (ResetLayoutRequested)=\"OnResetLayout()\">\n </mj-media-move-menu>\n }\n @if (Ui.showEnd) {\n <button type=\"button\" class=\"board-focus-pill__btn board-focus-pill__btn--end\"\n (click)=\"OnFocusPillEnd()\"\n title=\"End call\" aria-label=\"End the call\">\n <i class=\"fa-solid fa-phone-slash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n }\n\n <!-- THE CAMERA CHECK: the first time the user turns the camera on in a call, they see it, and can pick another\n camera, before the agent does. Until they choose, the camera's own box says it is waiting. -->\n @if (CameraCheck; as camera) {\n <mj-realtime-camera-check-card\n [Camera]=\"camera\"\n [AgentName]=\"AgentName\"\n [Switch]=\"SwitchCheckedCamera\"\n (Confirmed)=\"OnCameraCheckConfirmed()\"\n (Declined)=\"OnCameraCheckDeclined()\">\n </mj-realtime-camera-check-card>\n }\n\n </div>\n}\n\n<!-- SESSION REVIEW whiteboard pane body: the reviewed session's saved board, rehydrated\n locally (WhiteboardState.FromJSON) and rendered READ-ONLY (pan/zoom only). Registered\n as a template-based channel tab ONLY when a parseable Whiteboard state exists. -->\n<ng-template #reviewBoardTpl>\n @if (ReviewWhiteboard; as board) {\n <!-- The board host positions itself absolutely \u2014 give it a filling, positioned frame. -->\n <div class=\"review-board-host\">\n <mj-realtime-whiteboard\n [State]=\"board\"\n [AgentName]=\"AgentName\"\n [ReadOnly]=\"true\">\n </mj-realtime-whiteboard>\n </div>\n }\n</ng-template>\n\n<!-- SESSION REVIEW recording pane body: the reviewed session's recorded audio synced to its\n transcript, replayed via the shared storage media player (click-to-seek transcript + playhead\n highlight). Registered as a template-based channel tab ONLY when the reviewed session carries a\n RecordingFileID; the player resolves the authenticated audio itself from that file id. -->\n<ng-template #recordingTpl>\n <div class=\"review-recording-host\">\n <mj-storage-media-player\n [FileID]=\"ReviewRecordingFileID\"\n [Transcript]=\"ReviewCues\"\n [Provider]=\"Provider\">\n </mj-storage-media-player>\n </div>\n</ng-template>\n", styles: [":host {\n display: contents;\n}\n\n/* Fills the conversation panel IN PLACE: the chat area host provides the positioned\n context (position:relative on .chat-area) and this covers it edge to edge \u2014 header,\n thread and composer included. Opaque-ish page surface with a slight blur so the\n conversation underneath reads as \"paused\", not as an app-wide modal. */\n.call-overlay {\n position: absolute;\n inset: 0;\n z-index: 50;\n display: flex;\n background: color-mix(in srgb, var(--mj-bg-page) 94%, transparent);\n backdrop-filter: blur(8px);\n overflow: hidden;\n}\n\n/* Minimized: hidden (NOT destroyed) so the shell's session/view state survives while\n the host shows its floating \"on call\" pill. The audio session is untouched. */\n.call-overlay--hidden {\n display: none;\n}\n\n/* MAIN column: banner (top) \u2192 scrolling thread \u2192 channel strip \u2192 composer \u2192 controls.\n The 420px floor keeps the call column readable while the panel is dragged wide\n (the drag clamp's 70% cap is the other guard). */\n.call-main {\n flex: 1;\n min-width: 420px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* The call's controls at the foot of the column: the \"Agent can see\" chip, the channel strip and the composer. The\n stage starts its picture-in-picture boxes above this box, so it is never squeezed below its content's height. */\n.call-controls {\n flex: none;\n}\n\n.call-body {\n flex: 1;\n overflow-y: auto;\n padding: 16px 22px;\n min-height: 0;\n scrollbar-width: thin;\n scrollbar-color: var(--mj-border-strong) transparent;\n}\n.call-body::-webkit-scrollbar {\n width: 6px;\n}\n.call-body::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 3px;\n}\n\n.call-connecting {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n min-height: 160px;\n}\n\n/* ---------- PURE-AUDIO HERO (disclosure level 0) ----------\n The orb IS the interface: it breathes with the audio inside expanding sound-wave\n rings, with a small voice equalizer underneath. Nothing to read, nothing to\n configure \u2014 text, panels and the composer are revealed later (or peeked on demand). */\n.call-body--hero {\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n}\n.hero {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n animation: hero-in 420ms cubic-bezier(0.2, 0.8, 0.3, 1);\n}\n@keyframes hero-in {\n from { opacity: 0; transform: scale(0.94); }\n to { opacity: 1; transform: scale(1); }\n}\n/* The orb (mj-realtime-agent-orb) at hero scale. */\n.hero__orb {\n margin-bottom: 4px;\n}\n/* Voice equalizer: lively while the agent speaks, near-still otherwise. */\n.hero__eq {\n display: flex;\n align-items: center;\n gap: 4px;\n height: 30px;\n margin-bottom: 6px;\n}\n.hero__eq span {\n width: 4px;\n height: 8px;\n border-radius: var(--mj-radius-full, 9999px);\n background: var(--mj-brand-accent, var(--mj-brand-primary));\n opacity: 0.55;\n}\n.hero[data-state='speaking'] .hero__eq span {\n animation: hero-eq 1.05s ease-in-out infinite;\n}\n.hero__eq span:nth-child(1) { animation-delay: 0s; }\n.hero__eq span:nth-child(2) { animation-delay: 0.14s; }\n.hero__eq span:nth-child(3) { animation-delay: 0.28s; }\n.hero__eq span:nth-child(4) { animation-delay: 0.07s; }\n.hero__eq span:nth-child(5) { animation-delay: 0.21s; }\n.hero__eq span:nth-child(6) { animation-delay: 0.35s; }\n.hero__eq span:nth-child(7) { animation-delay: 0.1s; }\n.hero__eq span:nth-child(8) { animation-delay: 0.24s; }\n.hero__eq span:nth-child(9) { animation-delay: 0.03s; }\n@keyframes hero-eq {\n 0%, 100% { height: 7px; opacity: 0.6; }\n 50% { height: 28px; opacity: 1; }\n}\n/* ---------- the agent's place while its video presents (the Avatar) ----------\n The stage lays the agent's video over these boxes; each has a size only while the video presents. Portrait, as\n avatar video is (Google's samples are 704x1280). */\n.hero--presenting {\n height: 100%;\n min-height: 0;\n}\n.hero__presenter,\n.call-presenter {\n display: none;\n}\n.hero__presenter--on {\n display: block;\n position: relative;\n container-type: size;\n flex: 1 1 auto;\n min-height: 160px;\n max-height: 520px;\n aspect-ratio: 3 / 4;\n margin-bottom: 8px;\n}\n/* Captions over the agent's video, as subtitles: the newest two lines, over the lower third and clear of the tile's\n footer. Above the stage (z-index 1), where the video is. Light on a dark band in both themes, like the tile's chips. */\n.hero__caption {\n position: absolute;\n left: 6%;\n right: 6%;\n bottom: 16%;\n z-index: 2;\n margin: 0;\n padding: 6px 10px;\n border-radius: var(--mj-radius-md);\n background: rgba(0, 0, 0, 0.6);\n color: rgba(255, 255, 255, 0.95);\n font-size: 0.95rem;\n line-height: 1.4;\n text-align: center;\n}\n/* Two lines, the newest: older ones leave through the top. The window clips, not the padded band, so nothing of an\n older line shows in the padding. */\n.hero__caption-window {\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n max-height: 2.8em;\n overflow: hidden;\n}\n.hero__caption-speaker {\n font-weight: 600;\n}\n/* A small tile (a short window): one smaller line, so the video still shows. */\n@container (max-height: 240px) {\n .hero__caption {\n bottom: 22%;\n padding: 3px 6px;\n font-size: 0.75rem;\n }\n .hero__caption-window {\n max-height: 1.4em;\n }\n}\n/* In the console it sits above the scrolling thread, so it stays in view as the conversation grows. Wide enough for\n the tile's \"AI-generated video\" label on one line. */\n.call-presenter--on {\n display: block;\n flex: none;\n align-self: center;\n height: 200px;\n aspect-ratio: 4 / 5;\n margin-top: 12px;\n}\n.hero__name {\n font-size: 19px;\n font-weight: 800;\n letter-spacing: -0.01em;\n color: var(--mj-text-primary);\n}\n.hero__sub {\n font-size: 12.5px;\n color: var(--mj-text-muted);\n}\n/* The hero's state for screen readers only, while the agent's tile shows it. */\n.hero__sr {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n/* ---------- AUDIO-REACTIVE MODE (data-audio-live, set by the rAF meter loop) ----------\n With real audio metering the visuals stop acting and start REACTING: the EQ renders the\n true spectrum (--eq-1..9), and [data-voice-dir] colors it by who is speaking (agent =\n brand, user = green). The orb (mj-realtime-agent-orb) reads the same attributes and the\n smoothed output envelope (--voice-out) itself. Without metering (driver attached no\n meters) the attribute stays 'false' and the turn-state keyframe animations stay in charge. */\n/* True-spectrum EQ: per-bar heights from the meter's bins. */\n.call-overlay[data-audio-live='true'] .hero__eq span {\n animation: none;\n transition: height 70ms linear, opacity 120ms linear;\n}\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(1) { height: calc(6px + var(--eq-1, 0) * 24px); opacity: calc(0.45 + var(--eq-1, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(2) { height: calc(6px + var(--eq-2, 0) * 24px); opacity: calc(0.45 + var(--eq-2, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(3) { height: calc(6px + var(--eq-3, 0) * 24px); opacity: calc(0.45 + var(--eq-3, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(4) { height: calc(6px + var(--eq-4, 0) * 24px); opacity: calc(0.45 + var(--eq-4, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(5) { height: calc(6px + var(--eq-5, 0) * 24px); opacity: calc(0.45 + var(--eq-5, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(6) { height: calc(6px + var(--eq-6, 0) * 24px); opacity: calc(0.45 + var(--eq-6, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(7) { height: calc(6px + var(--eq-7, 0) * 24px); opacity: calc(0.45 + var(--eq-7, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(8) { height: calc(6px + var(--eq-8, 0) * 24px); opacity: calc(0.45 + var(--eq-8, 0) * 0.55); }\n.call-overlay[data-audio-live='true'] .hero__eq span:nth-child(9) { height: calc(6px + var(--eq-9, 0) * 24px); opacity: calc(0.45 + var(--eq-9, 0) * 0.55); }\n.call-overlay[data-audio-live='true'][data-voice-dir='user'] .hero__eq span {\n background: var(--mj-status-success);\n}\n\n/* The quiet first reveal: show the conversation as text (raises disclosure to level 1). */\n.hero__reveal {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-top: 18px;\n padding: 6px 14px;\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: 11.5px;\n font-weight: 600;\n cursor: pointer;\n transition: color 140ms ease, border-color 140ms ease, background 140ms ease;\n}\n.hero__reveal:hover {\n color: var(--mj-text-secondary);\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n.hero__reveal i {\n font-size: 11px;\n}\n\n/* Ephemeral narration shown under the banner when no working card anchors it */\n.banner-live-note {\n display: flex;\n align-items: flex-start;\n gap: 7px;\n padding: 8px 22px 0;\n font-size: 12px;\n font-style: italic;\n color: var(--mj-text-muted);\n animation: overlay-note-in 220ms ease;\n}\n.banner-live-note i {\n font-size: 10px;\n margin-top: 3px;\n flex-shrink: 0;\n}\n@keyframes overlay-note-in {\n from { opacity: 0; transform: translateY(2px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* The call's notices under the banner (no microphone works; no avatar): mj-alert brings its own tint, border and text\n colours; this only places them. */\n.call-microphone-notice,\n.call-avatar-notice {\n flex-shrink: 0;\n margin: var(--mj-space-2) var(--mj-space-5) 0;\n}\n\n/* ---------- FOCUS-BOARD mode (whiteboard \"Focus board\" toggle) ----------\n The main call column collapses away entirely and the focused channel's surface fills\n the stage; a compact floating call pill keeps the live call reachable. */\n.call-overlay.board-focus .call-main {\n display: none;\n}\n\n/* ---------- the stage (every channel surface, in one layer) ----------\n mj-media-stage covers the overlay and places each surface itself. Above the panel it\n lays surfaces over, and above the call's controls, so its picture-in-picture boxes\n start clear of them (.call-controls); below the onboarding card (5), the menus of the\n dock and the chip (5) and the focus pill (60). */\n.call-stage {\n z-index: 1;\n}\n/* A surface's frame: fills the box the stage gives it. The surface component is created\n beside the pane host inside it, and sizes itself to it (height: 100%). */\n.stage-frame {\n position: relative;\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n/* The \"Move to\u2026\" menu on a surface that presents the agent, backed so it reads over video. Bottom right, in the\n tile's footer, which holds nothing there for the agent, so it never covers the tile's labels. */\n.stage-presenter-move {\n position: absolute;\n bottom: 4px;\n right: 6px;\n z-index: 1;\n border-radius: var(--mj-radius-full);\n background: color-mix(in srgb, var(--mj-bg-surface) 85%, transparent);\n}\n\n/* Floating call pill: orb + state + mute / show-thread / end (per the whiteboard mockup). */\n.board-focus-pill {\n position: absolute;\n left: 64px;\n top: 12px;\n z-index: 60;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 7px 9px 7px 12px;\n border-radius: var(--mj-radius-full, 999px);\n background: color-mix(in srgb, var(--mj-bg-surface-card) 92%, transparent);\n backdrop-filter: blur(8px);\n border: 1px solid var(--mj-border-strong);\n box-shadow: var(--mj-shadow-xl, 0 12px 32px rgba(0, 0, 0, 0.18));\n animation: overlay-note-in 220ms ease;\n}\n.board-focus-pill__orb {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n flex-shrink: 0;\n background: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.board-focus-pill__orb[data-state='speaking'],\n.board-focus-pill__orb[data-state='listening'] {\n animation: board-pill-pulse 1.6s ease-in-out infinite;\n}\n.board-focus-pill__orb[data-state='error'] {\n background: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 18%, transparent);\n}\n@keyframes board-pill-pulse {\n 0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent); }\n 50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--mj-brand-primary) 8%, transparent); }\n}\n.board-focus-pill__text {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.board-focus-pill__name {\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n color: var(--mj-text-primary);\n}\n.board-focus-pill__state {\n font-size: 10.5px;\n font-weight: 600;\n white-space: nowrap;\n color: var(--mj-brand-primary);\n}\n.board-focus-pill__btn {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n border: 1px solid var(--mj-border-strong);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 11px;\n display: grid;\n place-items: center;\n font-family: inherit;\n flex-shrink: 0;\n}\n.board-focus-pill__btn:hover {\n color: var(--mj-text-primary);\n}\n.board-focus-pill__btn--active {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n.board-focus-pill__btn--end {\n background: var(--mj-status-error);\n border-color: var(--mj-status-error);\n color: var(--mj-text-inverse, #fff);\n}\n\n/* ---------- Session review mode ---------- */\n/* Subtle archival tint so a glance says \"this is history, not a live call\". */\n.call-overlay--review {\n background:\n linear-gradient(180deg, color-mix(in srgb, var(--mj-text-muted) 4%, transparent), transparent 120px),\n var(--mj-bg-surface);\n}\n\n/* The review whiteboard pane body: the board component positions itself absolutely\n (inset: 0), so its template-based pane needs a filling, positioned frame. */\n.review-board-host {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n/* The review recording pane body: the evidence player fills its host (:host height:100%),\n so its template-based pane needs a filling, constrained frame. */\n.review-recording-host {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.review-recording-host mj-realtime-evidence-playback {\n flex: 1;\n min-height: 0;\n}\n\n/* ---------- flex layout (main column | resize handle | surface panel) ---------- */\n/* Token-styled resize handle: invisible until hover, brand-tinted while interacting.\n 7px hit target, col-resize cursor; removed (not rendered) while collapsed / focus. */\n.call-resizer {\n flex: 0 0 7px;\n width: 7px;\n cursor: col-resize;\n background: transparent;\n transition: background 140ms ease;\n}\n.call-resizer:hover,\n.call-resizer--active {\n background: color-mix(in srgb, var(--mj-brand-primary) 26%, transparent);\n}\n/* The surface panel: a plain fixed-width flex item (inline width set by the overlay;\n collapsed = the slim strip width). flex-shrink lets it yield to the call column's\n min-width on tight overlays; overflow hidden keeps the flex height chain intact so\n the panel's content scrolls internally. */\n.call-panel {\n flex: 0 1 auto;\n min-width: 0;\n display: flex;\n overflow: hidden;\n /* Disclosure-gated: the panel is CREATED when earned/peeked \u2014 its arrival slides in\n from the right so the reveal doubles as the progress cue. */\n animation: panel-in 420ms cubic-bezier(0.25, 0.8, 0.3, 1);\n}\n@keyframes panel-in {\n from { opacity: 0; transform: translateX(48px); }\n to { opacity: 1; transform: translateX(0); }\n}\n.call-panel > * {\n flex: 1;\n min-width: 0;\n min-height: 0;\n}\n"] }]
2584
2689
  }], () => [], { Hidden: [{
2585
2690
  type: Input
2586
2691
  }], AgentName: [{
@@ -2591,6 +2696,10 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
2591
2696
  type: Input
2592
2697
  }], AvatarNoticeLabels: [{
2593
2698
  type: Input
2699
+ }], ShowAvatarNotice: [{
2700
+ type: Input
2701
+ }], ShowPerceptionChip: [{
2702
+ type: Input
2594
2703
  }], Chrome: [{
2595
2704
  type: Input
2596
2705
  }], ConsoleBreakpointPx: [{
@@ -2601,6 +2710,8 @@ export class RealtimeSessionOverlayComponent extends BaseAngularComponent {
2601
2710
  type: Input
2602
2711
  }], AllowTextReveal: [{
2603
2712
  type: Input
2713
+ }], AllowTyping: [{
2714
+ type: Input
2604
2715
  }], ShowCaptionsControl: [{
2605
2716
  type: Input
2606
2717
  }], ShowDensityPicker: [{