@coframe-gtm/annotations 1.0.4 → 1.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coframe-gtm/annotations",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Clean-room AFS v1.1 annotation overlay (frontend) + transport-agnostic ingest core (backend). Injects into any page; humans + agents annotate bidirectionally.",
@@ -13,7 +13,7 @@
13
13
  "files": [
14
14
  "src",
15
15
  "README.md",
16
- "!src/**/*.stories.tsx"
16
+ "!src/**/*.stories.ts"
17
17
  ],
18
18
  "publishConfig": {
19
19
  "access": "public"
@@ -33,13 +33,9 @@
33
33
  "storybook": "storybook dev -p 6006",
34
34
  "build-storybook": "storybook build"
35
35
  },
36
- "dependencies": {
37
- "@preact/signals": "^2.0.0",
38
- "preact": "^10.24.0"
39
- },
36
+ "dependencies": {},
40
37
  "devDependencies": {
41
- "@preact/preset-vite": "^2.10.5",
42
- "@storybook/preact-vite": "^10.4.1",
38
+ "@storybook/html-vite": "^10.4.1",
43
39
  "@types/node": "^22.10.5",
44
40
  "esbuild": "^0.28.0",
45
41
  "jsdom": "^25.0.0",
package/src/README.md CHANGED
@@ -5,7 +5,7 @@ The clean-room injection bundle described in
5
5
  this scaffold:
6
6
 
7
7
  - Closed Shadow DOM mount (`shadow.ts`)
8
- - Preact-rendered debug shell (`ui/App.ts`)
8
+ - Vanilla DOM overlay (`ui/overlay.ts`)
9
9
  - `window.__annotations` API surface (`api.ts`)
10
10
  - Outbound webhook emitter (`webhook.ts`)
11
11
  - CDP install helpers (`inject/install.ts`)
@@ -61,14 +61,15 @@ src/v1/
61
61
  ├── README.md # this file
62
62
  ├── index.ts # public Node surface (install helpers, types)
63
63
  ├── types.ts # data model
64
- ├── store.ts # Preact signals
64
+ ├── store.ts # reactive signals (vanilla, ./signal.ts)
65
65
  ├── ulid.ts # tiny inlined ULID
66
66
  ├── shadow.ts # closed Shadow DOM mount
67
67
  ├── webhook.ts # outbound POST emitter
68
68
  ├── api.ts # window.__annotations
69
69
  ├── bundle.ts # IIFE entry
70
+ ├── signal.ts # tiny vanilla reactive primitive
70
71
  ├── ui/
71
- │ └── App.ts # root Preact tree (debug shell for P1)
72
+ │ └── overlay.ts # vanilla per-layer overlay mount
72
73
  └── inject/
73
74
  ├── install.ts # CDP install helpers
74
75
  └── build.ts # esbuild build script
package/src/api.ts CHANGED
@@ -90,6 +90,10 @@ export interface AnnotationsApi {
90
90
  /** Remove all cursors. */
91
91
  clearCursors(): void;
92
92
  setMode(next: Mode): void;
93
+ /** Current overlay mode. Lets a parent frame (headless) read view/comment state. */
94
+ getMode(): Mode;
95
+ /** Subscribe to mode changes. Returns an unsubscribe function. */
96
+ subscribeMode(fn: (mode: Mode) => void): () => void;
93
97
  setTheme(next: Theme): void;
94
98
  getAnnotations(): Annotation[];
95
99
  }
@@ -242,6 +246,14 @@ export const api: AnnotationsApi = {
242
246
  emit("session.updated", { mode: next });
243
247
  },
244
248
 
249
+ getMode() {
250
+ return mode.value;
251
+ },
252
+
253
+ subscribeMode(fn) {
254
+ return mode.subscribe(fn);
255
+ },
256
+
245
257
  setTheme(next) {
246
258
  theme.value = next;
247
259
  },
package/src/bundle.ts CHANGED
@@ -11,13 +11,11 @@
11
11
  * starting state.
12
12
  */
13
13
 
14
- import { render, h } from "preact";
15
-
16
14
  import { api, initSession } from "./api.js";
17
15
  import { installPicker, setPickerHost } from "./picker.js";
18
16
  import { mountShadow } from "./shadow.js";
19
17
  import { author, mode, ready, theme, viewportTick } from "./store.js";
20
- import { App } from "./ui/App.js";
18
+ import { mountOverlay as mountOverlayUi } from "./ui/overlay.js";
21
19
 
22
20
  import type { AnnotationsApi } from "./api.js";
23
21
  import type { Mode, Theme } from "./types.js";
@@ -28,6 +26,12 @@ interface InitOptions {
28
26
  author?: { kind: "human" | "agent"; id?: string; displayName?: string };
29
27
  mode?: Mode;
30
28
  theme?: Theme;
29
+ /**
30
+ * Headless mode: mount pins/cursors/composer/thread but NOT the
31
+ * toolbar, so a parent frame drives view/comment mode via
32
+ * `window.__annotations.setMode(...)`.
33
+ */
34
+ headless?: boolean;
31
35
  }
32
36
 
33
37
  declare global {
@@ -37,12 +41,14 @@ declare global {
37
41
  }
38
42
 
39
43
  let mounted = false;
44
+ let headless = false;
40
45
 
41
46
  function init(opts: InitOptions = {}): void {
42
47
  initSession(opts);
43
48
  if (opts.author) author.value = opts.author;
44
49
  if (opts.mode) mode.value = opts.mode;
45
50
  if (opts.theme) theme.value = opts.theme;
51
+ if (opts.headless) headless = true;
46
52
 
47
53
  mountOverlay();
48
54
 
@@ -51,7 +57,7 @@ function init(opts: InitOptions = {}): void {
51
57
  console.info("[annotations v1] ready on", location.href);
52
58
  }
53
59
 
54
- // Mount the shadow host + Preact tree once the DOM root exists. When the
60
+ // Mount the shadow host + overlay tree once the DOM root exists. When the
55
61
  // bundle is injected at document-start (e.g. via
56
62
  // `Page.addScriptToEvaluateOnNewDocument`), `document.documentElement` is
57
63
  // still null, so `mountShadow()` would throw and the overlay would never
@@ -69,7 +75,7 @@ function mountOverlay(): void {
69
75
  const { host, appRoot } = mountShadow();
70
76
  setPickerHost(host);
71
77
  installPicker();
72
- render(h(App, {}), appRoot);
78
+ mountOverlayUi(appRoot, { headless });
73
79
 
74
80
  const bump = (): void => {
75
81
  viewportTick.value++;
@@ -29,8 +29,6 @@ await build({
29
29
  format: "iife",
30
30
  minify: true,
31
31
  target: "es2020",
32
- jsx: "automatic",
33
- jsxImportSource: "preact",
34
32
  legalComments: "none",
35
33
  logLevel: "info",
36
34
  });
@@ -2,4 +2,4 @@
2
2
  // This file is generated by `pnpm build`.
3
3
  // Do not edit by hand. Regenerate by running the build script.
4
4
  export const ANNOTATIONS_V1_BUNDLE_SOURCE: string =
5
- "\"use strict\";(()=>{var pe,m,lt,Re,D,rt,ct,ut,Me,le,te,ft,Be,Ie,Le,kn,ue={},fe=[],wn=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,_e=Array.isArray;function O(e,t){for(var n in t)e[n]=t[n];return e}function Oe(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function Ue(e,t,n){var o,r,i,s={};for(i in t)i==\"key\"?o=t[i]:i==\"ref\"?r=t[i]:s[i]=t[i];if(arguments.length>2&&(s.children=arguments.length>3?pe.call(arguments,2):n),typeof e==\"function\"&&e.defaultProps!=null)for(i in e.defaultProps)s[i]===void 0&&(s[i]=e.defaultProps[i]);return ce(e,s,o,r,null)}function ce(e,t,n,o,r){var i={type:e,props:t,key:n,ref:o,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:r??++lt,__i:-1,__u:0};return r==null&&m.vnode!=null&&m.vnode(i),i}function j(e){return e.children}function K(e,t){this.props=e,this.context=t}function X(e,t){if(t==null)return e.__?X(e.__,e.__i+1):null;for(var n;t<e.__k.length;t++)if((n=e.__k[t])!=null&&n.__e!=null)return n.__e;return typeof e.type==\"function\"?X(e):null}function Cn(e){if(e.__P&&e.__d){var t=e.__v,n=t.__e,o=[],r=[],i=O({},t);i.__v=t.__v+1,m.vnode&&m.vnode(i),Fe(e.__P,i,t,e.__n,e.__P.namespaceURI,32&t.__u?[n]:null,o,n??X(t),!!(32&t.__u),r),i.__v=t.__v,i.__.__k[i.__i]=i,mt(o,i,r),t.__e=t.__=null,i.__e!=n&&dt(i)}}function dt(e){if((e=e.__)!=null&&e.__c!=null)return e.__e=e.__c.base=null,e.__k.some(function(t){if(t!=null&&t.__e!=null)return e.__e=e.__c.base=t.__e}),dt(e)}function it(e){(!e.__d&&(e.__d=!0)&&D.push(e)&&!de.__r++||rt!=m.debounceRendering)&&((rt=m.debounceRendering)||ct)(de)}function de(){try{for(var e,t=1;D.length;)D.length>t&&D.sort(ut),e=D.shift(),t=D.length,Cn(e)}finally{D.length=de.__r=0}}function pt(e,t,n,o,r,i,s,c,f,l,d){var a,_,p,C,I,S,v,h=o&&o.__k||fe,F=t.length;for(f=Sn(n,t,h,f,F),a=0;a<F;a++)(p=n.__k[a])!=null&&(_=p.__i!=-1&&h[p.__i]||ue,p.__i=a,S=Fe(e,p,_,r,i,s,c,f,l,d),C=p.__e,p.ref&&_.ref!=p.ref&&(_.ref&&De(_.ref,null,p),d.push(p.ref,p.__c||C,p)),I==null&&C!=null&&(I=C),(v=!!(4&p.__u))||_.__k===p.__k?(f=_t(p,f,e,v),v&&_.__e&&(_.__e=null)):typeof p.type==\"function\"&&S!==void 0?f=S:C&&(f=C.nextSibling),p.__u&=-7);return n.__e=I,f}function Sn(e,t,n,o,r){var i,s,c,f,l,d=n.length,a=d,_=0;for(e.__k=new Array(r),i=0;i<r;i++)(s=t[i])!=null&&typeof s!=\"boolean\"&&typeof s!=\"function\"?(typeof s==\"string\"||typeof s==\"number\"||typeof s==\"bigint\"||s.constructor==String?s=e.__k[i]=ce(null,s,null,null,null):_e(s)?s=e.__k[i]=ce(j,{children:s},null,null,null):s.constructor===void 0&&s.__b>0?s=e.__k[i]=ce(s.type,s.props,s.key,s.ref?s.ref:null,s.__v):e.__k[i]=s,f=i+_,s.__=e,s.__b=e.__b+1,c=null,(l=s.__i=An(s,n,f,a))!=-1&&(a--,(c=n[l])&&(c.__u|=2)),c==null||c.__v==null?(l==-1&&(r>d?_--:r<d&&_++),typeof s.type!=\"function\"&&(s.__u|=4)):l!=f&&(l==f-1?_--:l==f+1?_++:(l>f?_--:_++,s.__u|=4))):e.__k[i]=null;if(a)for(i=0;i<d;i++)(c=n[i])!=null&&(2&c.__u)==0&&(c.__e==o&&(o=X(c)),vt(c,c));return o}function _t(e,t,n,o){var r,i;if(typeof e.type==\"function\"){for(r=e.__k,i=0;r&&i<r.length;i++)r[i]&&(r[i].__=e,t=_t(r[i],t,n,o));return t}e.__e!=t&&(o&&(t&&e.type&&!t.parentNode&&(t=X(e)),n.insertBefore(e.__e,t||null)),t=e.__e);do t=t&&t.nextSibling;while(t!=null&&t.nodeType==8);return t}function An(e,t,n,o){var r,i,s,c=e.key,f=e.type,l=t[n],d=l!=null&&(2&l.__u)==0;if(l===null&&c==null||d&&c==l.key&&f==l.type)return n;if(o>(d?1:0)){for(r=n-1,i=n+1;r>=0||i<t.length;)if((l=t[s=r>=0?r--:i++])!=null&&(2&l.__u)==0&&c==l.key&&f==l.type)return s}return-1}function at(e,t,n){t[0]==\"-\"?e.setProperty(t,n??\"\"):e[t]=n==null?\"\":typeof n!=\"number\"||wn.test(t)?n:n+\"px\"}function se(e,t,n,o,r){var i,s;e:if(t==\"style\")if(typeof n==\"string\")e.style.cssText=n;else{if(typeof o==\"string\"&&(e.style.cssText=o=\"\"),o)for(t in o)n&&t in n||at(e.style,t,\"\");if(n)for(t in n)o&&n[t]==o[t]||at(e.style,t,n[t])}else if(t[0]==\"o\"&&t[1]==\"n\")i=t!=(t=t.replace(ft,\"$1\")),s=t.toLowerCase(),t=s in e||t==\"onFocusOut\"||t==\"onFocusIn\"?s.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+i]=n,n?o?n[te]=o[te]:(n[te]=Be,e.addEventListener(t,i?Le:Ie,i)):e.removeEventListener(t,i?Le:Ie,i);else{if(r==\"http://www.w3.org/2000/svg\")t=t.replace(/xlink(H|:h)/,\"h\").replace(/sName$/,\"s\");else if(t!=\"width\"&&t!=\"height\"&&t!=\"href\"&&t!=\"list\"&&t!=\"form\"&&t!=\"tabIndex\"&&t!=\"download\"&&t!=\"rowSpan\"&&t!=\"colSpan\"&&t!=\"role\"&&t!=\"popover\"&&t in e)try{e[t]=n??\"\";break e}catch{}typeof n==\"function\"||(n==null||n===!1&&t[4]!=\"-\"?e.removeAttribute(t):e.setAttribute(t,t==\"popover\"&&n==1?\"\":n))}}function st(e){return function(t){if(this.l){var n=this.l[t.type+e];if(t[le]==null)t[le]=Be++;else if(t[le]<n[te])return;return n(m.event?m.event(t):t)}}}function Fe(e,t,n,o,r,i,s,c,f,l){var d,a,_,p,C,I,S,v,h,F,H,ee,ot,ae,$e,R=t.type;if(t.constructor!==void 0)return null;128&n.__u&&(f=!!(32&n.__u),i=[c=t.__e=n.__e]),(d=m.__b)&&d(t);e:if(typeof R==\"function\")try{if(v=t.props,h=R.prototype&&R.prototype.render,F=(d=R.contextType)&&o[d.__c],H=d?F?F.props.value:d.__:o,n.__c?S=(a=t.__c=n.__c).__=a.__E:(h?t.__c=a=new R(v,H):(t.__c=a=new K(v,H),a.constructor=R,a.render=Tn),F&&F.sub(a),a.state||(a.state={}),a.__n=o,_=a.__d=!0,a.__h=[],a._sb=[]),h&&a.__s==null&&(a.__s=a.state),h&&R.getDerivedStateFromProps!=null&&(a.__s==a.state&&(a.__s=O({},a.__s)),O(a.__s,R.getDerivedStateFromProps(v,a.__s))),p=a.props,C=a.state,a.__v=t,_)h&&R.getDerivedStateFromProps==null&&a.componentWillMount!=null&&a.componentWillMount(),h&&a.componentDidMount!=null&&a.__h.push(a.componentDidMount);else{if(h&&R.getDerivedStateFromProps==null&&v!==p&&a.componentWillReceiveProps!=null&&a.componentWillReceiveProps(v,H),t.__v==n.__v||!a.__e&&a.shouldComponentUpdate!=null&&a.shouldComponentUpdate(v,a.__s,H)===!1){t.__v!=n.__v&&(a.props=v,a.state=a.__s,a.__d=!1),t.__e=n.__e,t.__k=n.__k,t.__k.some(function(q){q&&(q.__=t)}),fe.push.apply(a.__h,a._sb),a._sb=[],a.__h.length&&s.push(a);break e}a.componentWillUpdate!=null&&a.componentWillUpdate(v,a.__s,H),h&&a.componentDidUpdate!=null&&a.__h.push(function(){a.componentDidUpdate(p,C,I)})}if(a.context=H,a.props=v,a.__P=e,a.__e=!1,ee=m.__r,ot=0,h)a.state=a.__s,a.__d=!1,ee&&ee(t),d=a.render(a.props,a.state,a.context),fe.push.apply(a.__h,a._sb),a._sb=[];else do a.__d=!1,ee&&ee(t),d=a.render(a.props,a.state,a.context),a.state=a.__s;while(a.__d&&++ot<25);a.state=a.__s,a.getChildContext!=null&&(o=O(O({},o),a.getChildContext())),h&&!_&&a.getSnapshotBeforeUpdate!=null&&(I=a.getSnapshotBeforeUpdate(p,C)),ae=d!=null&&d.type===j&&d.key==null?ht(d.props.children):d,c=pt(e,_e(ae)?ae:[ae],t,n,o,r,i,s,c,f,l),a.base=t.__e,t.__u&=-161,a.__h.length&&s.push(a),S&&(a.__E=a.__=null)}catch(q){if(t.__v=null,f||i!=null)if(q.then){for(t.__u|=f?160:128;c&&c.nodeType==8&&c.nextSibling;)c=c.nextSibling;i[i.indexOf(c)]=null,t.__e=c}else{for($e=i.length;$e--;)Oe(i[$e]);Ne(t)}else t.__e=n.__e,t.__k=n.__k,q.then||Ne(t);m.__e(q,t,n)}else i==null&&t.__v==n.__v?(t.__k=n.__k,t.__e=n.__e):c=t.__e=En(n.__e,t,n,o,r,i,s,f,l);return(d=m.diffed)&&d(t),128&t.__u?void 0:c}function Ne(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(Ne))}function mt(e,t,n){for(var o=0;o<n.length;o++)De(n[o],n[++o],n[++o]);m.__c&&m.__c(t,e),e.some(function(r){try{e=r.__h,r.__h=[],e.some(function(i){i.call(r)})}catch(i){m.__e(i,r.__v)}})}function ht(e){return typeof e!=\"object\"||e==null||e.__b>0?e:_e(e)?e.map(ht):e.constructor!==void 0?null:O({},e)}function En(e,t,n,o,r,i,s,c,f){var l,d,a,_,p,C,I,S=n.props||ue,v=t.props,h=t.type;if(h==\"svg\"?r=\"http://www.w3.org/2000/svg\":h==\"math\"?r=\"http://www.w3.org/1998/Math/MathML\":r||(r=\"http://www.w3.org/1999/xhtml\"),i!=null){for(l=0;l<i.length;l++)if((p=i[l])&&\"setAttribute\"in p==!!h&&(h?p.localName==h:p.nodeType==3)){e=p,i[l]=null;break}}if(e==null){if(h==null)return document.createTextNode(v);e=document.createElementNS(r,h,v.is&&v),c&&(m.__m&&m.__m(t,i),c=!1),i=null}if(h==null)S===v||c&&e.data==v||(e.data=v);else{if(i=h==\"textarea\"&&v.defaultValue!=null?null:i&&pe.call(e.childNodes),!c&&i!=null)for(S={},l=0;l<e.attributes.length;l++)S[(p=e.attributes[l]).name]=p.value;for(l in S)p=S[l],l==\"dangerouslySetInnerHTML\"?a=p:l==\"children\"||l in v||l==\"value\"&&\"defaultValue\"in v||l==\"checked\"&&\"defaultChecked\"in v||se(e,l,null,p,r);for(l in v)p=v[l],l==\"children\"?_=p:l==\"dangerouslySetInnerHTML\"?d=p:l==\"value\"?C=p:l==\"checked\"?I=p:c&&typeof p!=\"function\"||S[l]===p||se(e,l,p,S[l],r);if(d)c||a&&(d.__html==a.__html||d.__html==e.innerHTML)||(e.innerHTML=d.__html),t.__k=[];else if(a&&(e.innerHTML=\"\"),pt(t.type==\"template\"?e.content:e,_e(_)?_:[_],t,n,o,h==\"foreignObject\"?\"http://www.w3.org/1999/xhtml\":r,i,s,i?i[0]:n.__k&&X(n,0),c,f),i!=null)for(l=i.length;l--;)Oe(i[l]);c&&h!=\"textarea\"||(l=\"value\",h==\"progress\"&&C==null?e.removeAttribute(\"value\"):C!=null&&(C!==e[l]||h==\"progress\"&&!C||h==\"option\"&&C!=S[l])&&se(e,l,C,S[l],r),l=\"checked\",I!=null&&I!=e[l]&&se(e,l,I,S[l],r))}return e}function De(e,t,n){try{if(typeof e==\"function\"){var o=typeof e.__u==\"function\";o&&e.__u(),o&&t==null||(e.__u=e(t))}else e.current=t}catch(r){m.__e(r,n)}}function vt(e,t,n){var o,r;if(m.unmount&&m.unmount(e),(o=e.ref)&&(o.current&&o.current!=e.__e||De(o,null,t)),(o=e.__c)!=null){if(o.componentWillUnmount)try{o.componentWillUnmount()}catch(i){m.__e(i,t)}o.base=o.__P=null}if(o=e.__k)for(r=0;r<o.length;r++)o[r]&&vt(o[r],t,n||typeof e.type!=\"function\");n||Oe(e.__e),e.__c=e.__=e.__e=void 0}function Tn(e,t,n){return this.constructor(e,n)}function gt(e,t,n){var o,r,i,s;t==document&&(t=document.documentElement),m.__&&m.__(e,t),r=(o=typeof n==\"function\")?null:n&&n.__k||t.__k,i=[],s=[],Fe(t,e=(!o&&n||t).__k=Ue(j,null,[e]),r||ue,ue,t.namespaceURI,!o&&n?[n]:r?null:t.firstChild?pe.call(t.childNodes):null,i,!o&&n?n:r?r.__e:t.firstChild,o,s),mt(i,e,s)}pe=fe.slice,m={__e:function(e,t,n,o){for(var r,i,s;t=t.__;)if((r=t.__c)&&!r.__)try{if((i=r.constructor)&&i.getDerivedStateFromError!=null&&(r.setState(i.getDerivedStateFromError(e)),s=r.__d),r.componentDidCatch!=null&&(r.componentDidCatch(e,o||{}),s=r.__d),s)return r.__E=r}catch(c){e=c}throw e}},lt=0,Re=function(e){return e!=null&&e.constructor===void 0},K.prototype.setState=function(e,t){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=O({},this.state),typeof e==\"function\"&&(e=e(O({},n),this.props)),e&&O(n,e),e!=null&&this.__v&&(t&&this._sb.push(t),it(this))},K.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),it(this))},K.prototype.render=j,D=[],ct=typeof Promise==\"function\"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,ut=function(e,t){return e.__v.__b-t.__v.__b},de.__r=0,Me=Math.random().toString(8),le=\"__d\"+Me,te=\"__a\"+Me,ft=/(PointerCapture)$|Capture$/i,Be=0,Ie=st(!1),Le=st(!0),kn=0;var yt=\"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";function me(e=Date.now()){let t=e,n=\"\";for(let r=0;r<10;r++)n=yt[t&31]+n,t=Math.floor(t/32);let o=\"\";for(let r=0;r<16;r++)o+=yt[Math.floor(Math.random()*32)];return n+o}var ve,b,je,bt,He=0,Tt=[],k=m,xt=k.__b,kt=k.__r,wt=k.diffed,Ct=k.__c,St=k.unmount,At=k.__;function Pt(e,t){k.__h&&k.__h(b,e,He||t),He=0;var n=b.__H||(b.__H={__:[],__h:[]});return e>=n.__.length&&n.__.push({}),n.__[e]}function Z(e){return He=1,Pn($t,e)}function Pn(e,t,n){var o=Pt(ve++,2);if(o.t=e,!o.__c&&(o.__=[n?n(t):$t(void 0,t),function(c){var f=o.__N?o.__N[0]:o.__[0],l=o.t(f,c);f!==l&&(o.__N=[l,o.__[1]],o.__c.setState({}))}],o.__c=b,!b.__f)){var r=function(c,f,l){if(!o.__c.__H)return!0;var d=o.__c.__H.__.filter(function(_){return _.__c});if(d.every(function(_){return!_.__N}))return!i||i.call(this,c,f,l);var a=o.__c.props!==c;return d.some(function(_){if(_.__N){var p=_.__[0];_.__=_.__N,_.__N=void 0,p!==_.__[0]&&(a=!0)}}),i&&i.call(this,c,f,l)||a};b.__f=!0;var i=b.shouldComponentUpdate,s=b.componentWillUpdate;b.componentWillUpdate=function(c,f,l){if(this.__e){var d=i;i=void 0,r(c,f,l),i=d}s&&s.call(this,c,f,l)},b.shouldComponentUpdate=r}return o.__N||o.__}function We(e,t){var n=Pt(ve++,7);return In(n.__H,t)&&(n.__=e(),n.__H=t,n.__h=e),n.__}function $n(){for(var e;e=Tt.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(he),t.__h.some(ze),t.__h=[]}catch(n){t.__h=[],k.__e(n,e.__v)}}}k.__b=function(e){b=null,xt&&xt(e)},k.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),At&&At(e,t)},k.__r=function(e){kt&&kt(e),ve=0;var t=(b=e.__c).__H;t&&(je===b?(t.__h=[],b.__h=[],t.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(t.__h.some(he),t.__h.some(ze),t.__h=[],ve=0)),je=b},k.diffed=function(e){wt&&wt(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(Tt.push(t)!==1&&bt===k.requestAnimationFrame||((bt=k.requestAnimationFrame)||Mn)($n)),t.__H.__.some(function(n){n.u&&(n.__H=n.u),n.u=void 0})),je=b=null},k.__c=function(e,t){t.some(function(n){try{n.__h.some(he),n.__h=n.__h.filter(function(o){return!o.__||ze(o)})}catch(o){t.some(function(r){r.__h&&(r.__h=[])}),t=[],k.__e(o,n.__v)}}),Ct&&Ct(e,t)},k.unmount=function(e){St&&St(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.some(function(o){try{he(o)}catch(r){t=r}}),n.__H=void 0,t&&k.__e(t,n.__v))};var Et=typeof requestAnimationFrame==\"function\";function Mn(e){var t,n=function(){clearTimeout(o),Et&&cancelAnimationFrame(t),setTimeout(e)},o=setTimeout(n,35);Et&&(t=requestAnimationFrame(n))}function he(e){var t=b,n=e.__c;typeof n==\"function\"&&(e.__c=void 0,n()),b=t}function ze(e){var t=b;e.__c=e.__(),b=t}function In(e,t){return!e||e.length!==t.length||t.some(function(n,o){return n!==e[o]})}function $t(e,t){return typeof t==\"function\"?t(e):t}var Ln=Symbol.for(\"preact-signals\");function xe(){if(U>1)U--;else{var e,t=!1;for((function(){var r=ye;for(ye=void 0;r!==void 0;)r.S.v===r.v&&(r.S.i=r.i),r=r.o})();ne!==void 0;){var n=ne;for(ne=void 0,ge++;n!==void 0;){var o=n.u;if(n.u=void 0,n.f&=-3,!(8&n.f)&&Lt(n))try{n.c()}catch(r){t||(e=r,t=!0)}n=o}}if(ge=0,U--,t)throw e}}function Ve(e){if(U>0)return e();Ye=++Nn,U++;try{return e()}finally{xe()}}var g=void 0;function ke(e){var t=g;g=void 0;try{return e()}finally{g=t}}var Mt,ne=void 0,U=0,ge=0,Nn=0,Ye=0,ye=void 0,be=0;function It(e){if(g!==void 0){var t=e.n;if(t===void 0||t.t!==g)return t={i:0,S:e,p:g.s,n:void 0,t:g,e:void 0,x:void 0,r:t},g.s!==void 0&&(g.s.n=t),g.s=t,e.n=t,32&g.f&&e.S(t),t;if(t.i===-1)return t.i=0,t.n!==void 0&&(t.n.p=t.p,t.p!==void 0&&(t.p.n=t.n),t.p=g.s,t.n=void 0,g.s.n=t,g.s=t),t}}function w(e,t){this.v=e,this.i=0,this.n=void 0,this.t=void 0,this.l=0,this.W=t?.watched,this.Z=t?.unwatched,this.name=t?.name}w.prototype.brand=Ln;w.prototype.h=function(){return!0};w.prototype.S=function(e){var t=this,n=this.t;n!==e&&e.e===void 0&&(e.x=n,this.t=e,n!==void 0?n.e=e:ke(function(){var o;(o=t.W)==null||o.call(t)}))};w.prototype.U=function(e){var t=this;if(this.t!==void 0){var n=e.e,o=e.x;n!==void 0&&(n.x=o,e.e=void 0),o!==void 0&&(o.e=n,e.x=void 0),e===this.t&&(this.t=o,o===void 0&&ke(function(){var r;(r=t.Z)==null||r.call(t)}))}};w.prototype.subscribe=function(e){var t=this;return W(function(){var n=t.value,o=g;g=void 0;try{e(n)}finally{g=o}},{name:\"sub\"})};w.prototype.valueOf=function(){return this.value};w.prototype.toString=function(){return this.value+\"\"};w.prototype.toJSON=function(){return this.value};w.prototype.peek=function(){var e=this;return ke(function(){return e.value})};Object.defineProperty(w.prototype,\"value\",{get:function(){var e=It(this);return e!==void 0&&(e.i=this.i),this.v},set:function(e){if(e!==this.v){if(ge>100)throw new Error(\"Cycle detected\");(function(n){U!==0&&ge===0&&n.l!==Ye&&(n.l=Ye,ye={S:n,v:n.v,i:n.i,o:ye})})(this),this.v=e,this.i++,be++,U++;try{for(var t=this.t;t!==void 0;t=t.x)t.t.N()}finally{xe()}}}});function x(e,t){return new w(e,t)}function Lt(e){for(var t=e.s;t!==void 0;t=t.n)if(t.S.i!==t.i||!t.S.h()||t.S.i!==t.i)return!0;return!1}function Nt(e){for(var t=e.s;t!==void 0;t=t.n){var n=t.S.n;if(n!==void 0&&(t.r=n),t.S.n=t,t.i=-1,t.n===void 0){e.s=t;break}}}function Rt(e){for(var t=e.s,n=void 0;t!==void 0;){var o=t.p;t.i===-1?(t.S.U(t),o!==void 0&&(o.n=t.n),t.n!==void 0&&(t.n.p=o)):n=t,t.S.n=t.r,t.r!==void 0&&(t.r=void 0),t=o}e.s=n}function z(e,t){w.call(this,void 0),this.x=e,this.s=void 0,this.g=be-1,this.f=4,this.W=t?.watched,this.Z=t?.unwatched,this.name=t?.name}z.prototype=new w;z.prototype.h=function(){if(this.f&=-3,1&this.f)return!1;if((36&this.f)==32||(this.f&=-5,this.g===be))return!0;if(this.g=be,this.f|=1,this.i>0&&!Lt(this))return this.f&=-2,!0;var e=g;try{Nt(this),g=this;var t=this.x();(16&this.f||this.v!==t||this.i===0)&&(this.v=t,this.f&=-17,this.i++)}catch(n){this.v=n,this.f|=16,this.i++}return g=e,Rt(this),this.f&=-2,!0};z.prototype.S=function(e){if(this.t===void 0){this.f|=36;for(var t=this.s;t!==void 0;t=t.n)t.S.S(t)}w.prototype.S.call(this,e)};z.prototype.U=function(e){if(this.t!==void 0&&(w.prototype.U.call(this,e),this.t===void 0)){this.f&=-33;for(var t=this.s;t!==void 0;t=t.n)t.S.U(t)}};z.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var e=this.t;e!==void 0;e=e.x)e.t.N()}};Object.defineProperty(z.prototype,\"value\",{get:function(){if(1&this.f)throw new Error(\"Cycle detected\");var e=It(this);if(this.h(),e!==void 0&&(e.i=this.i),16&this.f)throw this.v;return this.v}});function we(e,t){return new z(e,t)}function Bt(e){var t=e.m;if(e.m=void 0,typeof t==\"function\"){U++;var n=g;g=void 0;try{t()}catch(o){throw e.f&=-2,e.f|=8,qe(e),o}finally{g=n,xe()}}}function qe(e){for(var t=e.s;t!==void 0;t=t.n)t.S.U(t);e.x=void 0,e.s=void 0,Bt(e)}function Rn(e){if(g!==this)throw new Error(\"Out-of-order effect\");Rt(this),g=e,this.f&=-2,8&this.f&&qe(this),xe()}function G(e,t){this.x=e,this.m=void 0,this.s=void 0,this.u=void 0,this.f=32,this.name=t?.name,Mt&&Mt.push(this)}G.prototype.c=function(){var e=this.S();try{if(8&this.f||this.x===void 0)return;var t=this.x();typeof t==\"function\"&&(this.m=t)}finally{e()}};G.prototype.S=function(){if(1&this.f)throw new Error(\"Cycle detected\");this.f|=1,this.f&=-9,Bt(this),Nt(this),U++;var e=g;return g=this,Rn.bind(this,e)};G.prototype.N=function(){2&this.f||(this.f|=2,this.u=ne,ne=this)};G.prototype.d=function(){this.f|=8,1&this.f||qe(this)};G.prototype.dispose=function(){this.d()};function W(e,t){var n=new G(e,t);try{n.c()}catch(r){throw n.d(),r}var o=n.d.bind(n);return o[Symbol.dispose]=o,o}var Ot,Ke,Ce,Bn=typeof window<\"u\"&&!!window.__PREACT_SIGNALS_DEVTOOLS__;var Ut=[];W(function(){Ot=this.N})();function J(e,t){m[e]=t.bind(null,m[e]||function(){})}function Se(e){if(Ce){var t=Ce;Ce=void 0,t()}Ce=e&&e.S()}function Ft(e){var t=this,n=e.data,o=Un(n);o.value=n;var r=We(function(){for(var c=t,f=t.__v;f=f.__;)if(f.__c){f.__c.__$f|=4;break}var l=we(function(){var p=o.value.value;return p===0?0:p===!0?\"\":p||\"\"}),d=we(function(){return!Array.isArray(l.value)&&!Re(l.value)}),a=W(function(){if(this.N=Dt,d.value){var p=l.value;c.__v&&c.__v.__e&&c.__v.__e.nodeType===3&&(c.__v.__e.data=p)}}),_=t.__$u.d;return t.__$u.d=function(){a(),_.call(this)},[d,l]},[]),i=r[0],s=r[1];return i.value?s.peek():s.value}Ft.displayName=\"ReactiveTextNode\";Object.defineProperties(w.prototype,{constructor:{configurable:!0,value:void 0},type:{configurable:!0,value:Ft},props:{configurable:!0,get:function(){var e=this;return{data:{get value(){return e.value}}}}},__b:{configurable:!0,value:1}});J(\"__b\",function(e,t){if(typeof t.type==\"string\"){var n,o=t.props;for(var r in o)if(r!==\"children\"){var i=o[r];i instanceof w&&(n||(t.__np=n={}),n[r]=i,o[r]=i.peek())}}e(t)});J(\"__r\",function(e,t){if(e(t),t.type!==j){Se();var n,o=t.__c;o&&(o.__$f&=-2,(n=o.__$u)===void 0&&(o.__$u=n=(function(r,i){var s;return W(function(){s=this},{name:i}),s.c=r,s})(function(){var r;Bn&&((r=n.y)==null||r.call(n)),o.__$f|=1,o.setState({})},typeof t.type==\"function\"?t.type.displayName||t.type.name:\"\"))),Ke=o,Se(n)}});J(\"__e\",function(e,t,n,o){Se(),Ke=void 0,e(t,n,o)});J(\"diffed\",function(e,t){Se(),Ke=void 0;var n;if(typeof t.type==\"string\"&&(n=t.__e)){var o=t.__np,r=t.props;if(o){var i=n.U;if(i)for(var s in i){var c=i[s];c!==void 0&&!(s in o)&&(c.d(),i[s]=void 0)}else i={},n.U=i;for(var f in o){var l=i[f],d=o[f];l===void 0?(l=On(n,f,d),i[f]=l):l.o(d,r)}}}e(t)});function On(e,t,n,o){var r=t in e&&e.ownerSVGElement===void 0,i=x(n),s=n.peek();return{o:function(c,f){i.value=c,s=c.peek()},d:W(function(){this.N=Dt;var c=i.value.value;s!==c?(s=void 0,r?e[t]=c:c!=null&&(c!==!1||t[4]===\"-\")?e.setAttribute(t,c):e.removeAttribute(t)):s=void 0})}}J(\"unmount\",function(e,t){if(typeof t.type==\"string\"){var n=t.__e;if(n){var o=n.U;if(o){n.U=void 0;for(var r in o){var i=o[r];i&&i.d()}}}var s=t.__np;if(s){var c=t.props;for(var f in s)c[f]=s[f]}t.__np=void 0}else{var l=t.__c;if(l){var d=l.__$u;d&&(l.__$u=void 0,d.d())}}e(t)});J(\"__h\",function(e,t,n,o){(o<3||o===9)&&(t.__$f|=2),e(t,n,o)});K.prototype.shouldComponentUpdate=function(e,t){if(this.__R)return!0;var n=this.__$u,o=n&&n.s!==void 0;for(var r in t)return!0;if(this.__f||typeof this.u==\"boolean\"&&this.u===!0){var i=2&this.__$f;if(!(o||i||4&this.__$f)||1&this.__$f)return!0}else if(!(o||4&this.__$f)||3&this.__$f)return!0;for(var s in e)if(s!==\"__source\"&&e[s]!==this.props[s])return!0;for(var c in this.props)if(!(c in e))return!0;return!1};function Un(e,t){return We(function(){return x(e,t)},[])}var Fn=function(e){queueMicrotask(function(){queueMicrotask(e)})};function Dn(){Ve(function(){for(var e;e=Ut.shift();)Ot.call(e)})}function Dt(){Ut.push(this)===1&&(m.requestAnimationFrame||Fn)(Dn)}var y=x([]),A=x(\"view\"),Y=x(\"dark\"),Ae=x(null),oe=x(\"\"),jt=x(0),Ht=x(!1),L=x({kind:\"human\",id:\"human\",displayName:\"You\"}),E=x(\"element\"),T=x(null),P=x(null),$=x([]),M=x(null),Ee=x(0),N=x([]);function B(e,t){let n=Ae.value,o={type:e,timestamp:new Date().toISOString(),sessionId:oe.value,sequence:++jt.value,payload:t};if(n)try{fetch(n,{method:\"POST\",headers:{\"Content-Type\":\"application/json\"},body:JSON.stringify(o),keepalive:!0}).catch(r=>console.warn(\"[annotations] webhook emit failed\",r))}catch(r){console.warn(\"[annotations] webhook emit threw synchronously\",r)}}var V={version:\"0.1.0\",schema:\"afs-1.1\",addAnnotation(e){let t=e.id??`ann_${me().slice(-12).toLowerCase()}`,n=Date.now(),o={id:t,comment:e.comment,elementPath:e.elementPath,element:e.element,x:e.x,y:e.y,timestamp:e.timestamp??n,url:e.url,boundingBox:e.boundingBox,reactComponents:e.reactComponents,cssClasses:e.cssClasses,computedStyles:e.computedStyles,accessibility:e.accessibility,nearbyText:e.nearbyText,selectedText:e.selectedText,isFixed:e.isFixed,isMultiSelect:e.isMultiSelect,fullPath:e.fullPath,nearbyElements:e.nearbyElements,elementBoundingBoxes:e.elementBoundingBoxes,intent:e.intent,severity:e.severity,kind:e.kind??\"feedback\",placement:e.placement,rearrange:e.rearrange,status:e.status??\"pending\",thread:[],author:e.author??{kind:\"agent\",id:\"agent\",displayName:\"Agent\"},createdAt:new Date(n).toISOString(),updatedAt:new Date(n).toISOString()};return y.value=[...y.value,o],B(\"annotation.created\",o),t},replyToAnnotation(e,t){if(!y.value.find(r=>r.id===e))return null;let o={id:`msg_${me().slice(-10).toLowerCase()}`,role:t.role,content:t.content,timestamp:Date.now()};return y.value=y.value.map(r=>r.id===e?{...r,thread:[...r.thread??[],o],updatedAt:new Date().toISOString()}:r),B(\"thread.message\",{annotationId:e,message:o}),o.id},updateAnnotation(e,t){let n=!1;return y.value=y.value.map(o=>o.id!==e?o:(n=!0,{...o,...t,updatedAt:new Date().toISOString()})),n&&B(\"annotation.updated\",{id:e,patch:t}),n},acknowledgeAnnotation(e){return this.updateAnnotation(e,{status:\"acknowledged\"})},resolveAnnotation(e,t=\"agent\"){return this.updateAnnotation(e,{status:\"resolved\",resolvedAt:new Date().toISOString(),resolvedBy:t})},dismissAnnotation(e){return this.updateAnnotation(e,{status:\"dismissed\"})},removeAnnotation(e){let t=y.value.length;y.value=y.value.filter(o=>o.id!==e);let n=y.value.length<t;return n&&B(\"annotation.deleted\",{id:e}),n},clearAnnotations(){let e=y.value.length;return y.value=[],M.value=null,B(\"session.updated\",{cleared:e}),e},focusAnnotation(e){let t=y.value.some(n=>n.id===e);return t&&(M.value=e),t},closeThread(){M.value=null},setCursors(e){N.value=e},setCursor(e){let t=N.value.filter(n=>n.id!==e.id);N.value=[...t,e]},removeCursor(e){let t=N.value.length;return N.value=N.value.filter(n=>n.id!==e),N.value.length<t},clearCursors(){N.value=[]},setMode(e){A.value!==e&&(A.value=e,B(\"session.updated\",{mode:e}))},setTheme(e){Y.value=e},getAnnotations(){return y.value}};function zt(e){e.webhookUrl!==void 0&&(Ae.value=e.webhookUrl),oe.value=e.sessionId??`cf_${me().slice(-12).toLowerCase()}`,B(\"session.created\",{sessionId:oe.value,pageUrl:typeof location<\"u\"?location.href:\"\"})}var jn=[\"display\",\"position\",\"width\",\"height\",\"margin\",\"padding\",\"color\",\"background-color\",\"background\",\"font-family\",\"font-size\",\"font-weight\",\"line-height\",\"border\",\"border-radius\",\"box-shadow\",\"flex-direction\",\"justify-content\",\"align-items\",\"gap\",\"grid-template-columns\",\"z-index\",\"opacity\",\"text-align\"],Hn=[\"role\",\"aria-label\",\"aria-labelledby\",\"aria-describedby\",\"aria-hidden\",\"aria-expanded\",\"aria-checked\",\"aria-selected\",\"alt\",\"title\",\"tabindex\",\"type\",\"name\",\"for\",\"href\"];function Te(e){let t=e.getBoundingClientRect(),n=Qn(e),o=window.scrollX,r=window.scrollY,i={x:t.left+(n?0:o),y:t.top+(n?0:r),width:t.width,height:t.height};return{element:e.tagName.toLowerCase(),elementPath:zn(e),fullPath:Wn(e),x:eo((t.left+t.width/2)/window.innerWidth*100),y:n?t.top:t.top+r,url:location.href,boundingBox:i,isFixed:n,cssClasses:Yn(e),computedStyles:Vn(e),accessibility:qn(e),nearbyText:Kn(e),nearbyElements:Xn(e),reactComponents:Gn(e)}}function zn(e){if(e.id&&Wt(e.id))return`#${Ze(e.id)}`;let t=e.getAttribute(\"data-testid\");if(t)return`[data-testid=\"${t}\"]`;let n=e.tagName.toLowerCase(),o=Yt(e);return o?`${n}.${Ze(o)}`:n}function Wn(e){let t=[],n=e;for(;n&&n.nodeType===1&&n.tagName.toLowerCase()!==\"html\";){if(n.id&&Wt(n.id)){t.unshift(`#${Ze(n.id)}`);break}let o=n.tagName.toLowerCase(),r=n.parentElement;if(r){let i=Array.from(r.children).filter(s=>s.tagName===n.tagName);i.length>1&&(o+=`:nth-of-type(${i.indexOf(n)+1})`)}t.unshift(o),n=r}return t.join(\" > \")}function Ge(e){if(!e)return null;try{return document.querySelector(e)}catch{return null}}function Wt(e){return!(e.length>40||/^[:]?r[a-z0-9]+[:]?$/i.test(e)||/^(radix|headlessui|mui|react-aria)[-:]/i.test(e))}function Yt(e){for(let t of Array.from(e.classList))if(!(/^[a-z0-9_-]*[a-f0-9]{6,}$/i.test(t)&&/\\d/.test(t))&&!t.startsWith(\"cf-\"))return t;return e.classList[0]??null}function Ze(e){return typeof CSS<\"u\"&&typeof CSS.escape==\"function\"?CSS.escape(e):e.replace(/([^\\w-])/g,\"\\\\$1\")}function Yn(e){let t=Array.from(e.classList).filter(n=>!n.startsWith(\"cf-\"));return t.length?t.join(\" \"):void 0}function Vn(e){let t=window.getComputedStyle(e),n=[];for(let o of jn){let r=t.getPropertyValue(o);r&&r!==\"none\"&&r!==\"normal\"&&r!==\"auto\"&&n.push(`${o}: ${r};`)}return n.length?n.join(`\n`):void 0}function qn(e){let t=[];for(let o of Hn){let r=e.getAttribute(o);r!==null&&r!==\"\"&&t.push(`${o}=\"${r}\"`)}let n=Zn(e);return n&&t.push(`text=\"${Je(n,60)}\"`),t.length?t.join(\" \"):void 0}function Kn(e){let t=(e.textContent??\"\").replace(/\\s+/g,\" \").trim();if(t)return Je(t,200)}function Xn(e){let t=[];e.parentElement&&t.push(`parent: ${Xe(e.parentElement)}`);let n=e.previousElementSibling;n&&t.push(`prev: ${Xe(n)}`);let o=e.nextElementSibling;return o&&t.push(`next: ${Xe(o)}`),t.length?t.join(\" | \"):void 0}function Xe(e){let t=e.tagName.toLowerCase(),n=Yt(e),o=(e.textContent??\"\").replace(/\\s+/g,\" \").trim().slice(0,30);return`${t}${n?`.${n}`:\"\"}${o?` \"${o}\"`:\"\"}`}function Zn(e){let t=\"\";for(let n of Array.from(e.childNodes))n.nodeType===3&&(t+=n.textContent??\"\");return t.replace(/\\s+/g,\" \").trim()}function Gn(e){let t=Object.keys(e).find(f=>f.startsWith(\"__reactFiber$\")||f.startsWith(\"__reactInternalInstance$\"));if(!t)return;let n=e[t],o=[],r,i=0;for(;n&&i<30;){let f=n.type,l=typeof f==\"function\"?f.displayName??f.name:void 0;if(l&&/^[A-Z]/.test(l)&&!o.includes(l)&&(o.push(l),!r&&n.memoizedProps&&(r=n.memoizedProps),o.length>=3))break;n=n.return,i++}if(!o.length)return;let s=o[0],c=r?Jn(r):\"\";return c?`${s} (${c})`:s}function Jn(e){let t=[];for(let[n,o]of Object.entries(e))if(n!==\"children\"&&(typeof o==\"string\"?t.push(`${n}=${JSON.stringify(Je(o,40))}`):(typeof o==\"number\"||typeof o==\"boolean\")&&t.push(`${n}=${o}`),t.length>=5))break;return t.join(\", \")}function Qn(e){let t=e,n=0;for(;t&&n<20;){if(window.getComputedStyle(t).position===\"fixed\")return!0;t=t.parentElement,n++}return!1}function Je(e,t){return e.length>t?`${e.slice(0,t-1)}\\u2026`:e}function eo(e){return Math.max(0,Math.min(100,Math.round(e*10)/10))}var Qe=null,Vt=!1,qt=0;function to(e){let t=Date.now();t-qt<120||(qt=t,B(\"presence.cursor\",{id:L.value.id??\"human\",label:L.value.displayName??\"You\",kind:L.value.kind,x:e.clientX/window.innerWidth*100,y:e.clientY+window.scrollY}))}function Kt(e){Qe=e}function et(e){return Qe?e.composedPath().includes(Qe):!1}function Xt(e){return!(e instanceof Element)||e.tagName===\"HTML\"||e.tagName===\"BODY\"?null:e}function no(e){if(et(e)||to(e),A.value!==\"feedback\"||P.value){T.value=null;return}if(et(e)){T.value=null;return}if(E.value===\"text\"){T.value=null;return}let t=Xt(e.target);if(!t){T.value=null;return}let n=t.getBoundingClientRect();T.value={top:n.top,left:n.left,width:n.width,height:n.height}}function oo(e){if(A.value!==\"feedback\"||et(e)||E.value===\"text\"||P.value)return;let t=Xt(e.target);if(t){if(e.preventDefault(),e.stopPropagation(),E.value===\"multi\"){ao(t);return}tt(Te(t))}}function ro(){if(A.value!==\"feedback\"||E.value!==\"text\"||P.value)return;let e=window.getSelection(),t=e?.toString().trim();if(!t||!e||e.rangeCount===0)return;let n=e.getRangeAt(0),o=n.commonAncestorContainer.nodeType===1?n.commonAncestorContainer:n.commonAncestorContainer.parentElement;if(!o)return;let r=Te(o);tt({...r,selectedText:t})}function io(e){if(e.key===\"Escape\"){if(P.value){P.value=null;return}if($.value.length){$.value=[],T.value=null;return}A.value===\"feedback\"&&(A.value=\"view\",T.value=null)}}function ao(e){let t=$.value;$.value=t.includes(e)?t.filter(n=>n!==e):[...t,e]}function Zt(){let e=$.value;if(!e.length)return;let t=Te(e[0]),n=e.map(r=>{let i=r.getBoundingClientRect();return{x:i.left+window.scrollX,y:i.top+window.scrollY,width:i.width,height:i.height}}),o=e.map(r=>r.tagName.toLowerCase()).join(\", \");tt({...t,isMultiSelect:!0,elementBoundingBoxes:n,nearbyElements:`${e.length} elements: ${o}`})}function tt(e){$.value=[],T.value=null,P.value=e}function Gt(){Vt||(Vt=!0,document.addEventListener(\"mousemove\",no,!0),document.addEventListener(\"click\",oo,!0),document.addEventListener(\"mouseup\",ro,!0),document.addEventListener(\"keydown\",io,!0))}var Jt=\"annotations-v1-host\",so=`\n:host {\n all: initial;\n contain: layout style;\n font-family: -apple-system, \"SF Pro Text\", system-ui, sans-serif;\n font-size: 14px;\n line-height: 1.45;\n color: #f4f4f4;\n}\n*, *::before, *::after { box-sizing: border-box; }\nbutton { font: inherit; cursor: pointer; }\n[hidden] { display: none !important; }\n`,re=null;function Qt(){if(re&&document.contains(re.host))return re;let e=document.getElementById(Jt);e&&e.remove();let t=document.createElement(\"div\");t.id=Jt,t.style.cssText=[\"all: initial\",\"position: fixed\",\"inset: 0\",\"pointer-events: none\",\"z-index: 2147483647\"].join(\";\");let n=t.attachShadow({mode:\"closed\"}),o=document.createElement(\"style\");o.textContent=so,n.appendChild(o);let r=document.createElement(\"div\");return r.id=\"cf-app\",r.style.cssText=\"pointer-events: auto;\",n.appendChild(r),document.documentElement.appendChild(t),re={host:t,shadow:n,appRoot:r},re}function Pe(e){return`top:${e.top}px;left:${e.left}px;width:${e.width}px;height:${e.height}px;`}function en(e){let t=e.trim(),n=t.indexOf(`\n`);return n>0?t.slice(0,n):t}function tn(e,t){return e.length>t?`${e.slice(0,t-1)}\\u2026`:e}function nn(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n);return t}function on(e){let t=Ge(e.fullPath??\"\")??Ge(e.elementPath??\"\");if(t){let n=t.getBoundingClientRect();return{top:n.top-11,left:n.left-11}}return e.boundingBox?{top:e.boundingBox.y-(e.isFixed?0:window.scrollY)-11,left:e.boundingBox.x-(e.isFixed?0:window.scrollX)-11}:null}var lo=0;function u(e,t,n,o,r,i){t||(t={});var s,c,f=t;if(\"ref\"in f)for(c in f={},t)c==\"ref\"?s=t[c]:f[c]=t[c];var l={type:e,props:f,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--lo,__i:-1,__u:0,__source:r,__self:i};if(typeof e==\"function\"&&(s=e.defaultProps))for(c in s)f[c]===void 0&&(f[c]=s[c]);return m.vnode&&m.vnode(l),l}function co(e){return e===\"text\"?\"Select text on the page to annotate it.\":e===\"multi\"?\"Click elements to group them, then commit.\":\"Click any element to comment. Esc to exit.\"}function ie({label:e,on:t,onClick:n}){return u(\"button\",{class:`cf-seg-btn${t?\" on\":\"\"}`,onClick:n,children:e})}function rn(){let e=A.value===\"feedback\",t=y.value.length,n=$.value.length;return u(\"div\",{class:\"cf-toolbar\",children:[u(\"div\",{class:\"cf-toolbar-head\",children:[u(\"span\",{class:\"cf-logo-dot\"},\"dot\"),u(\"span\",{children:\"Annotations\"},\"label\"),u(\"span\",{class:\"cf-count\",children:String(t)},\"count\")]},\"head\"),u(\"div\",{class:\"cf-seg\",children:[u(ie,{label:\"View\",on:A.value===\"view\",onClick:()=>{A.value=\"view\",T.value=null,$.value=[]}},\"View\"),u(ie,{label:\"Comment\",on:e,onClick:()=>{A.value=\"feedback\"}},\"Comment\")]},\"modes\"),e?u(\"div\",{class:\"cf-seg cf-tools\",children:[u(ie,{label:\"Element\",on:E.value===\"element\",onClick:()=>{E.value=\"element\",$.value=[]}},\"Element\"),u(ie,{label:\"Text\",on:E.value===\"text\",onClick:()=>{E.value=\"text\",$.value=[]}},\"Text\"),u(ie,{label:\"Multi\",on:E.value===\"multi\",onClick:()=>{E.value=\"multi\"}},\"Multi\")]},\"tools\"):null,e&&E.value===\"multi\"&&n?u(\"button\",{class:\"cf-btn cf-btn-primary cf-commit\",onClick:Zt,children:`Comment ${n} element${n===1?\"\":\"s\"}`},\"commit\"):null,e?u(\"div\",{class:\"cf-hint\",children:co(E.value)},\"hint\"):null]},\"toolbar\")}var Q={blocking:\"#ef4444\",important:\"#f59e0b\",suggestion:\"#3ecf8e\"},an=\"#a78bfa\",sn=[\"fix\",\"change\",\"question\",\"approve\"],ln=[\"blocking\",\"important\",\"suggestion\"],cn=\"#8b94a3\",nt=[\"#a78bfa\",\"#3ecf8e\",\"#f59e0b\",\"#38bdf8\",\"#f472b6\"];function un({a:e,index:t}){let n=on(e);if(!n)return null;let o=e.severity?Q[e.severity]:an,r=e.status===\"resolved\"||e.status===\"dismissed\";return u(\"button\",{class:`cf-pin${r?\" resolved\":\"\"}${e.author?.kind===\"agent\"?\" agent\":\"\"}`,style:`top:${n.top}px;left:${n.left}px;--cf-pin:${o};`,title:en(e.comment),onClick:()=>{M.value=M.value===e.id?null:e.id},children:e.author?.kind===\"agent\"?\"\\u2605\":String(t)})}function fn({el:e}){let t=e.getBoundingClientRect();return u(\"div\",{class:\"cf-multi-box\",style:Pe({top:t.top,left:t.left,width:t.width,height:t.height})})}function dn({c:e}){let t=e.x/100*window.innerWidth,n=e.y-window.scrollY,o=e.color??(e.kind===\"agent\"?nt[Math.abs(nn(e.id))%nt.length]:\"#ffffff\");return u(\"div\",{class:`cf-cursor cf-cursor-${e.kind}`,style:`top:${n}px;left:${t}px;--cf-cursor:${o};`,children:[u(\"svg\",{width:\"18\",height:\"18\",viewBox:\"0 0 18 18\",class:\"cf-cursor-arrow\",children:u(\"path\",{d:\"M2 2 L2 14 L6 10 L9 16 L11 15 L8 9 L14 9 Z\",fill:o,stroke:\"rgba(0,0,0,0.35)\",\"stroke-width\":\"0.75\"})},\"arrow\"),u(\"span\",{class:\"cf-cursor-label\",children:`${e.kind===\"agent\"?\"\\u{1F916} \":\"\"}${e.label}`},\"label\")]})}function pn({label:e,on:t,color:n,onClick:o}){return u(\"button\",{class:`cf-chip${t?\" on\":\"\"}`,style:t?`--cf-chip:${n};`:void 0,onClick:o,children:e})}function _n({target:e}){let[t,n]=Z(\"\"),[o,r]=Z(\"change\"),[i,s]=Z(\"important\"),c=()=>{let d=t.trim();d&&(V.addAnnotation({...e,comment:d,intent:o,severity:i,kind:\"feedback\",author:L.value}),P.value=null)},f=()=>{P.value=null},l=e.isMultiSelect?`${e.elementBoundingBoxes?.length??0} elements`:e.selectedText?`\"${tn(e.selectedText,40)}\"`:`<${e.element}>`;return u(\"div\",{class:\"cf-popup cf-composer\",children:[u(\"div\",{class:\"cf-popup-head\",children:[u(\"span\",{class:\"cf-popup-target\",children:l},\"t\"),u(\"button\",{class:\"cf-icon-btn\",onClick:f,title:\"Cancel\",children:\"\\u2715\"},\"x\")]},\"head\"),u(\"textarea\",{class:\"cf-textarea\",placeholder:\"Describe the change\\u2026 (Markdown supported)\",autofocus:!0,value:t,onInput:d=>n(d.target.value),onKeyDown:d=>{(d.metaKey||d.ctrlKey)&&d.key===\"Enter\"&&c()}},\"ta\"),u(\"div\",{class:\"cf-field\",children:[u(\"span\",{class:\"cf-field-label\",children:\"Intent\"},\"l\"),u(\"div\",{class:\"cf-chipset\",children:sn.map(d=>u(pn,{label:d,on:o===d,color:cn,onClick:()=>r(d)},d))},\"g\")]},\"intent\"),u(\"div\",{class:\"cf-field\",children:[u(\"span\",{class:\"cf-field-label\",children:\"Severity\"},\"l\"),u(\"div\",{class:\"cf-chipset\",children:ln.map(d=>u(pn,{label:d,on:i===d,color:Q[d],onClick:()=>s(d)},d))},\"g\")]},\"sev\"),u(\"div\",{class:\"cf-popup-actions\",children:[u(\"button\",{class:\"cf-btn\",onClick:f,children:\"Cancel\"},\"c\"),u(\"button\",{class:\"cf-btn cf-btn-primary\",disabled:!t.trim(),onClick:c,children:\"Comment\"},\"s\")]},\"actions\")]})}function mn({role:e,name:t,content:n}){return u(\"div\",{class:`cf-msg cf-msg-${e}`,children:[u(\"div\",{class:\"cf-msg-meta\",children:[u(\"span\",{class:`cf-avatar cf-avatar-${e}`,children:e===\"agent\"?\"\\u{1F916}\":\"\\u{1F9D1}\"},\"av\"),u(\"span\",{class:\"cf-msg-name\",children:t},\"n\")]},\"meta\"),u(\"div\",{class:\"cf-msg-body\",children:n},\"c\")]})}function hn({id:e}){let[t,n]=Z(\"\"),o=y.value.find(i=>i.id===e);if(!o)return null;let r=()=>{let i=t.trim();i&&(V.replyToAnnotation(e,{role:L.value.kind,content:i}),n(\"\"))};return u(\"div\",{class:\"cf-popup cf-thread\",children:[u(\"div\",{class:\"cf-popup-head\",children:[u(\"span\",{class:\"cf-popup-target\",children:`<${o.element}>`},\"t\"),o.severity?u(\"span\",{class:\"cf-tag\",style:`--cf-tag:${Q[o.severity]};`,children:o.severity},\"sev\"):null,u(\"button\",{class:\"cf-icon-btn\",onClick:()=>M.value=null,title:\"Close\",children:\"\\u2715\"},\"x\")]},\"head\"),u(\"div\",{class:\"cf-thread-body\",children:[u(mn,{role:o.author?.kind??\"human\",name:o.author?.displayName??\"You\",content:o.comment},\"root\"),(o.thread??[]).map(i=>u(mn,{role:i.role,name:i.role===\"agent\"?\"Agent\":\"You\",content:i.content},i.id))]},\"body\"),u(\"div\",{class:\"cf-thread-compose\",children:[u(\"textarea\",{class:\"cf-textarea cf-textarea-sm\",placeholder:\"Reply\\u2026\",value:t,onInput:i=>n(i.target.value),onKeyDown:i=>{(i.metaKey||i.ctrlKey)&&i.key===\"Enter\"&&r()}},\"ta\"),u(\"div\",{class:\"cf-thread-actions\",children:[o.status!==\"resolved\"?u(\"button\",{class:\"cf-btn cf-btn-ghost\",onClick:()=>V.resolveAnnotation(e,L.value.kind),children:\"Resolve\"},\"resolve\"):u(\"span\",{class:\"cf-resolved-tag\",children:\"\\u2713 resolved\"},\"resolved\"),u(\"button\",{class:\"cf-btn cf-btn-primary\",disabled:!t.trim(),onClick:r,children:\"Reply\"},\"send\")]},\"row\")]},\"compose\")]})}var vn=`\n.cf-overlay {\n position: fixed;\n inset: 0;\n pointer-events: none;\n font-family: -apple-system, \"SF Pro Text\", system-ui, sans-serif;\n font-size: 13px;\n color: #f4f4f5;\n --cf-bg: rgba(18, 18, 22, 0.96);\n --cf-border: rgba(255, 255, 255, 0.1);\n --cf-muted: rgba(255, 255, 255, 0.55);\n --cf-accent: #a78bfa;\n}\n.cf-overlay[data-theme=\"light\"] {\n color: #18181b;\n --cf-bg: rgba(252, 252, 253, 0.97);\n --cf-border: rgba(0, 0, 0, 0.1);\n --cf-muted: rgba(0, 0, 0, 0.5);\n}\n\n/* Hover highlight + multi-select boxes */\n.cf-hover {\n position: fixed;\n pointer-events: none;\n border: 2px solid var(--cf-accent);\n background: rgba(167, 139, 250, 0.1);\n border-radius: 4px;\n box-shadow: 0 0 0 1px rgba(167, 139, 250, 0.4);\n transition: top .06s ease, left .06s ease, width .06s ease, height .06s ease;\n z-index: 1;\n}\n.cf-multi-box {\n position: fixed;\n pointer-events: none;\n border: 2px solid #3ecf8e;\n background: rgba(62, 207, 142, 0.12);\n border-radius: 4px;\n z-index: 1;\n animation: cf-multi-pulse 1.4s ease-in-out infinite;\n}\n@keyframes cf-multi-pulse {\n 0%, 100% { box-shadow: 0 0 0 0 rgba(62,207,142,0.0); }\n 50% { box-shadow: 0 0 0 3px rgba(62,207,142,0.25); }\n}\n\n/* Live presence cursors (multi-cursor collaboration) */\n.cf-cursor {\n position: fixed;\n z-index: 6;\n pointer-events: none;\n display: flex;\n align-items: flex-start;\n gap: 4px;\n /* Glide to new positions so multiple actors read as \"live\". */\n transition: top .12s ease, left .12s ease;\n will-change: top, left;\n}\n.cf-cursor-arrow { display: block; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.4)); }\n.cf-cursor-label {\n transform: translateY(2px);\n background: var(--cf-cursor, #a78bfa);\n color: #0b0b0f;\n font: 700 11px -apple-system, system-ui;\n padding: 2px 7px;\n border-radius: 8px;\n white-space: nowrap;\n box-shadow: 0 2px 8px rgba(0,0,0,0.35);\n}\n.cf-cursor-human .cf-cursor-label { color: #18181b; }\n.cf-cursor-agent .cf-cursor-label { color: #0b0b0f; }\n\n/* Pins */\n.cf-pin {\n position: fixed;\n width: 22px; height: 22px;\n border-radius: 50% 50% 50% 2px;\n background: var(--cf-pin, #a78bfa);\n color: #fff;\n border: 2px solid rgba(255,255,255,0.9);\n font: 700 11px -apple-system, system-ui;\n display: flex; align-items: center; justify-content: center;\n cursor: pointer;\n pointer-events: auto;\n box-shadow: 0 2px 8px rgba(0,0,0,0.35);\n z-index: 3;\n transition: transform .12s cubic-bezier(.34,1.56,.64,1);\n padding: 0;\n /* Pop in when a pin first renders so new annotations are obvious. */\n animation: cf-pin-pop .32s cubic-bezier(.34,1.56,.64,1) both;\n}\n.cf-pin:hover { transform: scale(1.2); }\n.cf-pin.resolved { opacity: 0.45; }\n/* Agent-pushed pins pulse a ring so reviewers spot what the agent added. */\n.cf-pin.agent { border-style: dashed; }\n.cf-pin.agent::after {\n content: \"\";\n position: absolute; inset: -4px;\n border-radius: inherit;\n border: 2px solid var(--cf-pin, #a78bfa);\n animation: cf-pin-ring 1.6s ease-out 3;\n pointer-events: none;\n}\n\n@keyframes cf-pin-pop {\n 0% { transform: scale(0); opacity: 0; }\n 60% { transform: scale(1.25); opacity: 1; }\n 100% { transform: scale(1); opacity: 1; }\n}\n@keyframes cf-pin-ring {\n 0% { transform: scale(1); opacity: .7; }\n 100% { transform: scale(2.4); opacity: 0; }\n}\n\n/* Toolbar */\n.cf-toolbar {\n position: fixed;\n left: 16px; bottom: 16px;\n pointer-events: auto;\n background: var(--cf-bg);\n border: 1px solid var(--cf-border);\n border-radius: 14px;\n padding: 10px;\n display: flex; flex-direction: column; gap: 8px;\n backdrop-filter: blur(16px) saturate(140%);\n box-shadow: 0 16px 48px rgba(0,0,0,0.5);\n min-width: 220px;\n z-index: 4;\n}\n.cf-toolbar-head {\n display: flex; align-items: center; gap: 7px;\n font-weight: 700; letter-spacing: 0.02em;\n}\n.cf-logo-dot {\n width: 8px; height: 8px; border-radius: 50%;\n background: var(--cf-accent);\n box-shadow: 0 0 10px var(--cf-accent);\n}\n.cf-count {\n margin-left: auto;\n font: 700 11px -apple-system, system-ui;\n color: var(--cf-muted);\n background: rgba(255,255,255,0.08);\n padding: 1px 7px; border-radius: 8px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-count { background: rgba(0,0,0,0.06); }\n\n.cf-seg {\n display: flex; gap: 2px;\n background: rgba(255,255,255,0.06);\n border-radius: 9px; padding: 2px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-seg { background: rgba(0,0,0,0.05); }\n.cf-seg-btn {\n flex: 1; border: none; background: transparent; color: var(--cf-muted);\n padding: 5px 10px; border-radius: 7px; font: 600 12px -apple-system, system-ui;\n}\n.cf-seg-btn.on {\n background: var(--cf-accent); color: #fff;\n box-shadow: 0 1px 4px rgba(0,0,0,0.3);\n}\n.cf-tools .cf-seg-btn.on { background: rgba(255,255,255,0.16); color: #fff; }\n.cf-overlay[data-theme=\"light\"] .cf-tools .cf-seg-btn.on { background: rgba(0,0,0,0.12); color: #111; }\n.cf-hint { font-size: 11px; color: var(--cf-muted); padding: 0 2px; }\n.cf-commit { width: 100%; }\n\n/* Buttons */\n.cf-btn {\n border: 1px solid var(--cf-border); background: transparent; color: inherit;\n padding: 6px 12px; border-radius: 8px; font: 600 12px -apple-system, system-ui;\n}\n.cf-btn:hover { background: rgba(255,255,255,0.06); }\n.cf-overlay[data-theme=\"light\"] .cf-btn:hover { background: rgba(0,0,0,0.04); }\n.cf-btn-primary {\n background: var(--cf-accent); border-color: var(--cf-accent); color: #fff;\n}\n.cf-btn-primary:hover { background: #9173f0; }\n.cf-btn-primary:disabled { opacity: 0.4; cursor: not-allowed; }\n.cf-btn-ghost { border-color: transparent; color: var(--cf-muted); }\n\n/* Popups (composer + thread) */\n.cf-popup {\n position: fixed;\n left: 16px; bottom: 92px;\n width: 320px;\n pointer-events: auto;\n background: var(--cf-bg);\n border: 1px solid var(--cf-border);\n border-radius: 14px;\n padding: 12px;\n display: flex; flex-direction: column; gap: 10px;\n backdrop-filter: blur(16px) saturate(140%);\n box-shadow: 0 16px 48px rgba(0,0,0,0.55);\n z-index: 5;\n animation: cf-rise .2s cubic-bezier(.16,1,.3,1) both;\n}\n@keyframes cf-rise {\n from { transform: translateY(10px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n.cf-popup-head {\n display: flex; align-items: center; gap: 8px;\n}\n.cf-popup-target {\n font: 600 12px ui-monospace, \"SF Mono\", monospace;\n color: var(--cf-accent);\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n}\n.cf-icon-btn {\n margin-left: auto; border: none; background: transparent;\n color: var(--cf-muted); font-size: 13px; cursor: pointer;\n width: 22px; height: 22px; border-radius: 6px;\n}\n.cf-icon-btn:hover { background: rgba(255,255,255,0.08); }\n\n.cf-textarea {\n width: 100%; min-height: 72px; resize: vertical;\n background: rgba(255,255,255,0.04);\n border: 1px solid var(--cf-border); border-radius: 9px;\n padding: 8px 10px; color: inherit; font: 400 13px -apple-system, system-ui;\n line-height: 1.45;\n}\n.cf-overlay[data-theme=\"light\"] .cf-textarea { background: rgba(0,0,0,0.03); }\n.cf-textarea:focus { outline: none; border-color: var(--cf-accent); }\n.cf-textarea-sm { min-height: 48px; }\n\n.cf-field { display: flex; flex-direction: column; gap: 5px; }\n.cf-field-label {\n font: 700 10px -apple-system, system-ui; letter-spacing: 0.06em;\n text-transform: uppercase; color: var(--cf-muted);\n}\n.cf-chipset { display: flex; flex-wrap: wrap; gap: 5px; }\n.cf-chip {\n border: 1px solid var(--cf-border); background: transparent; color: var(--cf-muted);\n padding: 4px 10px; border-radius: 20px; font: 600 11px -apple-system, system-ui;\n text-transform: capitalize;\n}\n.cf-chip.on {\n background: var(--cf-chip, var(--cf-accent));\n border-color: var(--cf-chip, var(--cf-accent));\n color: #fff;\n}\n.cf-popup-actions { display: flex; gap: 8px; justify-content: flex-end; }\n\n/* Thread */\n.cf-thread-body {\n display: flex; flex-direction: column; gap: 12px;\n max-height: 280px; overflow-y: auto; padding-right: 2px;\n}\n.cf-msg { display: flex; flex-direction: column; gap: 3px; }\n.cf-msg-meta { display: flex; align-items: center; gap: 6px; }\n.cf-avatar { font-size: 12px; }\n.cf-msg-name {\n font: 700 11px -apple-system, system-ui; color: var(--cf-muted);\n}\n.cf-msg-body {\n font-size: 13px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;\n background: rgba(255,255,255,0.04); border-radius: 9px; padding: 7px 10px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-msg-body { background: rgba(0,0,0,0.03); }\n.cf-msg-agent .cf-msg-body { border-left: 2px solid var(--cf-accent); }\n.cf-thread-compose { display: flex; flex-direction: column; gap: 8px; }\n.cf-thread-actions { display: flex; gap: 8px; align-items: center; }\n.cf-thread-actions .cf-btn-primary { margin-left: auto; }\n.cf-resolved-tag { font: 600 11px -apple-system, system-ui; color: #3ecf8e; }\n.cf-tag {\n font: 700 9px -apple-system, system-ui; text-transform: uppercase;\n letter-spacing: 0.05em; padding: 2px 6px; border-radius: 5px;\n background: var(--cf-tag, var(--cf-accent)); color: #fff;\n}\n\n/* Respect reduced-motion: keep the UI usable, drop the motion. */\n@media (prefers-reduced-motion: reduce) {\n .cf-pin, .cf-popup, .cf-multi-box { animation: none !important; }\n .cf-pin.agent::after { display: none; }\n}\n`;function gn(){let e=Y.value===\"auto\"?\"dark\":Y.value;return Ee.value,u(\"div\",{class:\"cf-overlay\",\"data-theme\":e,children:[u(\"style\",{children:vn},\"styles\"),T.value&&!P.value?u(\"div\",{class:\"cf-hover\",style:Pe(T.value)},\"hover\"):null,$.value.map((t,n)=>u(fn,{el:t},`multi-${n}`)),u(\"div\",{children:y.value.map((t,n)=>u(un,{a:t,index:n+1},t.id))},\"pins\"),u(\"div\",{children:N.value.map(t=>u(dn,{c:t},`cursor-${t.id}`))},\"cursors\"),u(rn,{}),P.value?u(_n,{target:P.value},\"composer\"):null,M.value?u(hn,{id:M.value},\"thread\"):null]})}var yn=!1;function bn(e={}){zt(e),e.author&&(L.value=e.author),e.mode&&(A.value=e.mode),e.theme&&(Y.value=e.theme),xn(),Ht.value=!0,console.info(\"[annotations v1] ready on\",location.href)}function xn(){if(yn||typeof document>\"u\")return;if(!document.documentElement){document.addEventListener(\"DOMContentLoaded\",xn,{once:!0});return}yn=!0;let{host:e,appRoot:t}=Qt();Kt(e),Gt(),gt(Ue(gn,{}),t);let n=()=>{Ee.value++};window.addEventListener(\"scroll\",n,{passive:!0,capture:!0}),window.addEventListener(\"resize\",n,{passive:!0})}var uo=Object.assign({__init:bn},V);window.__annotations=uo;bn();})();\n";
5
+ "\"use strict\";(()=>{var at=Object.defineProperty;var st=(e,t,n)=>t in e?at(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var ne=(e,t,n)=>st(e,typeof t!=\"symbol\"?t+\"\":t,n);var ve=\"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";function K(e=Date.now()){let t=e,n=\"\";for(let r=0;r<10;r++)n=ve[t&31]+n,t=Math.floor(t/32);let o=\"\";for(let r=0;r<16;r++)o+=ve[Math.floor(Math.random()*32)];return n+o}var oe=class{constructor(t){ne(this,\"_value\");ne(this,\"_subs\",new Set);this._value=t}get value(){return this._value}set value(t){if(!Object.is(this._value,t)){this._value=t;for(let n of Array.from(this._subs))n(t)}}peek(){return this._value}subscribe(t){return this._subs.add(t),()=>{this._subs.delete(t)}}};function m(e){return new oe(e)}var d=m([]),g=m(\"view\"),B=m(\"dark\"),W=m(null),_=m(\"\"),ye=m(0),we=m(!1),T=m({kind:\"human\",id:\"human\",displayName:\"You\"}),w=m(\"element\"),k=m(null),b=m(null),y=m([]),x=m(null),z=m(0),E=m([]),Y=m(null),H=m(null),I=m(!0),V=m(null);function A(e,t){let n=W.value,o={type:e,timestamp:new Date().toISOString(),sessionId:_.value,sequence:++ye.value,payload:t};if(n)try{fetch(n,{method:\"POST\",headers:{\"Content-Type\":\"application/json\"},body:JSON.stringify(o),keepalive:!0}).catch(r=>console.warn(\"[annotations] webhook emit failed\",r))}catch(r){console.warn(\"[annotations] webhook emit threw synchronously\",r)}}var S={version:\"0.1.0\",schema:\"afs-1.1\",addAnnotation(e){let t=e.id??`ann_${K().slice(-12).toLowerCase()}`,n=Date.now(),o={id:t,comment:e.comment,elementPath:e.elementPath,element:e.element,x:e.x,y:e.y,timestamp:e.timestamp??n,url:e.url,boundingBox:e.boundingBox,reactComponents:e.reactComponents,cssClasses:e.cssClasses,computedStyles:e.computedStyles,accessibility:e.accessibility,nearbyText:e.nearbyText,selectedText:e.selectedText,isFixed:e.isFixed,isMultiSelect:e.isMultiSelect,fullPath:e.fullPath,nearbyElements:e.nearbyElements,elementBoundingBoxes:e.elementBoundingBoxes,intent:e.intent,severity:e.severity,kind:e.kind??\"feedback\",placement:e.placement,rearrange:e.rearrange,status:e.status??\"pending\",thread:[],author:e.author??{kind:\"agent\",id:\"agent\",displayName:\"Agent\"},createdAt:new Date(n).toISOString(),updatedAt:new Date(n).toISOString()};return d.value=[...d.value,o],A(\"annotation.created\",o),t},replyToAnnotation(e,t){if(!d.value.find(r=>r.id===e))return null;let o={id:`msg_${K().slice(-10).toLowerCase()}`,role:t.role,content:t.content,timestamp:Date.now()};return d.value=d.value.map(r=>r.id===e?{...r,thread:[...r.thread??[],o],updatedAt:new Date().toISOString()}:r),A(\"thread.message\",{annotationId:e,message:o}),o.id},updateAnnotation(e,t){let n=!1;return d.value=d.value.map(o=>o.id!==e?o:(n=!0,{...o,...t,updatedAt:new Date().toISOString()})),n&&A(\"annotation.updated\",{id:e,patch:t}),n},acknowledgeAnnotation(e){return this.updateAnnotation(e,{status:\"acknowledged\"})},resolveAnnotation(e,t=\"agent\"){return this.updateAnnotation(e,{status:\"resolved\",resolvedAt:new Date().toISOString(),resolvedBy:t})},dismissAnnotation(e){return this.updateAnnotation(e,{status:\"dismissed\"})},removeAnnotation(e){let t=d.value.length;d.value=d.value.filter(o=>o.id!==e);let n=d.value.length<t;return n&&A(\"annotation.deleted\",{id:e}),n},clearAnnotations(){let e=d.value.length;return d.value=[],x.value=null,A(\"session.updated\",{cleared:e}),e},focusAnnotation(e){let t=d.value.some(n=>n.id===e);return t&&(x.value=e),t},closeThread(){x.value=null},setCursors(e){E.value=e},setCursor(e){let t=E.value.filter(n=>n.id!==e.id);E.value=[...t,e]},removeCursor(e){let t=E.value.length;return E.value=E.value.filter(n=>n.id!==e),E.value.length<t},clearCursors(){E.value=[]},setMode(e){g.value!==e&&(g.value=e,A(\"session.updated\",{mode:e}))},getMode(){return g.value},subscribeMode(e){return g.subscribe(e)},setTheme(e){B.value=e},getAnnotations(){return d.value}};function ke(e){e.webhookUrl!==void 0&&(W.value=e.webhookUrl),_.value=e.sessionId??`cf_${K().slice(-12).toLowerCase()}`,A(\"session.created\",{sessionId:_.value,pageUrl:typeof location<\"u\"?location.href:\"\"})}var lt=[\"display\",\"position\",\"width\",\"height\",\"margin\",\"padding\",\"color\",\"background-color\",\"background\",\"font-family\",\"font-size\",\"font-weight\",\"line-height\",\"border\",\"border-radius\",\"box-shadow\",\"flex-direction\",\"justify-content\",\"align-items\",\"gap\",\"grid-template-columns\",\"z-index\",\"opacity\",\"text-align\"],ct=[\"role\",\"aria-label\",\"aria-labelledby\",\"aria-describedby\",\"aria-hidden\",\"aria-expanded\",\"aria-checked\",\"aria-selected\",\"alt\",\"title\",\"tabindex\",\"type\",\"name\",\"for\",\"href\"];function X(e){let t=e.getBoundingClientRect(),n=yt(e),o=window.scrollX,r=window.scrollY,a={x:t.left+(n?0:o),y:t.top+(n?0:r),width:t.width,height:t.height};return{element:e.tagName.toLowerCase(),elementPath:dt(e),fullPath:ut(e),x:wt((t.left+t.width/2)/window.innerWidth*100),y:n?t.top:t.top+r,url:location.href,boundingBox:a,isFixed:n,cssClasses:pt(e),computedStyles:ft(e),accessibility:mt(e),nearbyText:gt(e),nearbyElements:ht(e),reactComponents:xt(e)}}function dt(e){if(e.id&&Ee(e.id))return`#${ie(e.id)}`;let t=e.getAttribute(\"data-testid\");if(t)return`[data-testid=\"${t}\"]`;let n=e.tagName.toLowerCase(),o=Te(e);return o?`${n}.${ie(o)}`:n}function ut(e){let t=[],n=e;for(;n&&n.nodeType===1&&n.tagName.toLowerCase()!==\"html\";){if(n.id&&Ee(n.id)){t.unshift(`#${ie(n.id)}`);break}let o=n.tagName.toLowerCase(),r=n.parentElement;if(r){let a=Array.from(r.children).filter(l=>l.tagName===n.tagName);a.length>1&&(o+=`:nth-of-type(${a.indexOf(n)+1})`)}t.unshift(o),n=r}return t.join(\" > \")}function ae(e){if(!e)return null;try{return document.querySelector(e)}catch{return null}}function Ee(e){return!(e.length>40||/^[:]?r[a-z0-9]+[:]?$/i.test(e)||/^(radix|headlessui|mui|react-aria)[-:]/i.test(e))}function Te(e){for(let t of Array.from(e.classList))if(!(/^[a-z0-9_-]*[a-f0-9]{6,}$/i.test(t)&&/\\d/.test(t))&&!t.startsWith(\"cf-\"))return t;return e.classList[0]??null}function ie(e){return typeof CSS<\"u\"&&typeof CSS.escape==\"function\"?CSS.escape(e):e.replace(/([^\\w-])/g,\"\\\\$1\")}function pt(e){let t=Array.from(e.classList).filter(n=>!n.startsWith(\"cf-\"));return t.length?t.join(\" \"):void 0}function ft(e){let t=window.getComputedStyle(e),n=[];for(let o of lt){let r=t.getPropertyValue(o);r&&r!==\"none\"&&r!==\"normal\"&&r!==\"auto\"&&n.push(`${o}: ${r};`)}return n.length?n.join(`\n`):void 0}function mt(e){let t=[];for(let o of ct){let r=e.getAttribute(o);r!==null&&r!==\"\"&&t.push(`${o}=\"${r}\"`)}let n=bt(e);return n&&t.push(`text=\"${se(n,60)}\"`),t.length?t.join(\" \"):void 0}function gt(e){let t=(e.textContent??\"\").replace(/\\s+/g,\" \").trim();if(t)return se(t,200)}function ht(e){let t=[];e.parentElement&&t.push(`parent: ${re(e.parentElement)}`);let n=e.previousElementSibling;n&&t.push(`prev: ${re(n)}`);let o=e.nextElementSibling;return o&&t.push(`next: ${re(o)}`),t.length?t.join(\" | \"):void 0}function re(e){let t=e.tagName.toLowerCase(),n=Te(e),o=(e.textContent??\"\").replace(/\\s+/g,\" \").trim().slice(0,30);return`${t}${n?`.${n}`:\"\"}${o?` \"${o}\"`:\"\"}`}function bt(e){let t=\"\";for(let n of Array.from(e.childNodes))n.nodeType===3&&(t+=n.textContent??\"\");return t.replace(/\\s+/g,\" \").trim()}function xt(e){let t=Object.keys(e).find(s=>s.startsWith(\"__reactFiber$\")||s.startsWith(\"__reactInternalInstance$\"));if(!t)return;let n=e[t],o=[],r,a=0;for(;n&&a<30;){let s=n.type,h=typeof s==\"function\"?s.displayName??s.name:void 0;if(h&&/^[A-Z]/.test(h)&&!o.includes(h)&&(o.push(h),!r&&n.memoizedProps&&(r=n.memoizedProps),o.length>=3))break;n=n.return,a++}if(!o.length)return;let l=o[0],f=r?vt(r):\"\";return f?`${l} (${f})`:l}function vt(e){let t=[];for(let[n,o]of Object.entries(e))if(n!==\"children\"&&(typeof o==\"string\"?t.push(`${n}=${JSON.stringify(se(o,40))}`):(typeof o==\"number\"||typeof o==\"boolean\")&&t.push(`${n}=${o}`),t.length>=5))break;return t.join(\", \")}function yt(e){let t=e,n=0;for(;t&&n<20;){if(window.getComputedStyle(t).position===\"fixed\")return!0;t=t.parentElement,n++}return!1}function se(e,t){return e.length>t?`${e.slice(0,t-1)}\\u2026`:e}function wt(e){return Math.max(0,Math.min(100,Math.round(e*10)/10))}var le=null,Ae=!1,Se=0;function kt(e){let t=Date.now();t-Se<120||(Se=t,A(\"presence.cursor\",{id:T.value.id??\"human\",label:T.value.displayName??\"You\",kind:T.value.kind,x:e.clientX/window.innerWidth*100,y:e.clientY+window.scrollY}))}function Ce(e){le=e}function ce(e){return le?e.composedPath().includes(le):!1}function Le(e){return!(e instanceof Element)||e.tagName===\"HTML\"||e.tagName===\"BODY\"?null:e}function Et(e){if(ce(e)||kt(e),g.value!==\"feedback\"||b.value){k.value=null;return}if(ce(e)){k.value=null;return}let t=Le(e.target);if(!t){k.value=null;return}let n=t.getBoundingClientRect();k.value={top:n.top,left:n.left,width:n.width,height:n.height}}function Tt(e){if(g.value!==\"feedback\"||ce(e)||w.value===\"text\"||b.value)return;let t=Le(e.target);if(t){if(e.preventDefault(),e.stopPropagation(),w.value===\"multi\"){Ct(t);return}de(X(t))}}function At(){if(g.value!==\"feedback\"||w.value!==\"text\"||b.value)return;let e=window.getSelection(),t=e?.toString().trim();if(!t||!e||e.rangeCount===0)return;let n=e.getRangeAt(0),o=n.commonAncestorContainer.nodeType===1?n.commonAncestorContainer:n.commonAncestorContainer.parentElement;if(!o)return;let r=X(o),a=n.getBoundingClientRect(),l=a.width||a.height?{x:a.left+(r.isFixed?0:window.scrollX),y:a.top+(r.isFixed?0:window.scrollY),width:a.width,height:a.height}:r.boundingBox;de({...r,selectedText:t,boundingBox:l,x:(a.left+a.width/2)/window.innerWidth*100,y:r.isFixed?a.top:a.top+window.scrollY})}function St(e){if(e.key===\"Escape\"){if(b.value){b.value=null;return}if(y.value.length){y.value=[],k.value=null;return}g.value===\"feedback\"&&(g.value=\"view\",k.value=null)}}function Ct(e){let t=y.value;y.value=t.includes(e)?t.filter(n=>n!==e):[...t,e]}function Me(){let e=y.value;if(!e.length)return;let t=X(e[0]),n=e.map(r=>{let a=r.getBoundingClientRect();return{x:a.left+window.scrollX,y:a.top+window.scrollY,width:a.width,height:a.height}}),o=e.map(r=>r.tagName.toLowerCase()).join(\", \");de({...t,isMultiSelect:!0,elementBoundingBoxes:n,nearbyElements:`${e.length} elements: ${o}`})}function de(e){y.value=[],k.value=null,b.value=e}function $e(){Ae||(Ae=!0,document.addEventListener(\"mousemove\",Et,!0),document.addEventListener(\"click\",Tt,!0),document.addEventListener(\"mouseup\",At,!0),document.addEventListener(\"keydown\",St,!0))}var Be=\"annotations-v1-host\",Lt=`\n:host {\n all: initial;\n contain: layout style;\n font-family: -apple-system, \"SF Pro Text\", system-ui, sans-serif;\n font-size: 14px;\n line-height: 1.45;\n color: #f4f4f4;\n}\n*, *::before, *::after { box-sizing: border-box; }\nbutton { font: inherit; cursor: pointer; }\n[hidden] { display: none !important; }\n`,F=null;function Pe(){if(F&&document.contains(F.host))return F;let e=document.getElementById(Be);e&&e.remove();let t=document.createElement(\"div\");t.id=Be,t.style.cssText=[\"all: initial\",\"position: fixed\",\"inset: 0\",\"pointer-events: none\",\"z-index: 2147483647\"].join(\";\");let n=t.attachShadow({mode:\"closed\"}),o=document.createElement(\"style\");o.textContent=Lt,n.appendChild(o);let r=document.createElement(\"div\");return r.id=\"cf-app\",r.style.cssText=\"pointer-events: auto;\",n.appendChild(r),document.documentElement.appendChild(t),F={host:t,shadow:n,appRoot:r},F}function D(e){return`top:${e.top}px;left:${e.left}px;width:${e.width}px;height:${e.height}px;`}function G(e){let t=e.trim(),n=t.indexOf(`\n`);return n>0?t.slice(0,n):t}function Ie(e,t){return e.length>t?`${e.slice(0,t-1)}\\u2026`:e}function J(e,t){e.style.position=\"fixed\",e.style.left=`${t.left}px`,e.style.top=`${t.top+t.height+10}px`,e.style.right=\"auto\",e.style.bottom=\"auto\",requestAnimationFrame(()=>{let n=e.getBoundingClientRect();if(!n.width)return;let o=Math.max(8,Math.min(t.left,window.innerWidth-n.width-8)),r=t.top+t.height+10;r+n.height>window.innerHeight-8&&(r=t.top-n.height-10),r=Math.max(8,Math.min(r,window.innerHeight-n.height-8)),e.style.left=`${o}px`,e.style.top=`${r}px`,Mt(e)})}function Mt(e){if(typeof e.animate!=\"function\")return;let n=e.closest(\".cf-overlay\")?.querySelector(\".cf-fab, .cf-toolbar\");if(!n)return;let o=n.getBoundingClientRect(),r=e.getBoundingClientRect();if(!o.width||!r.width)return;let a=o.left+o.width/2-(r.left+r.width/2),l=o.top+o.height/2-(r.top+r.height/2),f=Math.max(.08,o.width/r.width),s=Math.max(.08,o.height/r.height);e.classList.add(\"cf-morph\"),e.style.transformOrigin=\"center center\",e.animate([{transform:`translate(${a}px, ${l}px) scale(${f}, ${s})`,opacity:.25},{transform:\"translate(0, 0) scale(1, 1)\",opacity:1}],{duration:360,easing:\"cubic-bezier(.34,1.3,.5,1)\",fill:\"both\"}).addEventListener(\"finish\",()=>{e.style.transform=\"\"})}function Z(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n);return t}function Q(e){let t=ae(e.fullPath??\"\")??ae(e.elementPath??\"\");if(t){let n=t.getBoundingClientRect();return{top:n.top,left:n.left,width:n.width,height:n.height}}return e.boundingBox?{top:e.boundingBox.y-(e.isFixed?0:window.scrollY),left:e.boundingBox.x-(e.isFixed?0:window.scrollX),width:e.boundingBox.width,height:e.boundingBox.height}:null}var $t=\"http://www.w3.org/2000/svg\";function Re(e,t){for(let[n,o]of Object.entries(t))if(o!=null){if(n===\"class\"){e.setAttribute(\"class\",String(o));continue}if(n===\"style\"){e.setAttribute(\"style\",String(o));continue}if(n===\"dataset\"){let r=o;if(e instanceof HTMLElement)for(let[a,l]of Object.entries(r))e.dataset[a]=l;continue}if(n.startsWith(\"on\")&&typeof o==\"function\"){let r=n.slice(2).toLowerCase();e.addEventListener(r,o);continue}if(typeof o==\"boolean\"){o&&e.setAttribute(n,\"\");continue}e.setAttribute(n,String(o))}}function ue(e,t){for(let n of t)if(!(n===null||n===!1||n===void 0)){if(Array.isArray(n)){ue(e,n);continue}if(n instanceof Node){e.appendChild(n);continue}e.appendChild(document.createTextNode(String(n)))}}function i(e,t,...n){let o=document.createElement(e);return t&&Re(o,t),ue(o,n),o}function pe(e,t,...n){let o=document.createElementNS($t,e);return t&&Re(o,t),ue(o,n),o}function R(e=\"\"){let t=i(\"span\",{class:`cf-brand${e?` ${e}`:\"\"}`}),n=V.value;return n?t.innerHTML=n:t.appendChild(i(\"span\",{class:\"cf-logo-dot\"})),t}var C=8,ee=(e,t,n)=>Math.max(t,Math.min(e,n));function Ne(e,t,n){t.addEventListener(\"pointerdown\",o=>{if(o.target?.closest(\"button\"))return;o.preventDefault();let r=e.getBoundingClientRect(),a=o.clientX-r.left,l=o.clientY-r.top,f=o.clientX,s=o.clientY,h=r.left,c=r.top,u=!1;t.setPointerCapture(o.pointerId),e.classList.add(\"cf-dragging\");let v=L=>{Math.abs(L.clientX-f)+Math.abs(L.clientY-s)>4&&(u=!0),h=ee(L.clientX-a,C,window.innerWidth-e.offsetWidth-C),c=ee(L.clientY-l,C,window.innerHeight-e.offsetHeight-C),e.style.left=`${h}px`,e.style.top=`${c}px`,e.style.right=\"auto\",e.style.bottom=\"auto\"},M=()=>{e.classList.remove(\"cf-dragging\"),t.removeEventListener(\"pointermove\",v),t.removeEventListener(\"pointerup\",M),u?Y.value={x:h,y:c}:n?.()};t.addEventListener(\"pointermove\",v),t.addEventListener(\"pointerup\",M)})}function He(e){let t=d.value;if(!t.length)return;let n=(e%t.length+t.length)%t.length,o=t[n],r=null;try{r=o.fullPath&&document.querySelector(o.fullPath)||(o.elementPath?document.querySelector(o.elementPath):null)}catch{}r?.scrollIntoView({behavior:\"smooth\",block:\"center\"}),x.value=o.id}function Bt(e){return e===\"text\"?\"Select text on the page to annotate it.\":e===\"multi\"?\"Click elements to group them, then commit.\":\"Click any element to comment. Esc to exit.\"}function U(e,t,n){return i(\"button\",{class:`cf-seg-btn${t?\" on\":\"\"}`,onClick:n},e)}function Oe(){let e=Y.value;return e?`left:${e.x}px;top:${e.y}px;right:auto;bottom:auto;`:void 0}function je(e){requestAnimationFrame(()=>{let t=e.getBoundingClientRect();if(!t.width||!t.height)return;let n=ee(t.left,C,Math.max(C,window.innerWidth-t.width-C)),o=ee(t.top,C,Math.max(C,window.innerHeight-t.height-C));(Math.abs(n-t.left)>.5||Math.abs(o-t.top)>.5)&&(e.style.left=`${n}px`,e.style.top=`${o}px`,e.style.right=\"auto\",e.style.bottom=\"auto\")})}function _e(){let e=d.value.length;if(I.value){let c=i(\"div\",{class:\"cf-fab\",role:\"button\",tabindex:\"0\",title:\"Open annotations \\xB7 drag to move\",style:Oe()});return c.appendChild(R()),e>0&&c.appendChild(i(\"span\",{class:\"cf-fab-badge\"},e>99?\"99+\":String(e))),c.addEventListener(\"keydown\",u=>{(u.key===\"Enter\"||u.key===\" \")&&(u.preventDefault(),I.value=!1)}),Ne(c,c,()=>{I.value=!1}),je(c),c}let t=g.value===\"feedback\",n=y.value.length,o=i(\"div\",{class:\"cf-toolbar-head\",title:\"Drag to move\"},i(\"span\",{class:\"cf-grip\",\"aria-hidden\":\"true\"},\"\\u283F\"),i(\"button\",{class:\"cf-collapse\",title:\"Collapse to icon\",onClick:()=>I.value=!0},R()),i(\"div\",{class:\"cf-seg\"},U(\"View\",g.value===\"view\",()=>{g.value=\"view\",k.value=null,y.value=[]}),U(\"Comment\",t,()=>{g.value=\"feedback\"})),i(\"span\",{class:\"cf-count\"},String(e)),e>0?i(\"button\",{class:\"cf-icon-btn cf-clear\",title:\"Clear all annotations\",onClick:()=>{S.clearAnnotations(),S.clearCursors()}},\"Clear\"):null),r=d.value,a=r.filter(c=>c.author?.kind===\"agent\").length,l=Math.max(0,r.findIndex(c=>c.id===x.value)),f=e>0?i(\"div\",{class:\"cf-nav\"},i(\"button\",{class:\"cf-nav-btn\",title:\"Previous\",onClick:()=>He(l-1)},\"\\u2039\"),i(\"span\",{class:\"cf-nav-label\"},a>0?`${a} agent${a===1?\"\":\"s\"} \\xB7 ${l+1}/${e}`:`${l+1} / ${e}`),i(\"button\",{class:\"cf-nav-btn\",title:\"Next\",onClick:()=>He(l+1)},\"\\u203A\")):null,s=i(\"div\",{class:\"cf-toolbar\",style:Oe()}),h=[o,f,t?i(\"div\",{class:\"cf-seg cf-tools\"},U(\"Element\",w.value===\"element\",()=>{w.value=\"element\",y.value=[]}),U(\"Text\",w.value===\"text\",()=>{w.value=\"text\",y.value=[]}),U(\"Multi\",w.value===\"multi\",()=>{w.value=\"multi\"})):null,t&&w.value===\"multi\"&&n?i(\"button\",{class:\"cf-btn cf-btn-primary cf-commit\",onClick:Me},`Comment ${n} element${n===1?\"\":\"s\"}`):null,t?i(\"div\",{class:\"cf-hint\"},Bt(w.value)):null,H.value?i(\"button\",{class:\"cf-btn cf-btn-primary cf-launch\",onClick:()=>H.value?.run()},H.value.label):null];for(let c of h)c&&s.appendChild(c);return Ne(s,o),je(s),s}var O={blocking:\"#ef4444\",important:\"#f59e0b\",suggestion:\"#3ecf8e\"},ze=\"#a78bfa\",Ye=[\"fix\",\"change\",\"question\",\"approve\"],Fe=[\"blocking\",\"important\",\"suggestion\"],De=\"#8b94a3\",j=[\"#a78bfa\",\"#3ecf8e\",\"#f59e0b\",\"#38bdf8\",\"#f472b6\"];function fe(e){let t=e.id||e.displayName||e.kind;return j[Math.abs(Z(t))%j.length]}function Pt(e){let t=(e.displayName??\"\").trim();if(!t)return e.kind===\"agent\"?\"AI\":\"?\";let n=t.split(/\\s+/).filter(Boolean);return n.length>=2?(n[0][0]+n[1][0]).toUpperCase():t.slice(0,2).toUpperCase()}function Ue(e){let t=fe(e);return e.avatarUrl?i(\"span\",{class:`cf-avatar cf-avatar-${e.kind}`,style:`--cf-av:${t};`},i(\"img\",{class:\"cf-avatar-img\",src:e.avatarUrl,alt:e.displayName??e.kind})):i(\"span\",{class:`cf-avatar cf-avatar-${e.kind}`,style:`--cf-av:${t};background:${t};`,title:e.displayName??e.kind},Pt(e))}var qe=new Set;function It(e,t){return{top:e.y-(t?0:window.scrollY),left:e.x-(t?0:window.scrollX),width:e.width,height:e.height}}function Rt(e,t){if(e.author?.kind===\"agent\"){let n=(e.author.displayName??\"\").trim();return n?n.charAt(0).toUpperCase():\"AI\"}return String(t)}function Ke(e,t){let n=e.author?.kind===\"agent\",o=n?fe(e.author):e.severity?O[e.severity]:ze,r=e.status===\"resolved\"||e.status===\"dismissed\",a=!qe.has(e.id);qe.add(e.id);let l=`${r?\" resolved\":\"\"}${n?\" agent\":\"\"}${a?\" cf-fresh\":\"\"}`,f=i(\"button\",{class:`cf-pin${l}`,title:e.author?.displayName?`${e.author.displayName}: ${G(e.comment)}`:G(e.comment),onClick:()=>{let v=x.value!==e.id;v&&(b.value=null),x.value=v?e.id:null}},Rt(e,t)),s=null;f.addEventListener(\"mouseenter\",()=>{s||x.value===e.id||(s=i(\"div\",{class:\"cf-pin-preview\"},G(e.comment)||e.comment),f.appendChild(s))}),f.addEventListener(\"mouseleave\",()=>{s?.remove(),s=null});let h=v=>i(\"div\",{class:`cf-anno${l}`,style:`${D(v)}--cf-pin:${o};`});if(e.isMultiSelect&&e.elementBoundingBoxes?.length){let v=i(\"div\",{class:\"cf-anno-group\"});return e.elementBoundingBoxes.forEach((M,L)=>{let $=h(It(M,e.isFixed));L===0&&$.appendChild(f),v.appendChild($)}),v}let c=Q(e);if(!c)return null;let u=h(c);return u.appendChild(f),u}function We(e){let t=e.getBoundingClientRect();return i(\"div\",{class:\"cf-multi-box\",style:D({top:t.top,left:t.left,width:t.width,height:t.height})})}function Ve(e){let t=e.x/100*window.innerWidth,n=e.y-window.scrollY,o=e.color??(e.kind===\"agent\"?j[Math.abs(Z(e.id))%j.length]:\"#ffffff\"),r=pe(\"svg\",{width:\"18\",height:\"18\",viewBox:\"0 0 18 18\",class:\"cf-cursor-arrow\"},pe(\"path\",{d:\"M2 2 L2 14 L6 10 L9 16 L11 15 L8 9 L14 9 Z\",fill:o,stroke:\"rgba(0,0,0,0.35)\",\"stroke-width\":\"0.75\"}));return i(\"div\",{class:`cf-cursor cf-cursor-${e.kind}`,style:`top:${n}px;left:${t}px;--cf-cursor:${o};`},r,i(\"span\",{class:\"cf-cursor-label\"},e.label))}function Xe(e){let t=\"change\",n=\"important\",o=i(\"textarea\",{class:\"cf-textarea\",placeholder:\"Describe the change\\u2026 (Markdown supported)\",autofocus:!0,onKeyDown:p=>{(p.metaKey||p.ctrlKey)&&p.key===\"Enter\"&&r()},onInput:()=>u()}),r=()=>{let p=o.value.trim();p&&(S.addAnnotation({...e,comment:p,intent:t,severity:n,kind:\"feedback\",author:T.value}),b.value=null)},a=()=>{b.value=null};function l(p,me,ge,rt){let he=p.map(P=>{let q=ge(P);return i(\"button\",{class:`cf-chip${q?\" on\":\"\"}`,style:q?`--cf-chip:${me(P)};`:void 0,onClick:()=>{rt(P),be()}},P)}),it=i(\"div\",{class:\"cf-chipset\"},...he);function be(){p.forEach((P,q)=>{let te=he[q],xe=ge(P);te.className=`cf-chip${xe?\" on\":\"\"}`,xe?te.setAttribute(\"style\",`--cf-chip:${me(P)};`):te.removeAttribute(\"style\")})}return{group:it,refresh:be}}let f=l(Ye,()=>De,p=>t===p,p=>{t=p}),s=l(Fe,p=>O[p],p=>n===p,p=>{n=p}),h=e.isMultiSelect?`${e.elementBoundingBoxes?.length??0} elements`:e.selectedText?`\"${Ie(e.selectedText,40)}\"`:`<${e.element}>`,c=i(\"button\",{class:\"cf-btn cf-btn-primary\",disabled:!0,onClick:r},\"Comment\");function u(){c.disabled=!o.value.trim()}let v=i(\"div\",{class:\"cf-details\",hidden:!0},i(\"div\",{class:\"cf-field\"},i(\"span\",{class:\"cf-field-label\"},\"Intent\"),f.group),i(\"div\",{class:\"cf-field\"},i(\"span\",{class:\"cf-field-label\"},\"Severity\"),s.group)),M=i(\"button\",{class:\"cf-disclose\",onClick:()=>{let p=v.hidden;v.hidden=!p,M.classList.toggle(\"on\",p),M.textContent=p?\"Details \\u25B4\":\"Details \\u25BE\"}},\"Details \\u25BE\"),L=i(\"div\",{class:\"cf-popup cf-composer\"},i(\"div\",{class:\"cf-popup-head\"},R(\"cf-popup-brand\"),i(\"span\",{class:\"cf-popup-target\"},h),i(\"button\",{class:\"cf-icon-btn\",onClick:a,title:\"Close (Esc)\"},\"\\u2715\")),o,v,i(\"div\",{class:\"cf-popup-actions\"},M,c)),$=e.boundingBox;return $&&J(L,{left:$.x-window.scrollX,top:$.y-window.scrollY,width:$.width,height:$.height}),requestAnimationFrame(()=>o.focus({preventScroll:!0})),L}function Ge(e,t){let n=e.displayName??(e.kind===\"agent\"?\"Agent\":\"You\");return i(\"div\",{class:`cf-msg cf-msg-${e.kind}`},i(\"div\",{class:\"cf-msg-meta\"},Ue(e),i(\"span\",{class:\"cf-msg-name\"},n)),i(\"div\",{class:\"cf-msg-body\"},t))}function Je(e){let t=d.value.find(s=>s.id===e);if(!t)return null;let n=i(\"textarea\",{class:\"cf-textarea cf-textarea-sm\",placeholder:\"Reply\\u2026\",onKeyDown:s=>{(s.metaKey||s.ctrlKey)&&s.key===\"Enter\"&&o()},onInput:()=>a()}),o=()=>{let s=n.value.trim();s&&S.replyToAnnotation(e,{role:T.value.kind,content:s})},r=i(\"button\",{class:\"cf-btn cf-btn-primary\",disabled:!0,onClick:o},\"Reply\");function a(){r.disabled=!n.value.trim()}let l=i(\"div\",{class:\"cf-popup cf-thread\"},i(\"div\",{class:\"cf-popup-head\"},R(\"cf-popup-brand\"),i(\"span\",{class:\"cf-popup-target\"},`<${t.element}>`),t.severity?i(\"span\",{class:\"cf-tag\",style:`--cf-tag:${O[t.severity]};`},t.severity):null,i(\"button\",{class:\"cf-icon-btn\",onClick:()=>{x.value=null},title:\"Close\"},\"\\u2715\")),i(\"div\",{class:\"cf-thread-body\"},Ge(t.author??{kind:\"human\",displayName:\"You\"},t.comment),...(t.thread??[]).map(s=>Ge({kind:s.role,displayName:s.role===\"agent\"?\"Agent\":\"You\"},s.content))),i(\"div\",{class:\"cf-thread-compose\"},n,i(\"div\",{class:\"cf-thread-actions\"},t.status!==\"resolved\"?i(\"button\",{class:\"cf-btn cf-btn-ghost\",onClick:()=>S.resolveAnnotation(e,T.value.kind)},\"Resolve\"):i(\"span\",{class:\"cf-resolved-tag\"},\"\\u2713 resolved\"),r))),f=Q(t);return f&&J(l,f),requestAnimationFrame(()=>n.focus({preventScroll:!0})),l}var Ze=`\n/* Box-sizing reset \\u2014 the host page's reset is scoped to its own tree and\n doesn't reach the overlay, so width:100% controls + padding would\n otherwise overflow their popups. Keep everything border-box. */\n.cf-overlay, .cf-overlay *, .cf-overlay *::before, .cf-overlay *::after {\n box-sizing: border-box;\n}\n.cf-overlay {\n position: fixed;\n inset: 0;\n pointer-events: none;\n font-family: -apple-system, \"SF Pro Text\", system-ui, sans-serif;\n font-size: 13px;\n color: #f4f4f5;\n --cf-bg: rgba(18, 18, 22, 0.96);\n --cf-border: rgba(255, 255, 255, 0.1);\n --cf-muted: rgba(255, 255, 255, 0.55);\n --cf-accent: #a78bfa;\n /* Liquid-glass fill for popups/panels \\u2014 low alpha so the backdrop blur\n actually reads as frosted glass instead of a solid black box. */\n --cf-glass: rgba(24, 24, 34, 0.55);\n --cf-glass-border: rgba(255, 255, 255, 0.14);\n}\n.cf-overlay[data-theme=\"light\"] {\n color: #18181b;\n --cf-bg: rgba(252, 252, 253, 0.97);\n --cf-border: rgba(0, 0, 0, 0.1);\n --cf-muted: rgba(0, 0, 0, 0.5);\n --cf-glass: rgba(252, 252, 253, 0.60);\n --cf-glass-border: rgba(0, 0, 0, 0.10);\n}\n\n/* Hover highlight + multi-select boxes */\n.cf-hover {\n position: fixed;\n pointer-events: none;\n border: 2px solid var(--cf-accent);\n background: rgba(167, 139, 250, 0.1);\n border-radius: 4px;\n box-shadow: 0 0 0 1px rgba(167, 139, 250, 0.4);\n transition: top .06s ease, left .06s ease, width .06s ease, height .06s ease;\n z-index: 1;\n}\n.cf-multi-box {\n position: fixed;\n pointer-events: none;\n border: 2px solid #3ecf8e;\n background: rgba(62, 207, 142, 0.12);\n border-radius: 4px;\n z-index: 1;\n animation: cf-multi-pulse 1.4s ease-in-out infinite;\n}\n@keyframes cf-multi-pulse {\n 0%, 100% { box-shadow: 0 0 0 0 rgba(62,207,142,0.0); }\n 50% { box-shadow: 0 0 0 3px rgba(62,207,142,0.25); }\n}\n\n/* Live presence cursors (multi-cursor collaboration) */\n.cf-cursor {\n position: fixed;\n z-index: 6;\n pointer-events: none;\n display: flex;\n align-items: flex-start;\n gap: 4px;\n /* Glide to new positions so multiple actors read as \"live\". */\n transition: top .12s ease, left .12s ease;\n will-change: top, left;\n}\n.cf-cursor-arrow { display: block; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.4)); }\n.cf-cursor-label {\n transform: translateY(2px);\n background: var(--cf-cursor, #a78bfa);\n color: #0b0b0f;\n font: 700 11px -apple-system, system-ui;\n padding: 2px 7px;\n border-radius: 8px;\n white-space: nowrap;\n box-shadow: 0 2px 8px rgba(0,0,0,0.35);\n}\n.cf-cursor-human .cf-cursor-label { color: #18181b; }\n.cf-cursor-agent .cf-cursor-label { color: #0b0b0f; }\n\n/* Pins */\n/* Outline box hugging the annotated element (so it's obvious what the\n annotation refers to). Colour-coded per author via --cf-pin. */\n/* A multi-element annotation renders several .cf-anno outlines wrapped in\n one group \\u2014 display:contents so the wrapper itself adds no layout box and\n the fixed-positioned outlines anchor straight to the viewport. */\n.cf-anno-group { display: contents; }\n.cf-anno {\n position: fixed;\n pointer-events: none;\n border: 1.5px solid var(--cf-pin, #a78bfa);\n border-radius: 7px;\n background: color-mix(in srgb, var(--cf-pin, #a78bfa) 9%, transparent);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--cf-pin, #a78bfa) 15%, transparent);\n z-index: 2;\n}\n/* Entrance animation plays only on first render (.cf-fresh), never on the\n scroll/resize re-renders \\u2014 otherwise the box flickers while scrolling. */\n.cf-anno.cf-fresh { animation: cf-rise .18s cubic-bezier(.16,1,.3,1) both; }\n.cf-anno.agent { border-style: dashed; }\n.cf-anno.resolved { opacity: 0.4; }\n.cf-pin {\n position: absolute;\n top: -11px; left: -11px;\n width: 22px; height: 22px;\n border-radius: 50% 50% 50% 2px;\n background: var(--cf-pin, #a78bfa);\n color: #fff;\n border: 2px solid rgba(255,255,255,0.9);\n font: 700 11px -apple-system, system-ui;\n display: flex; align-items: center; justify-content: center;\n cursor: pointer;\n pointer-events: auto;\n box-shadow: 0 2px 8px rgba(0,0,0,0.35);\n z-index: 3;\n transition: transform .12s cubic-bezier(.34,1.56,.64,1);\n padding: 0;\n}\n/* Pop in only when a pin first renders (.cf-fresh) \\u2014 not on the scroll\n re-renders, which would otherwise replay the pop on every tick. */\n.cf-pin.cf-fresh { animation: cf-pin-pop .32s cubic-bezier(.34,1.56,.64,1) both; }\n.cf-pin:hover { transform: scale(1.2); }\n.cf-pin.resolved { opacity: 0.45; }\n/* Human vs agent reads from the box outline (solid vs dashed) + the pin\n glyph (number vs initial) + colour \\u2014 no extra per-pin chrome. */\n\n/* Hover-to-preview card \\u2014 shown next to a pin on mouseenter. */\n.cf-pin-preview {\n position: absolute;\n top: 26px; left: 0;\n max-width: 240px;\n width: max-content;\n pointer-events: none;\n background: var(--cf-glass);\n border: 1px solid var(--cf-glass-border);\n border-radius: 9px;\n padding: 7px 10px;\n font: 500 12px -apple-system, system-ui;\n line-height: 1.4;\n color: #f4f4f5;\n white-space: normal;\n overflow-wrap: anywhere;\n -webkit-backdrop-filter: blur(24px) saturate(180%);\n backdrop-filter: blur(24px) saturate(180%);\n box-shadow:\n 0 8px 28px rgba(0,0,0,0.4),\n inset 0 1px 0 rgba(255,255,255,0.18);\n z-index: 7;\n animation: cf-rise .14s cubic-bezier(.16,1,.3,1) both;\n}\n.cf-overlay[data-theme=\"light\"] .cf-pin-preview { color: #18181b; }\n\n@keyframes cf-pin-pop {\n 0% { transform: scale(0); opacity: 0; }\n 60% { transform: scale(1.25); opacity: 1; }\n 100% { transform: scale(1); opacity: 1; }\n}\n@keyframes cf-pin-ring {\n 0% { transform: scale(1); opacity: .7; }\n 100% { transform: scale(2.4); opacity: 0; }\n}\n\n/* Toolbar */\n.cf-toolbar {\n position: fixed;\n left: 16px; bottom: 16px;\n pointer-events: auto;\n /* Liquid glass \\u2014 translucent, frosted, with a bright top edge. */\n background: rgba(24,24,34,0.52);\n border: 1px solid rgba(255,255,255,0.14);\n border-radius: 17px;\n padding: 9px;\n display: flex; flex-direction: column; gap: 8px;\n -webkit-backdrop-filter: blur(30px) saturate(185%);\n backdrop-filter: blur(30px) saturate(185%);\n box-shadow:\n 0 18px 50px rgba(0,0,0,0.34),\n inset 0 1px 0 rgba(255,255,255,0.22),\n inset 0 -1px 0 rgba(0,0,0,0.22);\n z-index: 4;\n}\n.cf-toolbar-head {\n display: flex; align-items: center; gap: 7px;\n cursor: grab; user-select: none; touch-action: none;\n}\n.cf-toolbar-head:active { cursor: grabbing; }\n/* Visible drag affordance \\u2014 signals the panel can be moved. */\n.cf-grip {\n flex: 0 0 auto; color: var(--cf-muted);\n font-size: 13px; line-height: 1; letter-spacing: -2px; opacity: 0.5;\n}\n.cf-toolbar-head:hover .cf-grip { opacity: 0.85; }\n/* Logo button \\u2014 tap to collapse back to the puck. */\n.cf-collapse {\n display: inline-flex; align-items: center; justify-content: center;\n width: 26px; height: 26px; flex: 0 0 auto; padding: 0;\n border: 0; border-radius: 8px; cursor: pointer;\n /* Light tile so a dark brand logo reads on the dark panel. */\n background: #fff;\n box-shadow: 0 1px 3px rgba(0,0,0,0.25);\n}\n.cf-collapse:hover { filter: brightness(0.94); }\n.cf-brand {\n display: inline-flex; align-items: center; justify-content: center;\n width: 22px; height: 22px; flex: 0 0 auto; pointer-events: none;\n}\n.cf-brand svg { width: 18px; height: 18px; display: block; }\n.cf-toolbar.cf-dragging {\n box-shadow: 0 24px 64px rgba(0,0,0,0.6);\n transition: none;\n}\n.cf-logo-dot {\n width: 9px; height: 9px; border-radius: 50%;\n background: var(--cf-accent); box-shadow: 0 0 10px var(--cf-accent);\n}\n\n/* Collapsed FAB \\u2014 a draggable logo puck; tap to expand. */\n.cf-fab {\n position: fixed; left: 16px; bottom: 16px;\n width: 48px; height: 48px; border-radius: 16px;\n pointer-events: auto; cursor: grab; user-select: none; touch-action: none;\n display: flex; align-items: center; justify-content: center;\n /* Liquid glass puck \\u2014 frosted light so the dark mark reads. */\n background: rgba(255,255,255,0.66);\n -webkit-backdrop-filter: blur(22px) saturate(185%);\n backdrop-filter: blur(22px) saturate(185%);\n box-shadow:\n 0 12px 34px rgba(0,0,0,0.20),\n inset 0 1px 0 rgba(255,255,255,0.95),\n 0 0 0 0.5px rgba(0,0,0,0.06);\n z-index: 4;\n transition: transform .13s cubic-bezier(.34,1.56,.64,1), box-shadow .15s ease;\n}\n.cf-fab:hover { transform: scale(1.06); }\n.cf-fab.cf-dragging { cursor: grabbing; transition: none; box-shadow: 0 18px 44px rgba(0,0,0,0.42); }\n.cf-fab .cf-brand { width: 28px; height: 28px; cursor: inherit; }\n.cf-fab .cf-brand svg { width: 24px; height: 24px; }\n.cf-fab-badge {\n position: absolute; top: -5px; right: -5px;\n min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box;\n border-radius: 9px; background: var(--cf-accent); color: #fff;\n font: 800 10px -apple-system, system-ui;\n display: flex; align-items: center; justify-content: center;\n box-shadow: 0 0 0 2px var(--cf-bg);\n}\n.cf-count {\n margin-left: auto;\n font: 700 11px -apple-system, system-ui;\n color: var(--cf-muted);\n background: rgba(255,255,255,0.08);\n padding: 1px 7px; border-radius: 8px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-count { background: rgba(0,0,0,0.06); }\n\n/* View / Comment reads as a pill switch \\u2014 rounded track + sliding pill. */\n.cf-seg {\n display: flex; gap: 2px;\n background: rgba(255,255,255,0.07);\n border-radius: 999px; padding: 3px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-seg { background: rgba(0,0,0,0.05); }\n.cf-seg-btn {\n flex: 1; border: none; background: transparent; color: var(--cf-muted);\n padding: 5px 14px; border-radius: 999px; cursor: pointer;\n font: 600 12px -apple-system, system-ui;\n transition: color .15s ease, background .2s ease;\n}\n.cf-seg-btn:hover { color: #fff; }\n.cf-seg-btn.on {\n background: var(--cf-accent); color: #fff;\n box-shadow: 0 1px 5px rgba(124,92,255,0.45);\n}\n/* Suggestions navigator \\u2014 count + jump to each annotation. */\n.cf-nav {\n display: flex; align-items: center; justify-content: space-between; gap: 6px;\n background: rgba(255,255,255,0.05); border-radius: 10px; padding: 2px 3px;\n}\n.cf-nav-btn {\n border: 0; background: transparent; color: var(--cf-muted); cursor: pointer;\n width: 24px; height: 22px; border-radius: 7px; font-size: 16px; line-height: 1; padding: 0;\n}\n.cf-nav-btn:hover { background: rgba(255,255,255,0.1); color: #fff; }\n.cf-nav-label { font: 700 11px -apple-system, system-ui; color: var(--cf-muted); }\n.cf-tools .cf-seg-btn.on { background: rgba(255,255,255,0.16); color: #fff; }\n.cf-overlay[data-theme=\"light\"] .cf-tools .cf-seg-btn.on { background: rgba(0,0,0,0.12); color: #111; }\n.cf-hint { font-size: 11px; color: var(--cf-muted); padding: 0 2px; }\n.cf-commit { width: 100%; }\n.cf-launch {\n width: 100%; border: 0; margin-top: 2px;\n background: linear-gradient(135deg, #7c5cff, #3ecf8e);\n box-shadow: 0 6px 18px rgba(124,92,255,0.35);\n}\n.cf-launch:hover { filter: brightness(1.07); }\n\n/* Buttons */\n.cf-btn {\n border: 1px solid var(--cf-border); background: transparent; color: inherit;\n padding: 6px 12px; border-radius: 8px; font: 600 12px -apple-system, system-ui;\n}\n.cf-btn:hover { background: rgba(255,255,255,0.06); }\n.cf-overlay[data-theme=\"light\"] .cf-btn:hover { background: rgba(0,0,0,0.04); }\n.cf-btn-primary {\n background: var(--cf-accent); border-color: var(--cf-accent); color: #fff;\n}\n.cf-btn-primary:hover { background: #9173f0; }\n.cf-btn-primary:disabled { opacity: 0.4; cursor: not-allowed; }\n.cf-btn-ghost { border-color: transparent; color: var(--cf-muted); }\n\n/* Popups (composer + thread) */\n.cf-popup {\n position: fixed;\n left: 16px; bottom: 92px;\n width: 320px;\n pointer-events: auto;\n /* Liquid glass \\u2014 translucent + heavily frosted with a bright top edge,\n matching the toolbar/FAB. The low-alpha fill is what lets the blur\n read as glass rather than a solid black box. */\n background: var(--cf-glass);\n border: 1px solid var(--cf-glass-border);\n border-radius: 16px;\n padding: 12px;\n display: flex; flex-direction: column; gap: 10px;\n -webkit-backdrop-filter: blur(30px) saturate(185%);\n backdrop-filter: blur(30px) saturate(185%);\n box-shadow:\n 0 18px 50px rgba(0,0,0,0.40),\n inset 0 1px 0 rgba(255,255,255,0.22),\n inset 0 -1px 0 rgba(0,0,0,0.22);\n z-index: 5;\n animation: cf-rise .2s cubic-bezier(.16,1,.3,1) both;\n}\n@keyframes cf-rise {\n from { transform: translateY(10px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n.cf-popup-head {\n display: flex; align-items: center; gap: 8px;\n}\n.cf-popup-target {\n font: 600 12px ui-monospace, \"SF Mono\", monospace;\n color: var(--cf-accent);\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n}\n.cf-icon-btn {\n margin-left: auto; border: none; background: transparent;\n color: var(--cf-muted); font-size: 13px; cursor: pointer;\n width: 22px; height: 22px; border-radius: 6px;\n}\n.cf-icon-btn:hover { background: rgba(255,255,255,0.08); }\n/* Clear / erase-board \\u2014 small text button after the count. */\n.cf-clear {\n margin-left: 4px; width: auto; height: auto; padding: 3px 8px;\n font: 700 10px -apple-system, system-ui; text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n.cf-clear:hover { color: #fff; }\n\n.cf-textarea {\n width: 100%; min-height: 72px; resize: vertical;\n background: rgba(255,255,255,0.04);\n border: 1px solid var(--cf-border); border-radius: 9px;\n padding: 8px 10px; color: inherit; font: 400 13px -apple-system, system-ui;\n line-height: 1.45;\n}\n.cf-overlay[data-theme=\"light\"] .cf-textarea { background: rgba(0,0,0,0.03); }\n.cf-textarea:focus { outline: none; border-color: var(--cf-accent); }\n.cf-textarea-sm { min-height: 48px; }\n\n.cf-field { display: flex; flex-direction: column; gap: 5px; }\n.cf-field-label {\n font: 700 10px -apple-system, system-ui; letter-spacing: 0.06em;\n text-transform: uppercase; color: var(--cf-muted);\n}\n.cf-chipset { display: flex; flex-wrap: wrap; gap: 5px; }\n.cf-chip {\n border: 1px solid var(--cf-border); background: transparent; color: var(--cf-muted);\n padding: 4px 10px; border-radius: 20px; font: 600 11px -apple-system, system-ui;\n text-transform: capitalize;\n}\n.cf-chip.on {\n background: var(--cf-chip, var(--cf-accent));\n border-color: var(--cf-chip, var(--cf-accent));\n color: #fff;\n}\n.cf-popup-actions { display: flex; gap: 8px; align-items: center; justify-content: flex-end; }\n\n/* Composer grows out of the floater \\u2014 the WAAPI morph drives it, so drop\n the CSS keyframe to avoid a double animation. */\n.cf-popup.cf-morph { animation: none; }\n/* The logo in the popup head \\u2014 the floater mark that flew over + opened. */\n.cf-popup-brand {\n width: 20px; height: 20px; flex: 0 0 auto;\n display: inline-flex; align-items: center; justify-content: center;\n background: #fff; border-radius: 6px; box-shadow: 0 1px 2px rgba(0,0,0,0.25);\n}\n.cf-popup-brand svg { width: 15px; height: 15px; display: block; }\n/* Intent/severity disclosure \\u2014 minimal by default. */\n.cf-details { display: flex; flex-direction: column; gap: 10px; }\n.cf-details[hidden] { display: none; }\n.cf-disclose {\n margin-right: auto; border: 0; background: transparent; color: var(--cf-muted);\n font: 600 11px -apple-system, system-ui; cursor: pointer;\n padding: 6px 6px; border-radius: 7px;\n}\n.cf-disclose:hover, .cf-disclose.on { color: #fff; background: rgba(255,255,255,0.06); }\n.cf-overlay[data-theme=\"light\"] .cf-disclose:hover,\n.cf-overlay[data-theme=\"light\"] .cf-disclose.on { color: #111; background: rgba(0,0,0,0.05); }\n\n/* Thread */\n.cf-thread-body {\n display: flex; flex-direction: column; gap: 12px;\n max-height: 280px; overflow-y: auto; padding-right: 2px;\n}\n.cf-msg { display: flex; flex-direction: column; gap: 3px; }\n.cf-msg-meta { display: flex; align-items: center; gap: 6px; }\n.cf-avatar {\n width: 20px; height: 20px; flex: 0 0 auto;\n display: inline-flex; align-items: center; justify-content: center;\n border-radius: 50%; overflow: hidden;\n font: 800 9px -apple-system, system-ui; letter-spacing: 0.02em;\n color: #fff; text-shadow: 0 1px 1px rgba(0,0,0,0.25);\n box-shadow: 0 0 0 1.5px rgba(255,255,255,0.14), 0 1px 2px rgba(0,0,0,0.3);\n}\n/* Agents read as a distinct rounded \"logo\" tile; humans stay round. */\n.cf-avatar-agent { border-radius: 7px; }\n.cf-avatar-img { width: 100%; height: 100%; object-fit: cover; }\n.cf-msg-name {\n font: 700 11px -apple-system, system-ui; color: var(--cf-muted);\n}\n.cf-msg-body {\n font-size: 13px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;\n background: rgba(255,255,255,0.04); border-radius: 9px; padding: 7px 10px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-msg-body { background: rgba(0,0,0,0.03); }\n.cf-msg-agent .cf-msg-body { border-left: 2px solid var(--cf-accent); }\n.cf-thread-compose { display: flex; flex-direction: column; gap: 8px; }\n.cf-thread-actions { display: flex; gap: 8px; align-items: center; }\n.cf-thread-actions .cf-btn-primary { margin-left: auto; }\n.cf-resolved-tag { font: 600 11px -apple-system, system-ui; color: #3ecf8e; }\n.cf-tag {\n font: 700 9px -apple-system, system-ui; text-transform: uppercase;\n letter-spacing: 0.05em; padding: 2px 6px; border-radius: 5px;\n background: var(--cf-tag, var(--cf-accent)); color: #fff;\n}\n\n/* Respect reduced-motion: keep the UI usable, drop the motion. */\n@media (prefers-reduced-motion: reduce) {\n .cf-pin, .cf-popup, .cf-multi-box { animation: none !important; }\n .cf-pin.agent::after { display: none; }\n}\n`;function N(e,t,n){let o=()=>{e.replaceChildren();let r=n();r!==null&&(Array.isArray(r)?e.append(...r):e.append(r))};o();for(let r of t)r.subscribe(o)}function Qe(e,t={}){let n=i(\"div\",{class:\"cf-overlay\"}),o=()=>{n.setAttribute(\"data-theme\",B.value===\"auto\"?\"dark\":B.value)};o(),B.subscribe(o);let r=document.createElement(\"style\");r.textContent=Ze,n.appendChild(r);let a=i(\"div\",{class:\"cf-layer-hover\"});N(a,[k,b],()=>{let u=k.value;return!u||b.value?null:i(\"div\",{class:\"cf-hover\",style:D(u)})}),n.appendChild(a);let l=i(\"div\",{class:\"cf-layer-multi\"});N(l,[y,z],()=>y.value.map(u=>We(u))),n.appendChild(l);let f=i(\"div\",{class:\"cf-layer-pins\"});N(f,[d,z],()=>d.value.map((u,v)=>Ke(u,v+1)).filter(u=>u!==null)),n.appendChild(f);let s=i(\"div\",{class:\"cf-layer-cursors\"});if(N(s,[E],()=>E.value.map(u=>Ve(u))),n.appendChild(s),!t.headless){let u=i(\"div\",{class:\"cf-layer-toolbar\"});N(u,[g,w,d,y,Y,H,I,V],()=>_e()),n.appendChild(u)}let h=i(\"div\",{class:\"cf-layer-composer\"});N(h,[b],()=>b.value?Xe(b.value):null),n.appendChild(h);let c=i(\"div\",{class:\"cf-layer-thread\"});N(c,[x,d],()=>x.value?Je(x.value):null),n.appendChild(c),e.appendChild(n)}var et=!1,tt=!1;function nt(e={}){ke(e),e.author&&(T.value=e.author),e.mode&&(g.value=e.mode),e.theme&&(B.value=e.theme),e.headless&&(tt=!0),ot(),we.value=!0,console.info(\"[annotations v1] ready on\",location.href)}function ot(){if(et||typeof document>\"u\")return;if(!document.documentElement){document.addEventListener(\"DOMContentLoaded\",ot,{once:!0});return}et=!0;let{host:e,appRoot:t}=Pe();Ce(e),$e(),Qe(t,{headless:tt});let n=()=>{z.value++};window.addEventListener(\"scroll\",n,{passive:!0,capture:!0}),window.addEventListener(\"resize\",n,{passive:!0})}var Nt=Object.assign({__init:nt},S);window.__annotations=Nt;nt();})();\n";
package/src/output.ts CHANGED
@@ -166,6 +166,6 @@ function quote(text: string): string {
166
166
  }
167
167
 
168
168
  function formatThreadMessage(msg: ThreadMessage): string {
169
- const author = msg.role === "agent" ? "🤖 agent" : "🧑 human";
169
+ const author = msg.role === "agent" ? "agent" : "human";
170
170
  return `- _${author}_: ${msg.content.trim()}`;
171
171
  }
package/src/picker.ts CHANGED
@@ -18,6 +18,7 @@
18
18
 
19
19
  import { captureElement, type CapturedTarget } from "./capture.js";
20
20
  import {
21
+ activeThreadId,
21
22
  author,
22
23
  draft,
23
24
  feedbackTool,
@@ -74,10 +75,9 @@ function onMouseMove(event: MouseEvent): void {
74
75
  hoverBox.value = null;
75
76
  return;
76
77
  }
77
- if (feedbackTool.value === "text") {
78
- hoverBox.value = null;
79
- return;
80
- }
78
+ // Text mode highlights the hovered text-bearing element too, so there's
79
+ // always a visible target before the user drags to select — same as
80
+ // element mode. The native selection highlight then shows the exact span.
81
81
  const el = pickable(event.target);
82
82
  if (!el) {
83
83
  hoverBox.value = null;
@@ -127,7 +127,25 @@ function onMouseUp(): void {
127
127
  : range.commonAncestorContainer.parentElement;
128
128
  if (!anchor) return;
129
129
  const captured = captureElement(anchor);
130
- openComposer({ ...captured, selectedText: text });
130
+ // Anchor the pin + composer to the SELECTED TEXT's rect — not the whole
131
+ // containing element — so the marker hugs exactly what was highlighted.
132
+ const rect = range.getBoundingClientRect();
133
+ const selectionBox =
134
+ rect.width || rect.height
135
+ ? {
136
+ x: rect.left + (captured.isFixed ? 0 : window.scrollX),
137
+ y: rect.top + (captured.isFixed ? 0 : window.scrollY),
138
+ width: rect.width,
139
+ height: rect.height,
140
+ }
141
+ : captured.boundingBox;
142
+ openComposer({
143
+ ...captured,
144
+ selectedText: text,
145
+ boundingBox: selectionBox,
146
+ x: ((rect.left + rect.width / 2) / window.innerWidth) * 100,
147
+ y: captured.isFixed ? rect.top : rect.top + window.scrollY,
148
+ });
131
149
  }
132
150
 
133
151
  function onKeyDown(event: KeyboardEvent): void {
package/src/signal.ts ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Tiny vanilla reactive primitive — a drop-in for the `@preact/signals`
3
+ * `signal()` we used previously, with no dependencies.
4
+ *
5
+ * A `Signal<T>` holds a value behind a `.value` getter/setter. Writing a
6
+ * value that differs (per `Object.is`) from the current one notifies all
7
+ * subscribers. `.peek()` reads without implying a subscription, and
8
+ * `.subscribe(fn)` registers a listener and returns an unsubscribe fn.
9
+ *
10
+ * This is intentionally minimal: no computed/effect graph, no batching.
11
+ * The overlay only needs per-signal subscriptions, which is all the
12
+ * store + UI layers consume.
13
+ */
14
+
15
+ export interface Signal<T> {
16
+ value: T;
17
+ /** Read the current value without subscribing. */
18
+ peek(): T;
19
+ /** Subscribe to changes. Returns an unsubscribe function. */
20
+ subscribe(fn: (value: T) => void): () => void;
21
+ }
22
+
23
+ class SignalImpl<T> implements Signal<T> {
24
+ private _value: T;
25
+ private readonly _subs = new Set<(value: T) => void>();
26
+
27
+ constructor(initial: T) {
28
+ this._value = initial;
29
+ }
30
+
31
+ get value(): T {
32
+ return this._value;
33
+ }
34
+
35
+ set value(next: T) {
36
+ if (Object.is(this._value, next)) return;
37
+ this._value = next;
38
+ // Snapshot so an unsubscribe during notification can't skip listeners.
39
+ for (const fn of Array.from(this._subs)) fn(next);
40
+ }
41
+
42
+ peek(): T {
43
+ return this._value;
44
+ }
45
+
46
+ subscribe(fn: (value: T) => void): () => void {
47
+ this._subs.add(fn);
48
+ return () => {
49
+ this._subs.delete(fn);
50
+ };
51
+ }
52
+ }
53
+
54
+ export function signal<T>(initial: T): Signal<T> {
55
+ return new SignalImpl<T>(initial);
56
+ }
package/src/store.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Preact signals for the v1 library state.
2
+ * Reactive signals for the v1 library state.
3
3
  *
4
4
  * Single in-memory source of truth — there's no persistence inside
5
5
  * the library; the host's webhook handler is the durable log. On
@@ -7,7 +7,7 @@
7
7
  * re-hydrate via `addAnnotation` if it wants to.
8
8
  */
9
9
 
10
- import { signal } from "@preact/signals";
10
+ import { signal } from "./signal.js";
11
11
  import type { CapturedTarget } from "./capture.js";
12
12
  import type { Annotation, Mode, Theme } from "./types.js";
13
13
 
@@ -77,3 +77,37 @@ export interface PresenceCursor {
77
77
  }
78
78
 
79
79
  export const cursors = signal<PresenceCursor[]>([]);
80
+
81
+ /**
82
+ * User-dragged toolbar position (viewport px from top-left). `null` =
83
+ * the default docked spot (bottom-right via CSS). Persisted here so it
84
+ * survives the toolbar layer's re-renders; the drag moves the element
85
+ * directly for smoothness and commits to this signal on release.
86
+ */
87
+ export const toolbarPos = signal<{ x: number; y: number } | null>(null);
88
+
89
+ /**
90
+ * Optional primary action shown in the toolbar (e.g. "Launch agents").
91
+ * Vendor-neutral: the host supplies the label + handler; the toolbar
92
+ * renders the button only when this is set, so the library hardcodes no
93
+ * product-specific behavior.
94
+ */
95
+ export interface PrimaryAction {
96
+ label: string;
97
+ run: () => void;
98
+ }
99
+ export const primaryAction = signal<PrimaryAction | null>(null);
100
+
101
+ /**
102
+ * Collapsed = the overlay shows just a draggable logo "FAB"; tapping it
103
+ * expands the control panel. Icon-first by default so the overlay stays
104
+ * out of the way until the user wants it.
105
+ */
106
+ export const collapsed = signal<boolean>(true);
107
+
108
+ /**
109
+ * Optional brand mark (inline SVG/HTML string) shown as the collapsed
110
+ * icon + in the expanded header. Host-supplied — the library ships a
111
+ * neutral default and hardcodes no brand asset.
112
+ */
113
+ export const brandLogo = signal<string | null>(null);
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Identity avatar — a small circular badge for a human or agent author.
3
+ *
4
+ * Vendor-neutral: the badge is derived entirely from the identity the
5
+ * host supplies (id / displayName / optional avatarUrl). No hardcoded
6
+ * names or brand assets live here — the host (e.g. its agent roster)
7
+ * decides who's who and may pass an `avatarUrl` for a real logo.
8
+ *
9
+ * - `avatarUrl` given → render the image.
10
+ * - otherwise → initials on a colour deterministically derived
11
+ * from the id, so each distinct author keeps a
12
+ * stable colour across pins, cursors, and threads.
13
+ */
14
+
15
+ import { CURSOR_PALETTE } from "./constants.js";
16
+ import { hashId } from "./helpers.js";
17
+ import { el } from "./dom.js";
18
+
19
+ export interface AvatarIdentity {
20
+ kind: "human" | "agent";
21
+ id?: string;
22
+ displayName?: string;
23
+ avatarUrl?: string;
24
+ }
25
+
26
+ /** Stable colour for an identity (shared with the presence-cursor palette). */
27
+ export function colorForIdentity(idt: AvatarIdentity): string {
28
+ const key = idt.id || idt.displayName || idt.kind;
29
+ return CURSOR_PALETTE[Math.abs(hashId(key)) % CURSOR_PALETTE.length]!;
30
+ }
31
+
32
+ function initials(idt: AvatarIdentity): string {
33
+ const name = (idt.displayName ?? "").trim();
34
+ if (!name) return idt.kind === "agent" ? "AI" : "?";
35
+ const parts = name.split(/\s+/).filter(Boolean);
36
+ if (parts.length >= 2) return (parts[0]![0]! + parts[1]![0]!).toUpperCase();
37
+ return name.slice(0, 2).toUpperCase();
38
+ }
39
+
40
+ export function renderAvatar(idt: AvatarIdentity): HTMLElement {
41
+ const color = colorForIdentity(idt);
42
+ if (idt.avatarUrl) {
43
+ return el(
44
+ "span",
45
+ { class: `cf-avatar cf-avatar-${idt.kind}`, style: `--cf-av:${color};` },
46
+ el("img", {
47
+ class: "cf-avatar-img",
48
+ src: idt.avatarUrl,
49
+ alt: idt.displayName ?? idt.kind,
50
+ }),
51
+ );
52
+ }
53
+ return el(
54
+ "span",
55
+ {
56
+ class: `cf-avatar cf-avatar-${idt.kind}`,
57
+ style: `--cf-av:${color};background:${color};`,
58
+ title: idt.displayName ?? idt.kind,
59
+ },
60
+ initials(idt),
61
+ );
62
+ }