@reticlehq/browser 2.13.1 → 3.1.0

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 (244) hide show
  1. package/dist/actions/actions-dom.d.ts +8 -20
  2. package/dist/actions/actions-dom.js +70 -69
  3. package/dist/actions/actions-press.d.ts +14 -0
  4. package/dist/actions/actions-press.js +123 -0
  5. package/dist/actions/actions.d.ts +1 -89
  6. package/dist/actions/actions.js +64 -365
  7. package/dist/actions/appeared-text.d.ts +0 -20
  8. package/dist/actions/appeared-text.js +6 -36
  9. package/dist/actions/danger-context.d.ts +3 -0
  10. package/dist/actions/danger-context.js +39 -0
  11. package/dist/actions/scroll.d.ts +8 -10
  12. package/dist/actions/scroll.js +28 -17
  13. package/dist/actions/synthetic/synthetic-input.d.ts +2 -0
  14. package/dist/actions/synthetic/synthetic-input.js +13 -0
  15. package/dist/actions/value-input.d.ts +0 -30
  16. package/dist/actions/value-input.js +0 -33
  17. package/dist/commands/commands.d.ts +0 -2
  18. package/dist/commands/commands.js +10 -70
  19. package/dist/connect-options.d.ts +2 -96
  20. package/dist/dom/a11y.d.ts +0 -29
  21. package/dist/dom/a11y.js +3 -90
  22. package/dist/dom/addressing/auto-anchor.d.ts +25 -0
  23. package/dist/dom/addressing/auto-anchor.js +41 -0
  24. package/dist/dom/addressing/refs.d.ts +14 -0
  25. package/dist/dom/addressing/refs.js +114 -0
  26. package/dist/dom/addressing/source.d.ts +9 -0
  27. package/dist/dom/addressing/source.js +29 -0
  28. package/dist/dom/chart.d.ts +0 -61
  29. package/dist/dom/chart.js +0 -60
  30. package/dist/dom/desktop-capture.d.ts +0 -30
  31. package/dist/dom/desktop-capture.js +1 -73
  32. package/dist/dom/dom-ignore.d.ts +0 -30
  33. package/dist/dom/dom-ignore.js +1 -48
  34. package/dist/dom/occlusion.d.ts +0 -7
  35. package/dist/dom/occlusion.js +31 -12
  36. package/dist/dom/paint-context.d.ts +6 -0
  37. package/dist/dom/paint-context.js +38 -0
  38. package/dist/dom/query.d.ts +0 -14
  39. package/dist/dom/query.js +50 -216
  40. package/dist/dom/realm.d.ts +0 -20
  41. package/dist/dom/realm.js +0 -28
  42. package/dist/dom/shadow-registry.d.ts +0 -33
  43. package/dist/dom/shadow-registry.js +2 -72
  44. package/dist/dom/snapshot.d.ts +2 -43
  45. package/dist/dom/snapshot.js +27 -152
  46. package/dist/dom/theme.d.ts +0 -37
  47. package/dist/dom/theme.js +2 -52
  48. package/dist/dom/virtualized.d.ts +0 -17
  49. package/dist/dom/virtualized.js +0 -27
  50. package/dist/edit-epoch.d.ts +1 -23
  51. package/dist/edit-epoch.js +1 -53
  52. package/dist/index.d.ts +4 -5
  53. package/dist/index.js +4 -28
  54. package/dist/observers/animation.d.ts +0 -1
  55. package/dist/observers/animation.js +1 -4
  56. package/dist/observers/blind-spots.d.ts +0 -26
  57. package/dist/observers/blind-spots.js +3 -62
  58. package/dist/observers/console.d.ts +1 -2
  59. package/dist/observers/console.js +41 -30
  60. package/dist/observers/context-open.d.ts +1 -11
  61. package/dist/observers/context-open.js +10 -14
  62. package/dist/observers/departure.d.ts +3 -0
  63. package/dist/observers/departure.js +52 -0
  64. package/dist/observers/dialogs.d.ts +2 -0
  65. package/dist/observers/dialogs.js +39 -0
  66. package/dist/observers/dom.js +28 -52
  67. package/dist/observers/download.d.ts +1 -2
  68. package/dist/observers/download.js +39 -56
  69. package/dist/observers/focus.d.ts +0 -6
  70. package/dist/observers/focus.js +0 -7
  71. package/dist/observers/frames.d.ts +0 -9
  72. package/dist/observers/frames.js +1 -28
  73. package/dist/observers/health.d.ts +0 -5
  74. package/dist/observers/health.js +2 -34
  75. package/dist/observers/install-all.d.ts +2 -0
  76. package/dist/observers/install-all.js +26 -27
  77. package/dist/observers/ipc.d.ts +0 -25
  78. package/dist/observers/ipc.js +0 -65
  79. package/dist/observers/navigation.d.ts +2 -0
  80. package/dist/observers/navigation.js +33 -0
  81. package/dist/observers/net-detail/network-body.d.ts +12 -0
  82. package/dist/observers/net-detail/network-body.js +71 -0
  83. package/dist/observers/net-detail/network-redact.d.ts +1 -0
  84. package/dist/observers/net-detail/network-redact.js +1 -0
  85. package/dist/observers/network-stream.d.ts +0 -21
  86. package/dist/observers/network-stream.js +3 -46
  87. package/dist/observers/network.d.ts +3 -27
  88. package/dist/observers/network.js +178 -295
  89. package/dist/observers/perf.d.ts +0 -10
  90. package/dist/observers/perf.js +0 -16
  91. package/dist/observers/route.d.ts +1 -2
  92. package/dist/observers/route.js +13 -19
  93. package/dist/observers/scroll.d.ts +0 -1
  94. package/dist/observers/scroll.js +2 -11
  95. package/dist/observers/sdk-failure.d.ts +1 -9
  96. package/dist/observers/sdk-failure.js +1 -30
  97. package/dist/observers/state.d.ts +1 -11
  98. package/dist/observers/state.js +13 -41
  99. package/dist/observers/storage.d.ts +0 -14
  100. package/dist/observers/storage.js +10 -34
  101. package/dist/observers/types.d.ts +0 -15
  102. package/dist/observers/types.js +0 -14
  103. package/dist/patching/capture-method.d.ts +0 -24
  104. package/dist/patching/capture-method.js +0 -26
  105. package/dist/presenter/chrome/layers.d.ts +2 -0
  106. package/dist/presenter/chrome/layers.js +2 -0
  107. package/dist/presenter/chrome/log-kinds.d.ts +12 -0
  108. package/dist/presenter/chrome/log-kinds.js +7 -0
  109. package/dist/presenter/{overlay.d.ts → chrome/overlay.d.ts} +0 -1
  110. package/dist/presenter/{overlay.js → chrome/overlay.js} +0 -1
  111. package/dist/presenter/chrome/presenter-brand.d.ts +3 -0
  112. package/dist/presenter/{presenter-brand.js → chrome/presenter-brand.js} +0 -21
  113. package/dist/presenter/chrome/presenter-effects.d.ts +4 -0
  114. package/dist/presenter/{presenter-effects.js → chrome/presenter-effects.js} +1 -10
  115. package/dist/presenter/chrome/presenter-hud-chrome.d.ts +7 -0
  116. package/dist/presenter/{presenter-hud-chrome.js → chrome/presenter-hud-chrome.js} +0 -10
  117. package/dist/presenter/chrome/presenter-log.d.ts +17 -0
  118. package/dist/presenter/{presenter-log.js → chrome/presenter-log.js} +5 -54
  119. package/dist/presenter/chrome/presenter-report-copy.d.ts +51 -0
  120. package/dist/presenter/chrome/presenter-report-copy.js +95 -0
  121. package/dist/presenter/chrome/presenter-safe-html.d.ts +2 -0
  122. package/dist/presenter/chrome/presenter-safe-html.js +16 -0
  123. package/dist/presenter/{presenter-tally.d.ts → chrome/presenter-tally.d.ts} +0 -5
  124. package/dist/presenter/{presenter-tally.js → chrome/presenter-tally.js} +1 -5
  125. package/dist/presenter/{presenter-verbs.js → chrome/presenter-verbs.js} +0 -7
  126. package/dist/presenter/{presenter-heroicons-data.d.ts → icons/presenter-heroicons-data.d.ts} +1 -8
  127. package/dist/presenter/{presenter-heroicons-data.js → icons/presenter-heroicons-data.js} +1 -8
  128. package/dist/presenter/{presenter-icons.d.ts → icons/presenter-icons.d.ts} +1 -6
  129. package/dist/presenter/{presenter-icons.js → icons/presenter-icons.js} +1 -6
  130. package/dist/presenter/presenter-account-styles.d.ts +1 -0
  131. package/dist/presenter/presenter-account-styles.js +99 -0
  132. package/dist/presenter/presenter-account.d.ts +40 -0
  133. package/dist/presenter/presenter-account.js +178 -0
  134. package/dist/presenter/presenter-config.d.ts +10 -107
  135. package/dist/presenter/presenter-config.js +5 -92
  136. package/dist/presenter/presenter-controls.d.ts +1 -35
  137. package/dist/presenter/presenter-controls.js +10 -133
  138. package/dist/presenter/presenter-dock-layout.d.ts +0 -3
  139. package/dist/presenter/presenter-dock-layout.js +1 -5
  140. package/dist/presenter/presenter-drag.d.ts +2 -42
  141. package/dist/presenter/presenter-drag.js +3 -76
  142. package/dist/presenter/presenter-glow.d.ts +0 -21
  143. package/dist/presenter/presenter-glow.js +2 -28
  144. package/dist/presenter/presenter-hud-position.d.ts +18 -0
  145. package/dist/presenter/presenter-hud-position.js +50 -0
  146. package/dist/presenter/presenter-report-styles.d.ts +0 -6
  147. package/dist/presenter/presenter-report-styles.js +22 -7
  148. package/dist/presenter/presenter-report.d.ts +5 -7
  149. package/dist/presenter/presenter-report.js +44 -95
  150. package/dist/presenter/presenter-run-state.d.ts +1 -8
  151. package/dist/presenter/presenter-run-state.js +1 -6
  152. package/dist/presenter/presenter-settings-styles.d.ts +0 -1
  153. package/dist/presenter/presenter-settings-styles.js +2 -2
  154. package/dist/presenter/presenter-settings.d.ts +5 -23
  155. package/dist/presenter/presenter-settings.js +21 -33
  156. package/dist/presenter/presenter-shell-styles.js +23 -20
  157. package/dist/presenter/presenter-shell.d.ts +6 -18
  158. package/dist/presenter/presenter-shell.js +26 -77
  159. package/dist/presenter/presenter-styles.d.ts +2 -10
  160. package/dist/presenter/presenter-styles.js +6 -12
  161. package/dist/presenter/presenter-workspace.d.ts +4 -4
  162. package/dist/presenter/presenter-workspace.js +30 -10
  163. package/dist/presenter/presenter.d.ts +3 -63
  164. package/dist/presenter/presenter.js +29 -132
  165. package/dist/presenter/tour/tour-view.d.ts +33 -0
  166. package/dist/presenter/tour/tour-view.js +188 -0
  167. package/dist/presenter/tour/tour.d.ts +25 -0
  168. package/dist/presenter/tour/tour.js +245 -0
  169. package/dist/recorder/recorder-styles.d.ts +0 -6
  170. package/dist/recorder/recorder-styles.js +0 -6
  171. package/dist/recorder/recorder.d.ts +0 -34
  172. package/dist/recorder/recorder.js +6 -49
  173. package/dist/registry/auto-testids.d.ts +0 -19
  174. package/dist/registry/auto-testids.js +1 -21
  175. package/dist/registry/capabilities.d.ts +0 -31
  176. package/dist/registry/capabilities.js +1 -46
  177. package/dist/registry/commit-and-signal.d.ts +0 -6
  178. package/dist/registry/commit-and-signal.js +1 -7
  179. package/dist/registry/declared-channels.d.ts +2 -0
  180. package/dist/registry/declared-channels.js +14 -0
  181. package/dist/registry/declared-platform.d.ts +4 -0
  182. package/dist/registry/declared-platform.js +34 -0
  183. package/dist/registry/domains.d.ts +0 -8
  184. package/dist/registry/domains.js +0 -7
  185. package/dist/registry/emitter.d.ts +0 -14
  186. package/dist/registry/emitter.js +1 -11
  187. package/dist/registry/store-adapters.d.ts +0 -186
  188. package/dist/registry/store-adapters.js +1 -164
  189. package/dist/registry/{adapters.d.ts → stores/adapters.d.ts} +0 -10
  190. package/dist/registry/{adapters.js → stores/adapters.js} +0 -10
  191. package/dist/registry/stores.d.ts +0 -33
  192. package/dist/registry/stores.js +1 -60
  193. package/dist/reticle-presenter-helpers.d.ts +0 -13
  194. package/dist/reticle-presenter-helpers.js +10 -20
  195. package/dist/reticle-singleton.d.ts +2 -0
  196. package/dist/reticle-singleton.js +3 -0
  197. package/dist/reticle.d.ts +1 -52
  198. package/dist/reticle.js +115 -180
  199. package/dist/review/annotator-styles.js +1 -8
  200. package/dist/review/annotator.d.ts +2 -13
  201. package/dist/review/annotator.js +2 -42
  202. package/dist/review/mark-anchor.d.ts +0 -11
  203. package/dist/review/mark-anchor.js +3 -11
  204. package/dist/security/serialization.d.ts +0 -20
  205. package/dist/security/serialization.js +1 -66
  206. package/dist/session-continuity.d.ts +0 -16
  207. package/dist/session-continuity.js +1 -20
  208. package/dist/timers/clock.d.ts +1 -14
  209. package/dist/timers/clock.js +59 -60
  210. package/dist/timers/console/native-console.js +5 -0
  211. package/dist/timers/native/native-timers.d.ts +11 -0
  212. package/dist/timers/native/native-timers.js +48 -0
  213. package/dist/transport/transport.d.ts +0 -51
  214. package/dist/transport/transport.js +5 -131
  215. package/dist/transport/unreachable-message.d.ts +0 -17
  216. package/dist/transport/unreachable-message.js +0 -17
  217. package/dist/util/captured-method.d.ts +0 -35
  218. package/dist/util/captured-method.js +0 -35
  219. package/package.json +5 -4
  220. package/dist/actions/synthetic-input.d.ts +0 -9
  221. package/dist/actions/synthetic-input.js +0 -40
  222. package/dist/dom/auto-anchor.d.ts +0 -65
  223. package/dist/dom/auto-anchor.js +0 -74
  224. package/dist/dom/refs.d.ts +0 -90
  225. package/dist/dom/refs.js +0 -245
  226. package/dist/dom/source.d.ts +0 -53
  227. package/dist/dom/source.js +0 -74
  228. package/dist/observers/network-body.d.ts +0 -35
  229. package/dist/observers/network-body.js +0 -168
  230. package/dist/observers/network-redact.d.ts +0 -20
  231. package/dist/observers/network-redact.js +0 -80
  232. package/dist/presenter/presenter-brand.d.ts +0 -22
  233. package/dist/presenter/presenter-effects.d.ts +0 -13
  234. package/dist/presenter/presenter-hud-chrome.d.ts +0 -17
  235. package/dist/presenter/presenter-log.d.ts +0 -64
  236. package/dist/presenter/presenter-report-copy.d.ts +0 -112
  237. package/dist/presenter/presenter-report-copy.js +0 -156
  238. package/dist/presenter/presenter-test-helpers.d.ts +0 -16
  239. package/dist/presenter/presenter-test-helpers.js +0 -41
  240. package/dist/timers/native-console.js +0 -9
  241. package/dist/timers/native-timers.d.ts +0 -36
  242. package/dist/timers/native-timers.js +0 -78
  243. /package/dist/presenter/{presenter-verbs.d.ts → chrome/presenter-verbs.d.ts} +0 -0
  244. /package/dist/timers/{native-console.d.ts → console/native-console.d.ts} +0 -0
@@ -1,11 +1,6 @@
1
1
  import { SessionState } from '@reticlehq/core';
2
- import { LOG_KIND, LOG_RESULT } from './presenter-log.js';
2
+ import { LOG_KIND, LOG_RESULT } from './chrome/presenter-log.js';
3
3
  import { getCapabilities } from '../registry/capabilities.js';
4
- /**
5
- * Compute the exported run-state from the controller's live fields: per-kind + pass/fail counts over
6
- * the activity log, the session duration, and the current capability surface. Extracted from
7
- * presenter.ts so the controller stays under the size cap; the counting is the same as before.
8
- */
9
4
  export function buildRunState(input) {
10
5
  const start = input.startMs ?? input.now;
11
6
  const counts = { reads: 0, acts: 0, narrations: 0, human: 0, passes: 0, fails: 0 };
@@ -1,2 +1 @@
1
- /** Compact settings card - dock-anchored above the HUD pill. */
2
1
  export declare const SETTINGS_CSS: string;
@@ -1,6 +1,5 @@
1
1
  import { SETTINGS_PANEL_ATTR, SETTINGS_ATTR, DOCK_ATTR, DOCK_ALIGN_ATTR, SETTINGS_PLACEMENT_ATTR, } from './presenter-config.js';
2
- import { HUD_DROP_SHADOW, HUD_SURFACE_CLASS, HUD_SURFACE_PAINT } from './presenter-hud-chrome.js';
3
- /** Compact settings card - dock-anchored above the HUD pill. */
2
+ import { HUD_DROP_SHADOW, HUD_SURFACE_CLASS, HUD_SURFACE_PAINT, } from './chrome/presenter-hud-chrome.js';
4
3
  export const SETTINGS_CSS = `
5
4
  [${'data-reticle-overlay'}][${SETTINGS_ATTR}="1"] [${'data-reticle-chat-panel'}]{
6
5
  display:none !important;visibility:hidden !important;pointer-events:none !important;}
@@ -150,4 +149,5 @@ export const SETTINGS_CSS = `
150
149
  display:none;pointer-events:none;}
151
150
  [${'data-reticle-overlay'}][data-reticle-hidden="1"] [${DOCK_ATTR}],
152
151
  [${'data-reticle-overlay'}][data-reticle-hidden="1"] [${SETTINGS_PANEL_ATTR}]{display:none !important;}
152
+
153
153
  `;
@@ -1,20 +1,13 @@
1
1
  import { SETTINGS_CSS } from './presenter-settings-styles.js';
2
+ import type { AccountState } from '@reticlehq/core';
3
+ import { type AccountDetails } from './presenter-account.js';
2
4
  export { SETTINGS_CSS };
3
- /** How much detail lands in copied/exported run state. */
4
5
  export declare const OutputDetail: {
5
6
  readonly MINIMAL: "minimal";
6
7
  readonly STANDARD: "standard";
7
8
  readonly VERBOSE: "verbose";
8
9
  };
9
10
  export type OutputDetail = (typeof OutputDetail)[keyof typeof OutputDetail];
10
- /**
11
- * Status themes: ONE choice, three colours.
12
- *
13
- * This was four separate pickers - a chrome accent plus a swatch row per state - which is 28
14
- * decisions to land on a set that works together. A theme is a combination we have already checked
15
- * reads as a progression (working -> waiting -> done) and against a dark app, so the choice is
16
- * "which mood", not "which four hex values".
17
- */
18
11
  export declare const StatusThemeId: {
19
12
  readonly SIGNAL: "signal";
20
13
  readonly TRAFFIC: "traffic";
@@ -23,7 +16,7 @@ export declare const StatusThemeId: {
23
16
  readonly EMBER: "ember";
24
17
  };
25
18
  export type StatusThemeId = (typeof StatusThemeId)[keyof typeof StatusThemeId];
26
- export interface StatusTheme {
19
+ interface StatusTheme {
27
20
  id: StatusThemeId;
28
21
  label: string;
29
22
  active: string;
@@ -34,13 +27,7 @@ export declare const STATUS_THEMES: readonly StatusTheme[];
34
27
  export declare function statusTheme(id: StatusThemeId): StatusTheme;
35
28
  export interface PresenterSettings {
36
29
  outputDetail: OutputDetail;
37
- /**
38
- * The colours the HUD signals session state with - the dot, the panel wash, the page glow, the
39
- * FAB halo and the annotation marks all read from whichever one is current. One choice, because
40
- * the three have to work as a set and against the user's own app.
41
- */
42
30
  statusThemeId: StatusThemeId;
43
- /** The page-edge glow. Off leaves every other signal (dot, panel, FAB) in place. */
44
31
  ambientGlow: boolean;
45
32
  reactComponents: boolean;
46
33
  hideUntilRestart: boolean;
@@ -53,21 +40,16 @@ export interface PresenterSettings {
53
40
  }
54
41
  export declare function getPresenterSettings(): PresenterSettings;
55
42
  export declare function loadPresenterSettings(): PresenterSettings;
56
- /** Settings panel markup - anchored above the gear in the toolbar. */
43
+ export declare const SETTINGS_ACCOUNT_ATTR = "data-reticle-settings-account";
44
+ export declare function paintSettingsAccount(root: HTMLElement, account: AccountState | undefined, dashboardUrl: string | undefined, details?: AccountDetails): void;
57
45
  export declare function settingsPanelHtml(): string;
58
46
  export interface SettingsHost {
59
47
  onHideUntilRestart?: () => void;
60
48
  onSettingsChange?: (settings: PresenterSettings) => void;
61
49
  onBeforeOpen?: () => void;
62
50
  }
63
- /** Apply persisted settings onto the overlay + dock. */
64
51
  export declare function applyPresenterSettings(root: HTMLElement, settings: PresenterSettings): void;
65
- /**
66
- * Toggle the full-page blocker. Only active while annotate mode is live AND the user opted in -
67
- * never on a collapsed FAB, so real hover/click on the host app still works.
68
- */
69
52
  export declare function syncPageBlocker(root: HTMLElement, settings: PresenterSettings, annotateLive: boolean): void;
70
- /** Blocker node - sits under Reticle UI, above the host page. */
71
53
  export declare function blockerHtml(): string;
72
54
  export declare class PresenterSettingsPanel {
73
55
  #private;
@@ -1,24 +1,16 @@
1
1
  import { SETTINGS_ATTR, SETTINGS_BTN_ATTR, SETTINGS_PANEL_ATTR, SETTINGS_CLOSE_ATTR, SETTING_KEY_ATTR, SETTINGS_STORAGE_KEY, AMBIENT_GLOW_ATTR, BLOCK_ATTR, HIDDEN_UNTIL_RESTART_ATTR, LOG_TIMESTAMPS_ATTR, REDUCE_MOTION_ATTR, DOCK_ATTR, MCP_DOCS_URL, } from './presenter-config.js';
2
- import { PresenterIcon, PRESENTER_ICON_SIZE, setHiIcon, hiIconHtml } from './presenter-icons.js';
3
- import { HUD_SURFACE_CLASS } from './presenter-hud-chrome.js';
2
+ import { PresenterIcon, PRESENTER_ICON_SIZE, setHiIcon, hiIconHtml, } from './icons/presenter-icons.js';
3
+ import { HUD_SURFACE_CLASS } from './chrome/presenter-hud-chrome.js';
4
4
  import { resetHudDockPosition } from './presenter-drag.js';
5
5
  import { findDock, scheduleSyncDockLayout } from './presenter-dock-layout.js';
6
6
  import { SETTINGS_CSS } from './presenter-settings-styles.js';
7
+ import { accountControlHtml } from './presenter-account.js';
7
8
  export { SETTINGS_CSS };
8
- /** How much detail lands in copied/exported run state. */
9
9
  export const OutputDetail = {
10
10
  MINIMAL: 'minimal',
11
11
  STANDARD: 'standard',
12
12
  VERBOSE: 'verbose',
13
13
  };
14
- /**
15
- * Status themes: ONE choice, three colours.
16
- *
17
- * This was four separate pickers - a chrome accent plus a swatch row per state - which is 28
18
- * decisions to land on a set that works together. A theme is a combination we have already checked
19
- * reads as a progression (working -> waiting -> done) and against a dark app, so the choice is
20
- * "which mood", not "which four hex values".
21
- */
22
14
  export const StatusThemeId = {
23
15
  SIGNAL: 'signal',
24
16
  TRAFFIC: 'traffic',
@@ -70,14 +62,6 @@ const DEFAULT_SETTINGS = {
70
62
  blockPageInteractions: true,
71
63
  showTally: false,
72
64
  showTimestamps: true,
73
- // ON by default: the chat IS the HUD's content, and shipping it off meant the default experience
74
- // was a bare toolbar until somebody found the toggle. `expand()` has always opened the chat for
75
- // the same reason; this is the other half — session start, with no click at all.
76
- //
77
- // Safe to default because `openChat()` expands a collapsed HUD, and session start is the one
78
- // moment where that is what you want. A user who prefers the bare toolbar turns this off and it
79
- // stays off: a stored `false` is honoured over the default, which is pinned in
80
- // presenter-chat-default.test.ts so the product cannot change somebody's answer behind their back.
81
65
  autoOpenChat: true,
82
66
  reduceMotion: false,
83
67
  };
@@ -101,10 +85,6 @@ export function loadPresenterSettings() {
101
85
  ? o['outputDetail']
102
86
  : DEFAULT_SETTINGS.outputDetail,
103
87
  reactComponents: true === o['reactComponents'],
104
- // NOT read back from storage. "Until restart" has to mean until restart: persisted, it
105
- // survived the reload that was supposed to undo it, and the only way back was clearing
106
- // localStorage by hand - the HUD was simply gone, including the settings panel that turned
107
- // it off. It is a this-page-only switch, so it lives only in memory.
108
88
  hideUntilRestart: false,
109
89
  statusThemeId: isStatusThemeId(o['statusThemeId'])
110
90
  ? o['statusThemeId']
@@ -140,7 +120,6 @@ function persistSettings(next) {
140
120
  localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(next));
141
121
  }
142
122
  catch {
143
- /* quota / private mode - settings still apply for this page */
144
123
  }
145
124
  }
146
125
  function patchSettings(patch) {
@@ -168,7 +147,18 @@ function settingsCheckRow(key, label, checked) {
168
147
  <span class="reticle-settings-check-label">${label}</span>
169
148
  </label>`;
170
149
  }
171
- /** Settings panel markup - anchored above the gear in the toolbar. */
150
+ export const SETTINGS_ACCOUNT_ATTR = 'data-reticle-settings-account';
151
+ const SETTINGS_ACCOUNT_ROW_ATTR = 'data-reticle-settings-account-row';
152
+ const ACCOUNT_HELP = 'Whether this machine is signed in to a Reticle workspace. Signing in happens in your terminal.';
153
+ export function paintSettingsAccount(root, account, dashboardUrl, details = {}) {
154
+ const row = root.querySelector(`[${SETTINGS_ACCOUNT_ROW_ATTR}]`);
155
+ const slot = root.querySelector(`[${SETTINGS_ACCOUNT_ATTR}]`);
156
+ if (!(row instanceof HTMLElement) || !(slot instanceof HTMLElement))
157
+ return;
158
+ const html = accountControlHtml(account, { ...details, dashboardUrl }, true);
159
+ row.hidden = 0 === html.length;
160
+ slot.innerHTML = html;
161
+ }
172
162
  export function settingsPanelHtml() {
173
163
  const close = hiIconHtml(PresenterIcon.REMOVE, PRESENTER_ICON_SIZE.MIN);
174
164
  const caret = hiIconHtml(PresenterIcon.CARET_RIGHT, PRESENTER_ICON_SIZE.HELP);
@@ -180,7 +170,7 @@ export function settingsPanelHtml() {
180
170
  const autoChatHelp = 'On by default. Opens the agent chat by itself when a session starts and when you expand the HUD. Off leaves the toolbar bare until you ask for the chat.';
181
171
  const motionHelp = 'Reduce HUD animations for accessibility';
182
172
  const glowHelp = 'Glow the page edges in the status colour while a session is live. Off keeps the HUD signals and leaves your app alone.';
183
- return `<div ${SETTINGS_PANEL_ATTR} class="reticle-settings ${HUD_SURFACE_CLASS}" role="dialog" aria-label="Reticle settings" aria-hidden="true">
173
+ return `<div ${SETTINGS_PANEL_ATTR} class="reticle-settings ${HUD_SURFACE_CLASS}" role="region" aria-label="Reticle settings" aria-hidden="true">
184
174
  <div class="reticle-settings-inner">
185
175
  <div class="reticle-settings-head">
186
176
  <span class="reticle-settings-title">Settings</span>
@@ -202,6 +192,11 @@ export function settingsPanelHtml() {
202
192
  ${settingsCheckRow('clearOnCopy', 'Clear on copy/send', false)}
203
193
  ${settingsToggleRow('hideUntilRestart', 'Hide Until Restart', hideHelp)}
204
194
  ${settingsToggleRow('reduceMotion', 'Reduce motion', motionHelp)}
195
+ <div class="reticle-settings-section">Account</div>
196
+ <div class="reticle-settings-row" ${SETTINGS_ACCOUNT_ROW_ATTR} hidden>
197
+ ${settingsLabel('Workspace', ACCOUNT_HELP)}
198
+ <span ${SETTINGS_ACCOUNT_ATTR}></span>
199
+ </div>
205
200
  <div class="reticle-settings-section">Status theme</div>
206
201
  ${settingsToggleRow('ambientGlow', 'Page glow', glowHelp)}
207
202
  <div class="reticle-settings-themes" data-reticle-settings-themes></div>
@@ -213,7 +208,6 @@ export function settingsPanelHtml() {
213
208
  </div>
214
209
  </div>`;
215
210
  }
216
- /** Apply persisted settings onto the overlay + dock. */
217
211
  export function applyPresenterSettings(root, settings) {
218
212
  const theme = statusTheme(settings.statusThemeId);
219
213
  root.style.setProperty('--reticle-mark-accent', theme.active);
@@ -235,14 +229,9 @@ export function applyPresenterSettings(root, settings) {
235
229
  tally.setAttribute('hidden', '');
236
230
  }
237
231
  }
238
- /**
239
- * Toggle the full-page blocker. Only active while annotate mode is live AND the user opted in -
240
- * never on a collapsed FAB, so real hover/click on the host app still works.
241
- */
242
232
  export function syncPageBlocker(root, settings, annotateLive) {
243
233
  root.setAttribute(BLOCK_ATTR, settings.blockPageInteractions && annotateLive ? '1' : '0');
244
234
  }
245
- /** Blocker node - sits under Reticle UI, above the host page. */
246
235
  export function blockerHtml() {
247
236
  return '<div data-reticle-blocker aria-hidden="true"></div>';
248
237
  }
@@ -470,7 +459,6 @@ export class PresenterSettingsPanel {
470
459
  el.textContent = on ? '✓' : '';
471
460
  }
472
461
  }
473
- /** One row of themes: each chip shows the whole set - active, idle, ended - in order. */
474
462
  #buildThemes() {
475
463
  const host = this.#panel?.querySelector('[data-reticle-settings-themes]');
476
464
  if (null === host || undefined === host)
@@ -1,10 +1,7 @@
1
- /**
2
- * Floating HUD shell styles - FAB, morphing toolbar, and agent chat panel.
3
- * Split from presenter-styles.ts so the controller stays under the size cap.
4
- */
5
- import { LOG_TIME_ATTR } from './presenter-log.js';
1
+ import { LOG_TIME_ATTR } from './chrome/presenter-log.js';
2
+ import { Z_HUD_TOOLTIP } from './presenter-config.js';
6
3
  import { CHAT_ATTR, CHAT_PILL_ATTR, CHAT_PLACEMENT_ATTR, DOCK_ALIGN_ATTR, DOCK_ATTR, LOG_TIMESTAMPS_ATTR, MIN_ATTR, REDUCE_MOTION_ATTR, LIVENESS_ATTR, } from './presenter-config.js';
7
- import { HUD_DROP_SHADOW, HUD_SURFACE_FILL } from './presenter-hud-chrome.js';
4
+ import { HUD_DROP_SHADOW, HUD_SURFACE_FILL } from './chrome/presenter-hud-chrome.js';
8
5
  const OVERLAY = 'data-reticle-overlay';
9
6
  const HUD = 'data-reticle-hud';
10
7
  const CHAT_PANEL = 'data-reticle-chat-panel';
@@ -89,8 +86,8 @@ export const SHELL_CSS = `
89
86
  /**
90
87
  * Minimising the chat leaves a CAPSULE, not a hole: the same glass, the same state dot, the last
91
88
  * thing the agent did - sitting directly above the toolbar capsule and reopening the panel when
92
- * clicked. Minimise used to leave the toolbar alone above an empty gap, so a minimised session
93
- * looked identical to no session at all.
89
+ * clicked. Leaving the toolbar alone above an empty gap would make a minimised session look
90
+ * identical to no session at all.
94
91
  */
95
92
  [${CHAT_PILL_ATTR}]{
96
93
  display:none;position:absolute;right:0;left:auto;bottom:calc(100% + 8px);z-index:5;
@@ -118,6 +115,13 @@ export const SHELL_CSS = `
118
115
  flex:none;display:flex;align-items:center;gap:8px;padding:11px 44px 9px 14px;
119
116
  border-bottom:1px solid rgba(255,255,255,.06);}
120
117
  [${CHAT_PANEL}] .reticle-chat-brand{display:inline-flex;align-items:center;gap:7px;color:var(--reticle-fg);}
118
+ /* The account capsule lives in the header, not the toolbar. The toolbar row is already 13px over its
119
+ own width, so a 20px avatar there pushed the close button outside the panel. The header has the
120
+ space, is visible under exactly the same condition, and is where an account avatar belongs anyway.
121
+ margin-left:auto right-aligns it; the head reserves 44px of right padding for the caret above it,
122
+ so the two never overlap. The :empty rule keeps the gap closed when no account state was sent. */
123
+ [${CHAT_PANEL}] .reticle-head-account{margin-left:auto;display:inline-flex;align-items:center;}
124
+ [${CHAT_PANEL}] .reticle-head-account:empty{display:none;}
121
125
  [${CHAT_PANEL}] .reticle-chat-brand .reticle-mark{height:14px;width:auto;}
122
126
  [${CHAT_PANEL}] .reticle-chat-brandname{font-size:12.5px;font-weight:600;letter-spacing:.01em;}
123
127
  /* No state word here: the activity strip immediately below already says "idle · 21s", and the
@@ -237,6 +241,7 @@ export const SHELL_CSS = `
237
241
  padding:2px;border-radius:999px;background:rgba(0,0,0,.2);}
238
242
  [${HUD}] .reticle-toolbar-chrome{display:inline-flex;align-items:center;gap:2px;flex:none;}
239
243
  [${HUD}] .reticle-tb-sep{width:1px;height:14px;background:rgba(255,255,255,.12);margin:0 4px;flex:none;align-self:center;}
244
+
240
245
  [${HUD}] .reticle-tb-wrap{position:relative;display:flex;align-items:center;justify-content:center;overflow:visible;}
241
246
  [${HUD}] .reticle-tb-btn{
242
247
  flex:none;display:inline-flex;align-items:center;justify-content:center;
@@ -262,10 +267,9 @@ export const SHELL_CSS = `
262
267
  [${HUD}] .reticle-hi-toggle .reticle-hi-icon--solid svg{
263
268
  transform:scale(1.12);transform-origin:center;}
264
269
  /*
265
- * Active toggles keep the OUTLINE icon. They used to swap to the solid heroicon, which is a filled
266
- * glyph next to 1.5px strokes everywhere else, so the pressed button read as a heavier typeface
267
- * rather than as a state. The state is already carried by accent colour and a background above,
268
- * which is enough and does not change the icon's weight.
270
+ * Active toggles keep the OUTLINE icon. The solid heroicon is a filled glyph next to 1.5px strokes
271
+ * everywhere else, so a pressed button reads as a heavier typeface rather than as a state. Accent
272
+ * colour and the background above already carry the state without changing the icon's weight.
269
273
  */
270
274
  [${HUD}] .reticle-tb-btn--toggle[data-active="1"] .reticle-hi-icon--outline{opacity:1;}
271
275
  [${HUD}] .reticle-tb-btn--toggle .reticle-hi-icon--solid{opacity:0;}
@@ -277,10 +281,10 @@ export const SHELL_CSS = `
277
281
  /**
278
282
  * The toolbar is a FIXED number of slots.
279
283
  *
280
- * Copy and Export appear when a session ends, and they used to be added to a bar that was already
281
- * full - eleven icons in a pill sized for nine, so the last one rendered outside the rounded box.
282
- * They take the two slots that Pause and End vacate: neither can do anything to a session that has
283
- * already ended, so the bar swaps two dead controls for two live ones and never changes width.
284
+ * Copy and Export appear when a session ends, and the bar is already full - eleven icons in a pill
285
+ * sized for nine renders the last one outside the rounded box. They take the two slots Pause and End
286
+ * vacate: neither can do anything to an ended session, so the bar swaps two dead controls for two
287
+ * live ones and never changes width.
284
288
  */
285
289
  [${HUD}] .reticle-tb-btn--export{display:none;}
286
290
  [${OVERLAY}][${STATE}="ended"] [${HUD}] .reticle-tb-btn--export{display:inline-flex;}
@@ -289,7 +293,7 @@ export const SHELL_CSS = `
289
293
  [${HUD}] .reticle-tb-tip{
290
294
  position:absolute;bottom:calc(100% + 14px);left:50%;transform:translateX(-50%) scale(.95);
291
295
  padding:6px 10px;background:#1a1a1a;color:rgba(255,255,255,.9);font-size:12px;font-weight:500;
292
- border-radius:8px;white-space:nowrap;opacity:0;visibility:hidden;pointer-events:none;z-index:3;
296
+ border-radius:8px;white-space:nowrap;opacity:0;visibility:hidden;pointer-events:none;z-index:${String(Z_HUD_TOOLTIP)};
293
297
  box-shadow:0 2px 8px rgba(0,0,0,.3);transition:opacity .135s ease,transform .135s ease,visibility .135s;}
294
298
  [${HUD}] .reticle-tb-tip::after{
295
299
  content:"";position:absolute;top:calc(100% - 4px);left:50%;transform:translateX(-50%) rotate(45deg);
@@ -310,9 +314,8 @@ export const SHELL_CSS = `
310
314
  * The mode, ON the status row rather than under it.
311
315
  *
312
316
  * The action text beside it is flex:1, so this claims the right edge of the row and takes its space
313
- * from the elided action text. Nothing above or below moves: the panel used to grow and shrink by
314
- * the height of this pill on every single tool call, which is what made one status line look like a
315
- * second UI appearing and leaving.
317
+ * from the elided action text. Nothing above or below moves: growing and shrinking by the height of
318
+ * this pill on every tool call makes one status line look like a second UI appearing and leaving.
316
319
  */
317
320
  [${DOCK_ATTR}] .reticle-chip{display:none;flex:none;align-items:center;gap:4px;font-size:8px;font-weight:600;letter-spacing:.06em;
318
321
  height:16px;padding:0 7px;line-height:1;border-radius:999px;text-transform:uppercase;
@@ -1,28 +1,23 @@
1
1
  import { PresenterReport } from './presenter-report.js';
2
+ import type { AccountState } from '@reticlehq/core';
3
+ import { type AccountDetails } from './presenter-account.js';
2
4
  import { type SettingsHost } from './presenter-settings.js';
3
- export interface HudShellCallbacks {
5
+ interface HudShellCallbacks {
4
6
  onChatOpen?: () => void;
5
7
  onChatClose?: () => void;
6
8
  onExpand?: () => void;
7
- /** The user pressed the annotate toggle. `on` is the state they asked for. */
8
9
  onAnnotateToggle?: (on: boolean) => void;
9
10
  onCollapse?: () => void;
11
+ onSyncNow?: () => void;
10
12
  settings?: SettingsHost;
11
13
  }
12
- /**
13
- * Morphing HUD shell: circular FAB ↔ icon toolbar, plus the agent chat panel above.
14
- * Expand enters annotation mode; the page stays clickable except for captured annotate clicks.
15
- */
16
14
  export declare class HudShell {
17
15
  #private;
16
+ paintAccount(account: AccountState | undefined, dashboardUrl: string | undefined, details?: AccountDetails): void;
18
17
  constructor(callbacks?: HudShellCallbacks);
19
- /** Markup for the dock wrapper (chat panel + morphing HUD shell). */
20
18
  static dockHtml(actStripHtml: string, bannerHtml: string, logAttr: string, flowsHtml: string, footHtml: string): string;
21
- /** The impact report, so the presenter can feed it and the chat can open it. */
22
19
  get report(): PresenterReport;
23
- /** Does the user currently want to annotate? */
24
20
  isAnnotateOn(): boolean;
25
- /** Set the toggle and reflect it on the button, without firing the callback. */
26
21
  setAnnotateOn(on: boolean): void;
27
22
  mount(root: HTMLElement): void;
28
23
  teardown(): void;
@@ -33,14 +28,7 @@ export declare class HudShell {
33
28
  openChat(): void;
34
29
  closeChat(): void;
35
30
  toggleChat(): void;
36
- /**
37
- * The chat, asked for by a PERSON - so it takes the slot from the report.
38
- *
39
- * `openChat` is also called by `expand`, which the agent triggers at session start; routing that
40
- * through here closed the impact report every time the agent touched the app, which is precisely
41
- * when you are reading it.
42
- */
43
31
  showChat(): void;
44
- /** Pulse the FAB when new activity arrives while collapsed. */
45
32
  pulseFab(active: boolean): void;
46
33
  }
34
+ export {};
@@ -1,27 +1,24 @@
1
1
  import { PresenterReport, reportPanelHtml } from './presenter-report.js';
2
+ import { paintToolbarAccount, TOOLBAR_ACCOUNT_ATTR } from './presenter-workspace.js';
3
+ import { mountAccountControl } from './presenter-account.js';
4
+ import { paintSettingsAccount } from './presenter-settings.js';
2
5
  import { CHAT_MIN_ATTR, CHAT_PILL_ATTR, REPORT_ATTR, REPORT_BTN_ATTR, ANNOTATE_BTN_ATTR, CHAT_ATTR, CHAT_TOGGLE_ATTR, CHAT_PANEL_ATTR, DOCK_ATTR, FAB_ATTR, MIN_ATTR, SETTINGS_ATTR, SETTINGS_BTN_ATTR, } from './presenter-config.js';
3
- import { BRAND_NAME, FAB_TOGGLE_HTML, MARK_SVG } from './presenter-brand.js';
4
- import { settleLogAtLatest } from './presenter-log.js';
6
+ import { BRAND_NAME, FAB_TOGGLE_HTML, MARK_SVG } from './chrome/presenter-brand.js';
7
+ import { settleLogAtLatest } from './chrome/presenter-log.js';
5
8
  import { installHudDragHandles, installHudPositionGuards } from './presenter-drag.js';
6
9
  import { scheduleSyncDockLayout } from './presenter-dock-layout.js';
7
- import { hiIconHtml, hiToggleIconHtml, PRESENTER_ICON_SIZE, PresenterIcon, } from './presenter-icons.js';
8
- import { HUD_SURFACE_CLASS, HUD_LOG_WELL_CLASS } from './presenter-hud-chrome.js';
10
+ import { hiIconHtml, hiToggleIconHtml, PRESENTER_ICON_SIZE, PresenterIcon, } from './icons/presenter-icons.js';
11
+ import { HUD_SURFACE_CLASS, HUD_LOG_WELL_CLASS } from './chrome/presenter-hud-chrome.js';
9
12
  import { CONTROLS_TOOLBAR_HTML } from './presenter-controls.js';
10
13
  import { PresenterSettingsPanel, settingsPanelHtml, } from './presenter-settings.js';
11
14
  const DRAG_HANDLE_CLASS = 'reticle-toolbar-drag';
12
15
  const TRANSITION_LOCK_MS = 120;
13
16
  const ANNOTATE_LABEL = 'Annotate';
14
17
  const CHAT_MIN_LABEL = 'Minimise chat';
15
- /** The minimised chat capsule's label - it reopens the panel. */
16
18
  const CHAT_PILL_LABEL = 'Open agent chat';
17
- /** The toolbar entry to the impact report. */
18
19
  const REPORT_LABEL = 'Impact';
19
20
  const SETTINGS_LABEL = 'Settings';
20
21
  const EXIT_LABEL = 'Exit';
21
- /**
22
- * Morphing HUD shell: circular FAB ↔ icon toolbar, plus the agent chat panel above.
23
- * Expand enters annotation mode; the page stays clickable except for captured annotate clicks.
24
- */
25
22
  export class HudShell {
26
23
  #root;
27
24
  #dock;
@@ -35,60 +32,47 @@ export class HudShell {
35
32
  #transitionLock = false;
36
33
  #suppressFabClick = false;
37
34
  #annotateBtn;
38
- /**
39
- * Whether the USER wants to annotate. Distinct from whether annotation is currently possible,
40
- * which also needs a live session and an expanded HUD — this is the half the user controls, and
41
- * conflating the two is why there was no way to keep the HUD open without annotating.
42
- *
43
- * OFF until asked for. It began as `true` to preserve the old behaviour where expanding the HUD
44
- * silently entered annotate mode, and that is exactly what made the toolbar icon look permanently
45
- * lit: the toolbar is only visible while expanded, so an intent that defaults to on is on every
46
- * time you can see it. Annotate mode also captures clicks, so defaulting it on means a click lands
47
- * as a mark before anyone asked for one. It is a mode now, and modes are entered deliberately.
48
- */
49
35
  #annotateOn = false;
50
36
  #toggleSync;
51
- /**
52
- * One signal for every listener this shell registers, so teardown cannot drift from mount.
53
- *
54
- * The click handlers below are anonymous closures over `this`: there is no reference to hand to
55
- * `removeEventListener`, so before this they were never removed at all. Mounting twice onto the
56
- * same root therefore stacked a second set, and every handler kept the shell reachable for as
57
- * long as its element lived.
58
- */
59
37
  #listeners;
60
38
  #report = new PresenterReport({
61
39
  onBeforeOpen: () => {
62
- // One panel at a time in the slot above the toolbar. The chat, the settings and the report
63
- // all anchor there, so opening one over another stacks two glass cards and reads as a bug.
64
40
  this.#settings.close();
65
41
  this.closeChat();
66
42
  },
43
+ onSyncNow: () => this.#callbacks.onSyncNow?.(),
67
44
  });
68
45
  #callbacks;
46
+ #pushedAccount;
47
+ #accountTeardown;
48
+ paintAccount(account, dashboardUrl, details = {}) {
49
+ this.#pushedAccount = { account, dashboardUrl, details };
50
+ if (this.#root === undefined)
51
+ return;
52
+ paintToolbarAccount(this.#root, account, dashboardUrl, details);
53
+ paintSettingsAccount(this.#root, account, dashboardUrl, details);
54
+ }
69
55
  constructor(callbacks = {}) {
70
56
  this.#callbacks = callbacks;
71
57
  this.#settings = new PresenterSettingsPanel({
72
58
  ...callbacks.settings,
73
59
  onBeforeOpen: () => {
74
- // Settings takes the slot from BOTH neighbours. Closing only the chat left the report
75
- // sitting behind the settings card - two glass panels stacked in one anchor.
76
60
  this.closeChat();
77
61
  this.#report.close();
78
62
  callbacks.settings?.onBeforeOpen?.();
79
63
  },
80
64
  });
81
65
  }
82
- /** Markup for the dock wrapper (chat panel + morphing HUD shell). */
83
66
  static dockHtml(actStripHtml, bannerHtml, logAttr, flowsHtml, footHtml) {
84
67
  const annotate = hiToggleIconHtml(PresenterIcon.ANNOTATE, PRESENTER_ICON_SIZE.TOOLBAR);
85
68
  const chart = hiToggleIconHtml(PresenterIcon.CHART, PRESENTER_ICON_SIZE.TOOLBAR);
86
69
  const gear = hiToggleIconHtml(PresenterIcon.GEAR, PRESENTER_ICON_SIZE.TOOLBAR);
87
70
  const exit = hiIconHtml(PresenterIcon.REMOVE, PRESENTER_ICON_SIZE.TOOLBAR);
88
71
  return `<div ${DOCK_ATTR}>
89
- <div ${CHAT_PANEL_ATTR} class="reticle-chat-panel ${HUD_SURFACE_CLASS}" role="dialog" aria-label="Reticle agent chat" aria-hidden="true">
72
+ <div ${CHAT_PANEL_ATTR} class="reticle-chat-panel ${HUD_SURFACE_CLASS}" role="region" aria-label="Reticle session" aria-hidden="true">
90
73
  <div class="reticle-chat-head">
91
74
  <span class="reticle-chat-brand">${MARK_SVG}<span class="reticle-chat-brandname">${BRAND_NAME}</span></span>
75
+ <span ${TOOLBAR_ACCOUNT_ATTR} class="reticle-head-account"></span>
92
76
  </div>
93
77
  <button type="button" ${CHAT_MIN_ATTR} class="reticle-chat-min" title="${CHAT_MIN_LABEL}" aria-label="${CHAT_MIN_LABEL}">${hiIconHtml(PresenterIcon.CARET_DOWN, PRESENTER_ICON_SIZE.TOOLBAR)}</button>
94
78
  ${actStripHtml}
@@ -134,11 +118,9 @@ export class HudShell {
134
118
  </div>
135
119
  </div>`;
136
120
  }
137
- /** The impact report, so the presenter can feed it and the chat can open it. */
138
121
  get report() {
139
122
  return this.#report;
140
123
  }
141
- /** Light exactly the toolbar buttons whose panels are open. */
142
124
  #syncToolbarToggles() {
143
125
  const root = this.#root;
144
126
  if (root === undefined)
@@ -152,11 +134,9 @@ export class HudShell {
152
134
  lit(SETTINGS_BTN_ATTR, '1' === root.getAttribute(SETTINGS_ATTR));
153
135
  lit(REPORT_BTN_ATTR, '1' === root.getAttribute(REPORT_ATTR));
154
136
  }
155
- /** Does the user currently want to annotate? */
156
137
  isAnnotateOn() {
157
138
  return this.#annotateOn;
158
139
  }
159
- /** Set the toggle and reflect it on the button, without firing the callback. */
160
140
  setAnnotateOn(on) {
161
141
  this.#annotateOn = on;
162
142
  this.#annotateBtn?.setAttribute('aria-pressed', on ? 'true' : 'false');
@@ -200,10 +180,6 @@ export class HudShell {
200
180
  root.removeAttribute(CHAT_ATTR);
201
181
  this.#settings.mount(root);
202
182
  this.#report.mount(root);
203
- // The toolbar's lit state FOLLOWS the panels, rather than being set by whoever was clicked.
204
- // Set at click time, a button stayed lit after its panel was closed by the panel that replaced
205
- // it - two icons active, one panel open. The observer is the only place that can be right for
206
- // every path: the toolbar, Escape, click-outside, and one panel closing another.
207
183
  this.#toggleSync = new MutationObserver(() => this.#syncToolbarToggles());
208
184
  this.#toggleSync.observe(root, {
209
185
  attributes: true,
@@ -247,15 +223,17 @@ export class HudShell {
247
223
  }
248
224
  document.addEventListener('pointerdown', this.#onDocPointerDown, { signal });
249
225
  document.addEventListener('keydown', this.#onKeyDown, { signal });
226
+ this.#accountTeardown = mountAccountControl(root);
227
+ if (this.#pushedAccount !== undefined) {
228
+ const pushed = this.#pushedAccount;
229
+ this.paintAccount(pushed.account, pushed.dashboardUrl, pushed.details);
230
+ }
250
231
  }
251
232
  teardown() {
252
- // One call for all nine registrations. It cannot fall out of step with mount() the way a list
253
- // of removeEventListener calls can, which is the whole point.
233
+ this.#accountTeardown?.();
234
+ this.#accountTeardown = undefined;
254
235
  this.#listeners?.abort();
255
236
  this.#listeners = undefined;
256
- // NOT covered by the signal: a MutationObserver takes no `signal` option. This disconnect was
257
- // missing entirely, so the observer kept `root` — and through it the shell — alive after
258
- // teardown, and a re-mount left the previous one still firing.
259
237
  this.#toggleSync?.disconnect();
260
238
  this.#toggleSync = undefined;
261
239
  this.#dragTeardown?.();
@@ -286,12 +264,6 @@ export class HudShell {
286
264
  if (this.#fab !== undefined)
287
265
  this.#fab.setAttribute('aria-expanded', 'true');
288
266
  this.#callbacks.onExpand?.();
289
- // The chat IS the HUD's content: expanding to a toolbar with nothing above it made the agent's
290
- // log something you had to know to go looking for. Unconditional on purpose — the way to a bare
291
- // toolbar is the chat's own minimise button, not a preference. `Auto-open chat` is a different
292
- // question (should it appear with no click at all, at session start) and stays separate, because
293
- // wiring expand to it made session start expand the HUD and the FAB never appeared.
294
- // `openChat` re-enters `expand` only when collapsed, and MIN_ATTR is already cleared above.
295
267
  this.openChat();
296
268
  if (this.#dock !== undefined)
297
269
  scheduleSyncDockLayout(this.#dock, this.#root);
@@ -316,8 +288,6 @@ export class HudShell {
316
288
  if (this.isChatOpen())
317
289
  return;
318
290
  this.#root.setAttribute(CHAT_ATTR, '1');
319
- // The panel had no layout while it was closed, so its feed could not follow the newest row.
320
- // Now that it does, put it there before it is looked at.
321
291
  const log = this.#root.querySelector('[data-reticle-log]');
322
292
  if (log !== null)
323
293
  settleLogAtLatest(log);
@@ -327,10 +297,6 @@ export class HudShell {
327
297
  this.#callbacks.onChatOpen?.();
328
298
  if (this.#dock !== undefined)
329
299
  scheduleSyncDockLayout(this.#dock, this.#root);
330
- const input = this.#root.querySelector('[data-reticle-input]');
331
- if (input !== null && !input.disabled) {
332
- requestAnimationFrame(() => input.focus());
333
- }
334
300
  }
335
301
  closeChat() {
336
302
  if (this.#root === undefined || !this.isChatOpen())
@@ -349,18 +315,10 @@ export class HudShell {
349
315
  else
350
316
  this.showChat();
351
317
  }
352
- /**
353
- * The chat, asked for by a PERSON - so it takes the slot from the report.
354
- *
355
- * `openChat` is also called by `expand`, which the agent triggers at session start; routing that
356
- * through here closed the impact report every time the agent touched the app, which is precisely
357
- * when you are reading it.
358
- */
359
318
  showChat() {
360
319
  this.#report.close();
361
320
  this.openChat();
362
321
  }
363
- /** Pulse the FAB when new activity arrives while collapsed. */
364
322
  pulseFab(active) {
365
323
  this.#fab?.setAttribute('data-pulse', active ? '1' : '0');
366
324
  }
@@ -370,15 +328,6 @@ export class HudShell {
370
328
  this.#transitionLock = false;
371
329
  }, TRANSITION_LOCK_MS);
372
330
  }
373
- /**
374
- * A click on the page dismisses the SETTINGS popover - and nothing else.
375
- *
376
- * The chat used to close here too, which was wrong from three directions: Reticle's own clicks
377
- * land on the page (synthetic in-page, or a genuine OS event when it drives through CDP), a click
378
- * in annotate mode is placing a mark, and a person clicking around their app while watching the
379
- * log is not asking for the log to go away. The chat has three deliberate ways out - its minimise
380
- * button, the toolbar toggle, and Escape - and that is all it needs.
381
- */
382
331
  #onDocPointerDown = (e) => {
383
332
  if (this.#root === undefined || this.#dock === undefined)
384
333
  return;
@@ -1,11 +1,3 @@
1
- /**
2
- * All presenter overlay CSS - glow border, synthetic cursor/ring/ripple, and the floating HUD shell.
3
- * Split across shell-styles + controls + log modules so each file stays under the size cap.
4
- */
5
- /**
6
- * The presenter overlay's stacking layer. Exported because the annotator has to sit ABOVE it: the
7
- * overlay holds the page blocker, and anything below this number is covered by that shield - which
8
- * is what buried the annotate composer and made its Cancel/Add buttons unclickable.
9
- */
10
- export declare const Z_OVERLAY = 2147483600;
1
+ import { Z_OVERLAY } from './chrome/layers.js';
2
+ export { Z_OVERLAY };
11
3
  export declare const PRESENTER_CSS: string;