@useclickly/react 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -2
  3. package/dist/index.cjs +5237 -1455
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +31 -7
  6. package/dist/index.d.ts +93 -12
  7. package/dist/index.js +5181 -1390
  8. package/dist/index.js.map +1 -1
  9. package/package.json +13 -12
  10. package/dist/Clickly.d.ts +0 -25
  11. package/dist/Clickly.d.ts.map +0 -1
  12. package/dist/hooks/useDraggable.d.ts +0 -28
  13. package/dist/hooks/useDraggable.d.ts.map +0 -1
  14. package/dist/hooks/usePersistedState.d.ts +0 -6
  15. package/dist/hooks/usePersistedState.d.ts.map +0 -1
  16. package/dist/index.d.ts.map +0 -1
  17. package/dist/internal/AnnotationList.d.ts +0 -11
  18. package/dist/internal/AnnotationList.d.ts.map +0 -1
  19. package/dist/internal/AnnotationPins.d.ts +0 -2
  20. package/dist/internal/AnnotationPins.d.ts.map +0 -1
  21. package/dist/internal/AnnotationPopup.d.ts +0 -5
  22. package/dist/internal/AnnotationPopup.d.ts.map +0 -1
  23. package/dist/internal/ClicklyRoot.d.ts +0 -15
  24. package/dist/internal/ClicklyRoot.d.ts.map +0 -1
  25. package/dist/internal/CollapsedFAB.d.ts +0 -10
  26. package/dist/internal/CollapsedFAB.d.ts.map +0 -1
  27. package/dist/internal/SettingsPopover.d.ts +0 -11
  28. package/dist/internal/SettingsPopover.d.ts.map +0 -1
  29. package/dist/internal/Toolbar.d.ts +0 -8
  30. package/dist/internal/Toolbar.d.ts.map +0 -1
  31. package/dist/internal/globalStyles.d.ts +0 -13
  32. package/dist/internal/globalStyles.d.ts.map +0 -1
  33. package/dist/internal/icons.d.ts +0 -14
  34. package/dist/internal/icons.d.ts.map +0 -1
  35. package/dist/internal/styles.d.ts +0 -7
  36. package/dist/internal/styles.d.ts.map +0 -1
  37. package/dist/output/markdown.d.ts +0 -5
  38. package/dist/output/markdown.d.ts.map +0 -1
  39. package/dist/output/markdown.test.d.ts +0 -2
  40. package/dist/output/markdown.test.d.ts.map +0 -1
  41. package/dist/state/annotations.d.ts +0 -21
  42. package/dist/state/annotations.d.ts.map +0 -1
  43. package/dist/state/annotations.test.d.ts +0 -2
  44. package/dist/state/annotations.test.d.ts.map +0 -1
  45. package/dist/state/settings.d.ts +0 -14
  46. package/dist/state/settings.d.ts.map +0 -1
  47. package/dist/state/settings.test.d.ts +0 -2
  48. package/dist/state/settings.test.d.ts.map +0 -1
  49. package/dist/state/useEngineState.d.ts +0 -7
  50. package/dist/state/useEngineState.d.ts.map +0 -1
  51. package/dist/test/setup.d.ts +0 -7
  52. package/dist/test/setup.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useclickly/react",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "Click-to-annotate dev toolbar for React 18+ apps. Generates agent-ready prompts. Drop in one component — no config.",
5
5
  "license": "MIT",
6
6
  "author": "Clickly contributors",
@@ -43,19 +43,12 @@
43
43
  },
44
44
  "./package.json": "./package.json"
45
45
  },
46
- "scripts": {
47
- "build": "tsup",
48
- "dev": "tsup --watch",
49
- "test": "vitest run",
50
- "test:e2e": "playwright test",
51
- "typecheck": "tsc --noEmit",
52
- "clean": "rimraf dist .turbo"
53
- },
54
46
  "dependencies": {
55
- "@useclickly/core": "workspace:*",
56
47
  "idb-keyval": "^6.2.1",
48
+ "modern-screenshot": "^4.7.0",
57
49
  "nanoid": "^5.0.7",
58
- "zustand": "^5.0.0"
50
+ "zustand": "^5.0.0",
51
+ "@useclickly/core": "1.1.0"
59
52
  },
60
53
  "peerDependencies": {
61
54
  "react": "^18.0.0 || ^19.0.0",
@@ -80,5 +73,13 @@
80
73
  },
81
74
  "publishConfig": {
82
75
  "access": "public"
76
+ },
77
+ "scripts": {
78
+ "build": "tsup",
79
+ "dev": "tsup --watch",
80
+ "test": "vitest run",
81
+ "test:e2e": "playwright test",
82
+ "typecheck": "tsc --noEmit",
83
+ "clean": "rimraf dist .turbo"
83
84
  }
84
- }
85
+ }
package/dist/Clickly.d.ts DELETED
@@ -1,25 +0,0 @@
1
- export interface ClicklyProps {
2
- /** Custom class on the host element (for z-index / positioning overrides). */
3
- className?: string;
4
- /** Optional MCP server endpoint, e.g. "http://localhost:4747". */
5
- endpoint?: string;
6
- /** Join an existing MCP session by ID. */
7
- sessionId?: string;
8
- onAnnotationAdd?: (id: string) => void;
9
- onAnnotationDelete?: (id: string) => void;
10
- onAnnotationsClear?: () => void;
11
- onCopy?: (markdown: string) => void;
12
- onSessionCreated?: (sessionId: string) => void;
13
- }
14
- /**
15
- * Mount once near the root of your React app. Dev-only by convention:
16
- *
17
- * ```tsx
18
- * {process.env.NODE_ENV === "development" && <Clickly />}
19
- * ```
20
- *
21
- * Renders a small floating button (FAB) in the bottom-right corner.
22
- * Click it (or press `⌘/Ctrl+Shift+F`) to open the full toolbar.
23
- */
24
- export declare function Clickly({ className }?: ClicklyProps): import("react").ReactPortal | null;
25
- //# sourceMappingURL=Clickly.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Clickly.d.ts","sourceRoot":"","sources":["../src/Clickly.tsx"],"names":[],"mappings":"AAYA,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,eAAe,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAChD;AASD;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,EAAE,SAAS,EAAE,GAAE,YAAiB,sCA6EvD"}
@@ -1,28 +0,0 @@
1
- export interface Position {
2
- x: number;
3
- y: number;
4
- }
5
- interface DraggableApi {
6
- position: Position;
7
- setPosition: (p: Position) => void;
8
- /** Spread onto the drag handle. */
9
- handleProps: {
10
- onPointerDown: (e: React.PointerEvent) => void;
11
- style: React.CSSProperties;
12
- };
13
- isDragging: boolean;
14
- }
15
- /**
16
- * In-session drag positioning. Position resets to `defaultPos` whenever
17
- * the consumer remounts (e.g. toolbar collapse → expand cycle).
18
- *
19
- * We deliberately do NOT persist across reloads — users expect the
20
- * toolbar to come back at its default anchor, not where they last left
21
- * it three sessions ago. Drag is for "get out of my way right now".
22
- */
23
- export declare function useDraggable(defaultPos: Position, size: {
24
- width: number;
25
- height: number;
26
- }): DraggableApi;
27
- export {};
28
- //# sourceMappingURL=useDraggable.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useDraggable.d.ts","sourceRoot":"","sources":["../../src/hooks/useDraggable.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;IACnC,mCAAmC;IACnC,WAAW,EAAE;QACX,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;QAC/C,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC;KAC5B,CAAC;IACF,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,QAAQ,EACpB,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtC,YAAY,CAqDd"}
@@ -1,6 +0,0 @@
1
- /**
2
- * `useState` + localStorage. Plain JSON-serializable values only.
3
- * Safe under SSR (returns `initial` on first render).
4
- */
5
- export declare function usePersistedState<T>(key: string, initial: T): [T, (next: T | ((prev: T) => T)) => void];
6
- //# sourceMappingURL=usePersistedState.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"usePersistedState.d.ts","sourceRoot":"","sources":["../../src/hooks/usePersistedState.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,GACT,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAqB3C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,QAAQ,IAAI,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,cAAc,GACf,MAAM,kBAAkB,CAAC"}
@@ -1,11 +0,0 @@
1
- interface Props {
2
- anchor: {
3
- x: number;
4
- y: number;
5
- };
6
- width: number;
7
- onClose: () => void;
8
- }
9
- export declare function AnnotationList({ anchor, width, onClose }: Props): import("react").JSX.Element;
10
- export {};
11
- //# sourceMappingURL=AnnotationList.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AnnotationList.d.ts","sourceRoot":"","sources":["../../src/internal/AnnotationList.tsx"],"names":[],"mappings":"AAOA,UAAU,KAAK;IACb,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,+BA2C/D"}
@@ -1,2 +0,0 @@
1
- export declare function AnnotationPins(): import("react").JSX.Element;
2
- //# sourceMappingURL=AnnotationPins.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AnnotationPins.d.ts","sourceRoot":"","sources":["../../src/internal/AnnotationPins.tsx"],"names":[],"mappings":"AAKA,wBAAgB,cAAc,gCA0B7B"}
@@ -1,5 +0,0 @@
1
- import { type SelectionEngine } from "@useclickly/core";
2
- export declare function AnnotationPopup({ engine }: {
3
- engine: SelectionEngine;
4
- }): import("react").JSX.Element | null;
5
- //# sourceMappingURL=AnnotationPopup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AnnotationPopup.d.ts","sourceRoot":"","sources":["../../src/internal/AnnotationPopup.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAC;AAS1B,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,eAAe,CAAA;CAAE,sCA4RtE"}
@@ -1,15 +0,0 @@
1
- import type { SelectionEngine } from "@useclickly/core";
2
- /**
3
- * Top-level React subtree rendered (via createPortal) inside the
4
- * shadow root. Owns:
5
- *
6
- * - the expanded ↔ collapsed UI state
7
- * - all keyboard shortcuts (delegating engine actions to the engine)
8
- * - the body `data-clickly-active` attribute used to flip the page
9
- * cursor to crosshair while inspecting
10
- */
11
- export declare function ClicklyRoot({ engine, host, }: {
12
- engine: SelectionEngine;
13
- host: HTMLElement;
14
- }): import("react").JSX.Element;
15
- //# sourceMappingURL=ClicklyRoot.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ClicklyRoot.d.ts","sourceRoot":"","sources":["../../src/internal/ClicklyRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAUxD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,IAAI,GACL,EAAE;IACD,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,WAAW,CAAC;CACnB,+BA2HA"}
@@ -1,10 +0,0 @@
1
- interface Props {
2
- onExpand: () => void;
3
- }
4
- /**
5
- * Default state — a small round button anchored bottom-right.
6
- * Click to expand the full toolbar.
7
- */
8
- export declare function CollapsedFAB({ onExpand }: Props): import("react").JSX.Element;
9
- export {};
10
- //# sourceMappingURL=CollapsedFAB.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CollapsedFAB.d.ts","sourceRoot":"","sources":["../../src/internal/CollapsedFAB.tsx"],"names":[],"mappings":"AAGA,UAAU,KAAK;IACb,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,+BAe/C"}
@@ -1,11 +0,0 @@
1
- interface Props {
2
- anchor: {
3
- x: number;
4
- y: number;
5
- };
6
- width: number;
7
- onClose: () => void;
8
- }
9
- export declare function SettingsPopover({ anchor, width, onClose }: Props): import("react").JSX.Element;
10
- export {};
11
- //# sourceMappingURL=SettingsPopover.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SettingsPopover.d.ts","sourceRoot":"","sources":["../../src/internal/SettingsPopover.tsx"],"names":[],"mappings":"AAIA,UAAU,KAAK;IACb,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,+BAyGhE"}
@@ -1,8 +0,0 @@
1
- import type { SelectionEngine } from "@useclickly/core";
2
- interface Props {
3
- engine: SelectionEngine;
4
- onCollapse: () => void;
5
- }
6
- export declare function Toolbar({ engine, onCollapse }: Props): import("react").JSX.Element;
7
- export {};
8
- //# sourceMappingURL=Toolbar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/internal/Toolbar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,kBAAkB,CAAC;AAoEvE,UAAU,KAAK;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAuBD,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,KAAK,+BAgPpD"}
@@ -1,13 +0,0 @@
1
- /**
2
- * CSS injected into `document.head` (NOT the shadow root). Targets the
3
- * host page body to:
4
- *
5
- * - disable text selection while we're inspecting/pressed/dragging
6
- * (otherwise the browser tries to select text mid-drag and the
7
- * marquee never starts)
8
- * - swap the cursor to crosshair in area mode for a clear UX cue
9
- *
10
- * Mounted by `Clickly.tsx`, torn down on unmount.
11
- */
12
- export declare const GLOBAL_PAGE_CSS = "\nbody[data-clickly-active] {\n -webkit-user-select: none !important;\n user-select: none !important;\n}\nbody[data-clickly-active],\nbody[data-clickly-active] *:not(input):not(textarea):not(select) {\n cursor: crosshair !important;\n}\nbody[data-clickly-mode=\"multi\"],\nbody[data-clickly-mode=\"multi\"] *:not(input):not(textarea):not(select) {\n cursor: copy !important;\n}\n/* Restore normal cursor while the annotation popup is open so the user\n can comfortably type in the textarea + click the buttons. */\nbody[data-clickly-annotating] {\n cursor: default !important;\n}\n";
13
- //# sourceMappingURL=globalStyles.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"globalStyles.d.ts","sourceRoot":"","sources":["../../src/internal/globalStyles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,ilBAkB3B,CAAC"}
@@ -1,14 +0,0 @@
1
- export declare const IconFreeze: () => import("react").JSX.Element;
2
- export declare const IconInfo: () => import("react").JSX.Element;
3
- export declare const IconCursor: () => import("react").JSX.Element;
4
- export declare const IconLayers: () => import("react").JSX.Element;
5
- export declare const IconSquare: () => import("react").JSX.Element;
6
- export declare const IconCopy: () => import("react").JSX.Element;
7
- export declare const IconTrash: () => import("react").JSX.Element;
8
- export declare const IconSettings: () => import("react").JSX.Element;
9
- export declare const IconGrip: () => import("react").JSX.Element;
10
- export declare const IconClose: () => import("react").JSX.Element;
11
- export declare const IconCheck: () => import("react").JSX.Element;
12
- export declare const IconList: () => import("react").JSX.Element;
13
- export declare const IconPower: () => import("react").JSX.Element;
14
- //# sourceMappingURL=icons.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/internal/icons.tsx"],"names":[],"mappings":"AA0BA,eAAO,MAAM,UAAU,mCAStB,CAAC;AAEF,eAAO,MAAM,QAAQ,mCAMpB,CAAC;AAEF,eAAO,MAAM,UAAU,mCAItB,CAAC;AAEF,eAAO,MAAM,UAAU,mCAMtB,CAAC;AAEF,eAAO,MAAM,UAAU,mCAItB,CAAC;AAEF,eAAO,MAAM,QAAQ,mCAKpB,CAAC;AAEF,eAAO,MAAM,SAAS,mCAIrB,CAAC;AAEF,eAAO,MAAM,YAAY,mCAKxB,CAAC;AAEF,eAAO,MAAM,QAAQ,mCASpB,CAAC;AAEF,eAAO,MAAM,SAAS,mCAIrB,CAAC;AAEF,eAAO,MAAM,SAAS,mCAIrB,CAAC;AAEF,eAAO,MAAM,QAAQ,mCAIpB,CAAC;AAEF,eAAO,MAAM,SAAS,mCAIrB,CAAC"}
@@ -1,7 +0,0 @@
1
- /**
2
- * CSS injected into the shadow root by the React layer. Separate from
3
- * the overlay-marker CSS in `@useclickly/core/styles` so each package owns
4
- * its surface.
5
- */
6
- export declare const REACT_UI_CSS = "\n.clickly-ui, .clickly-ui * { box-sizing: border-box; }\n\n/* \u2500\u2500\u2500 Floating action button (collapsed state) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.clickly-fab {\n position: fixed;\n right: 16px;\n bottom: 16px;\n width: 48px;\n height: 48px;\n border: none;\n border-radius: 999px;\n background: #0f172a;\n color: #f8fafc;\n display: grid;\n place-items: center;\n cursor: pointer;\n pointer-events: auto;\n user-select: none;\n box-shadow:\n 0 8px 24px rgba(0,0,0,0.30),\n 0 0 0 1px rgba(255,255,255,0.06) inset;\n transition: transform 140ms ease, box-shadow 140ms ease;\n z-index: 1;\n}\n.clickly-fab:hover {\n transform: scale(1.06);\n box-shadow:\n 0 10px 28px rgba(0,0,0,0.36),\n 0 0 0 1px rgba(255,255,255,0.10) inset;\n}\n.clickly-fab:active { transform: scale(0.96); }\n.clickly-fab svg { width: 18px; height: 18px; color: #f8fafc; }\n\n.clickly-fab-badge {\n position: absolute;\n top: -2px;\n right: -2px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: #f59e0b;\n color: #0f172a;\n font: 600 11px -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n border-radius: 9px;\n display: grid;\n place-items: center;\n pointer-events: none;\n}\n\n/* \u2500\u2500\u2500 Toolbar (expanded state) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.clickly-toolbar {\n position: fixed;\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 6px;\n height: 44px;\n background: rgba(9, 14, 28, 0.97);\n color: #f8fafc;\n border-radius: 16px;\n font: 13px/1 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n box-shadow:\n 0 16px 40px rgba(0,0,0,0.45),\n 0 0 0 1px rgba(255,255,255,0.08) inset,\n 0 1px 0 rgba(255,255,255,0.06) inset;\n pointer-events: auto;\n user-select: none;\n z-index: 1;\n animation: clickly-fade-in 150ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n@keyframes clickly-fade-in {\n from { opacity: 0; transform: translateY(6px) scale(0.97); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n.clickly-toolbar .grip {\n display: grid;\n place-items: center;\n width: 22px;\n height: 32px;\n color: #475569;\n touch-action: none;\n cursor: grab;\n border-radius: 6px;\n transition: color 120ms ease;\n}\n.clickly-toolbar .grip:hover { color: #94a3b8; }\n.clickly-toolbar .grip:active { cursor: grabbing; }\n\n.clickly-toolbar .divider {\n width: 1px;\n height: 20px;\n background: rgba(255,255,255,0.08);\n margin: 0 3px;\n flex-shrink: 0;\n}\n\n.clickly-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 32px;\n padding: 0 8px;\n background: transparent;\n border: none;\n border-radius: 10px;\n color: #94a3b8;\n cursor: pointer;\n font: inherit;\n transition: background 100ms ease, color 100ms ease;\n position: relative;\n}\n.clickly-btn:hover { background: rgba(255,255,255,0.09); color: #e2e8f0; }\n.clickly-btn:active { background: rgba(255,255,255,0.15); color: #fff; transform: scale(0.96); }\n.clickly-btn.is-active {\n background: #0ea5e9;\n color: #fff;\n box-shadow: 0 0 0 1px rgba(14,165,233,0.4), 0 2px 8px rgba(14,165,233,0.3);\n}\n.clickly-btn.is-active:hover { background: #0284c7; }\n.clickly-btn[disabled] { opacity: 0.28; cursor: not-allowed; pointer-events: none; }\n\n/* Freeze-animations active state \u2014 icy blue */\n.clickly-btn.is-freeze {\n background: rgba(99, 179, 237, 0.18);\n color: #63b3ed;\n box-shadow: 0 0 0 1px rgba(99,179,237,0.35), 0 2px 8px rgba(99,179,237,0.2);\n}\n.clickly-btn.is-freeze:hover { background: rgba(99, 179, 237, 0.26); }\n\n.clickly-btn.icon-only {\n width: 32px;\n padding: 0;\n}\n\n.clickly-btn.primary-pinned {\n background: #10b981;\n color: #fff;\n font-weight: 600;\n font-size: 12px;\n padding: 0 10px;\n gap: 5px;\n box-shadow: 0 0 0 1px rgba(16,185,129,0.4), 0 2px 8px rgba(16,185,129,0.25);\n}\n.clickly-btn.primary-pinned:hover { background: #059669; }\n\n/* \u2500\u2500\u2500 Tooltip \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.clickly-tip {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* Ensures the absolute-positioned counter badge clips correctly */\n isolation: isolate;\n}\n\n.clickly-tip .tip-bubble {\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n background: rgba(15, 23, 42, 0.98);\n color: #f1f5f9;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n padding: 5px 10px;\n border-radius: 8px;\n pointer-events: none;\n opacity: 0;\n transition: opacity 80ms ease;\n transition-delay: 200ms;\n box-shadow: 0 4px 16px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.07) inset;\n display: flex;\n align-items: center;\n gap: 6px;\n z-index: 10;\n}\n\n/* Arrow */\n.clickly-tip .tip-bubble::after {\n content: \"\";\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: rgba(15, 23, 42, 0.98);\n}\n\n.clickly-tip:hover .tip-bubble { opacity: 1; }\n\n.clickly-tip .tip-bubble kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 4px;\n background: rgba(255,255,255,0.12);\n border: 1px solid rgba(255,255,255,0.10);\n border-radius: 4px;\n font: 11px/1 ui-monospace, \"SF Mono\", Menlo, monospace;\n color: #94a3b8;\n}\n\n/* \u2500\u2500\u2500 Shortcuts panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.shortcuts-trigger {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.shortcuts-panel {\n position: absolute;\n bottom: calc(100% + 12px);\n left: 50%;\n transform: translateX(-50%);\n width: 260px;\n background: rgba(9, 14, 28, 0.97);\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 12px;\n box-shadow: 0 16px 40px rgba(0,0,0,0.45);\n padding: 10px;\n z-index: 10;\n animation: clickly-fade-in 100ms ease-out;\n pointer-events: none;\n}\n\n/* Arrow pointing down */\n.shortcuts-panel::after {\n content: \"\";\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 6px solid transparent;\n border-top-color: rgba(9, 14, 28, 0.97);\n}\n\n.shortcuts-title {\n font: 600 11px/1 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n padding: 2px 4px 8px;\n border-bottom: 1px solid rgba(255,255,255,0.06);\n margin-bottom: 6px;\n}\n\n.shortcuts-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 4px;\n border-radius: 6px;\n gap: 8px;\n}\n.shortcuts-row:hover { background: rgba(255,255,255,0.04); }\n\n.shortcuts-label {\n font: 12px/1.4 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n color: #94a3b8;\n flex: 1;\n min-width: 0;\n}\n\n.shortcuts-keys {\n display: flex;\n gap: 3px;\n align-items: center;\n flex-shrink: 0;\n}\n\n.shortcuts-keys kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 5px;\n background: rgba(255,255,255,0.08);\n border: 1px solid rgba(255,255,255,0.10);\n border-bottom-width: 2px;\n border-radius: 5px;\n font: 11px/1 ui-monospace, \"SF Mono\", Menlo, monospace;\n color: #e2e8f0;\n}\n\n/* \u2500\u2500\u2500 Popup & popovers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.clickly-popup, .clickly-popover {\n position: fixed;\n background: #fff;\n color: #0f172a;\n border-radius: 10px;\n box-shadow: 0 12px 32px rgba(2,6,23,0.18), 0 0 0 1px rgba(15,23,42,0.06);\n font: 13px/1.5 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n pointer-events: auto;\n z-index: 2;\n animation: clickly-fade-in 120ms ease-out;\n}\n\n.clickly-popup {\n width: 320px;\n padding: 12px;\n max-height: calc(100vh - 80px);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n/* \u2500\u2500\u2500 Shared inner styles \u2014 apply to both popup and pin-edit \u2500\u2500\u2500 */\n\n.clickly-popup .popup-header,\n.pin-edit .popup-header {\n display: flex;\n align-items: center;\n gap: 5px;\n margin-bottom: 8px;\n padding: 4px 2px;\n border-radius: 4px;\n cursor: pointer;\n user-select: none;\n color: #475569;\n font-size: 11px;\n font-family: ui-monospace, \"SF Mono\", Menlo, monospace;\n transition: background 80ms ease;\n}\n.clickly-popup .popup-header:hover,\n.pin-edit .popup-header:hover { background: #f1f5f9; }\n\n.clickly-popup .popup-chevron,\n.pin-edit .popup-chevron {\n font-size: 12px;\n color: #94a3b8;\n flex-shrink: 0;\n width: 12px;\n text-align: center;\n}\n\n.clickly-popup .popup-label,\n.pin-edit .popup-label {\n flex: 1;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n/* Edit-mode toggle button \u2014 top-right of CSS panel header */\n.clickly-popup .popup-edit-toggle {\n flex-shrink: 0;\n display: grid;\n place-items: center;\n width: 20px;\n height: 20px;\n background: transparent;\n border: 1px solid #e2e8f0;\n border-radius: 5px;\n color: #94a3b8;\n cursor: pointer;\n padding: 0;\n margin-left: auto;\n transition: background 100ms ease, color 100ms ease, border-color 100ms ease;\n}\n.clickly-popup .popup-edit-toggle:hover {\n background: #f1f5f9;\n color: #475569;\n border-color: #cbd5e1;\n}\n.clickly-popup .popup-edit-toggle.is-editing {\n background: #0ea5e9;\n color: #fff;\n border-color: #0ea5e9;\n}\n.clickly-popup .popup-edit-toggle.is-editing:hover {\n background: #0284c7;\n}\n\n/* Computed-styles panel */\n.clickly-popup .popup-styles,\n.pin-edit .popup-styles {\n margin-bottom: 8px;\n padding: 8px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n font-family: ui-monospace, \"SF Mono\", Menlo, monospace;\n font-size: 11px;\n max-height: 160px;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n.clickly-popup .style-row,\n.pin-edit .style-row {\n display: flex;\n align-items: center;\n gap: 6px;\n line-height: 1.7;\n border-radius: 4px;\n padding: 0 2px;\n transition: background 80ms ease;\n}\n\n.clickly-popup .style-row--changed,\n.pin-edit .style-row--changed {\n background: rgba(245, 158, 11, 0.10);\n}\n\n.clickly-popup .style-key,\n.pin-edit .style-key {\n color: #7c3aed;\n flex-shrink: 0;\n min-width: 90px;\n font-size: 11px;\n}\n\n.clickly-popup .style-val,\n.pin-edit .style-val {\n color: #0f172a;\n font-size: 11px;\n word-break: break-all;\n flex: 1;\n}\n\n/* Editable value input \u2014 live CSS preview */\n.clickly-popup .style-val-input {\n flex: 1;\n min-width: 0;\n background: transparent;\n border: none;\n border-bottom: 1px solid transparent;\n color: #0f172a;\n font: 11px/1.7 ui-monospace, \"SF Mono\", Menlo, monospace;\n padding: 0;\n outline: none;\n transition: border-color 100ms ease;\n word-break: break-all;\n}\n.clickly-popup .style-val-input:focus {\n border-bottom-color: #0ea5e9;\n background: rgba(14, 165, 233, 0.05);\n border-radius: 2px 2px 0 0;\n}\n\n/* Revert button shown only on changed rows */\n.clickly-popup .style-revert-btn {\n flex-shrink: 0;\n background: transparent;\n border: none;\n color: #94a3b8;\n font-size: 13px;\n cursor: pointer;\n padding: 0 2px;\n line-height: 1;\n border-radius: 3px;\n transition: color 80ms ease, background 80ms ease;\n}\n.clickly-popup .style-revert-btn:hover {\n color: #f59e0b;\n background: rgba(245,158,11,0.12);\n}\n\n/* Hint text at bottom of CSS panel */\n.clickly-popup .style-hint,\n.pin-edit .style-hint {\n margin-top: 6px;\n padding-top: 6px;\n border-top: 1px solid #e2e8f0;\n font-size: 10.5px;\n color: #94a3b8;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n line-height: 1.4;\n}\n\n.clickly-popup textarea,\n.pin-edit textarea {\n width: 100%;\n min-height: 64px;\n max-height: 160px;\n padding: 8px;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n resize: vertical;\n font: inherit;\n color: inherit;\n}\n.clickly-popup textarea:focus,\n.pin-edit textarea:focus {\n outline: none;\n border-color: #0ea5e9;\n box-shadow: 0 0 0 3px rgba(14,165,233,0.18);\n}\n\n.clickly-popup .row,\n.pin-edit .row {\n display: flex;\n justify-content: flex-end;\n gap: 6px;\n margin-top: 10px;\n}\n\n.clickly-popup .row .ghost,\n.pin-edit .row .ghost {\n background: transparent;\n color: #475569;\n border: 1px solid #e2e8f0;\n}\n.clickly-popup .row .ghost:hover,\n.pin-edit .row .ghost:hover { background: #f8fafc; }\n\n.clickly-popup .row .primary,\n.pin-edit .row .primary {\n background: #0ea5e9;\n color: #fff;\n border: none;\n}\n.clickly-popup .row .primary:hover,\n.pin-edit .row .primary:hover { background: #0284c7; }\n.clickly-popup .row button,\n.pin-edit .row button {\n height: 28px;\n padding: 0 12px;\n border-radius: 6px;\n font: inherit;\n cursor: pointer;\n}\n\n/* Old popover kept for any legacy use */\n.clickly-popover { width: 260px; padding: 12px; }\n\n/* \u2500\u2500\u2500 Settings panel (redesigned) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.clickly-settings {\n position: fixed;\n width: 284px;\n background: #fff;\n border-radius: 14px;\n box-shadow: 0 16px 48px rgba(2,6,23,0.20), 0 0 0 1px rgba(15,23,42,0.07);\n font: 13px/1.5 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n color: #0f172a;\n pointer-events: auto;\n z-index: 2;\n animation: clickly-fade-in 150ms cubic-bezier(0.16, 1, 0.3, 1);\n overflow: hidden;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 14px 12px;\n border-bottom: 1px solid #f1f5f9;\n}\n\n.settings-title {\n font-size: 13px;\n font-weight: 600;\n color: #0f172a;\n letter-spacing: -0.01em;\n}\n\n.settings-close {\n display: grid;\n place-items: center;\n width: 24px;\n height: 24px;\n background: #f1f5f9;\n border: none;\n border-radius: 6px;\n color: #64748b;\n cursor: pointer;\n padding: 0;\n transition: background 100ms, color 100ms;\n}\n.settings-close:hover { background: #e2e8f0; color: #0f172a; }\n.settings-close svg { width: 13px; height: 13px; }\n\n.settings-section { padding: 10px 14px; }\n\n.settings-divider {\n height: 1px;\n background: #f1f5f9;\n margin: 0;\n}\n\n.settings-label {\n display: flex;\n flex-direction: column;\n gap: 2px;\n font-size: 13px;\n font-weight: 500;\n color: #1e293b;\n margin-bottom: 8px;\n}\n\n.settings-hint {\n font-size: 11.5px;\n font-weight: 400;\n color: #94a3b8;\n}\n\n.settings-select {\n width: 100%;\n padding: 7px 10px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n font: inherit;\n font-size: 13px;\n color: #1e293b;\n cursor: pointer;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 10px center;\n padding-right: 32px;\n transition: border-color 120ms, box-shadow 120ms;\n}\n.settings-select:focus {\n outline: none;\n border-color: #0ea5e9;\n box-shadow: 0 0 0 3px rgba(14,165,233,0.15);\n background-color: #fff;\n}\n\n.settings-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 6px 0;\n}\n.settings-row + .settings-row {\n border-top: 1px solid #f8fafc;\n}\n\n.settings-row-label {\n display: flex;\n flex-direction: column;\n gap: 2px;\n font-size: 13px;\n font-weight: 500;\n color: #1e293b;\n min-width: 0;\n}\n\n/* Toggle switch */\n.clickly-toggle {\n position: relative;\n flex-shrink: 0;\n width: 38px;\n height: 22px;\n cursor: pointer;\n}\n.clickly-toggle input {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n}\n.toggle-track {\n position: absolute;\n inset: 0;\n background: #e2e8f0;\n border-radius: 11px;\n transition: background 180ms ease;\n}\n.toggle-track::after {\n content: \"\";\n position: absolute;\n top: 3px;\n left: 3px;\n width: 16px;\n height: 16px;\n background: #fff;\n border-radius: 50%;\n box-shadow: 0 1px 4px rgba(0,0,0,0.2);\n transition: transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n.clickly-toggle input:checked + .toggle-track {\n background: #0ea5e9;\n}\n.clickly-toggle input:checked + .toggle-track::after {\n transform: translateX(16px);\n}\n\n/* Color picker */\n.settings-color-wrap {\n display: flex;\n align-items: center;\n gap: 0;\n cursor: pointer;\n border-radius: 8px;\n overflow: hidden;\n border: 1px solid #e2e8f0;\n flex-shrink: 0;\n}\n.settings-color-wrap input[type=\"color\"] {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n pointer-events: none;\n}\n.color-swatch {\n display: block;\n width: 32px;\n height: 24px;\n border-radius: 7px;\n border: 1px solid rgba(0,0,0,0.08);\n transition: transform 100ms ease;\n}\n.settings-color-wrap:hover .color-swatch { transform: scale(1.08); }\n\n.clickly-counter {\n /* Float as a badge \u2014 positioned absolutely so it doesn't widen the button */\n position: absolute;\n top: -5px;\n right: -5px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: #f59e0b;\n color: #0f172a;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n border: 1.5px solid rgba(9, 14, 28, 0.97);\n}\n\n/* \u2500\u2500\u2500 Annotation pins (persistent numbered markers) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.clickly-pin {\n position: fixed;\n width: 24px;\n height: 24px;\n border-radius: 999px;\n background: #10b981;\n color: #fff;\n font: 700 11px/24px -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n text-align: center;\n cursor: pointer;\n pointer-events: auto;\n user-select: none;\n box-shadow: 0 2px 8px rgba(16,185,129,0.4), 0 0 0 2px #fff;\n z-index: 10;\n transition: transform 120ms cubic-bezier(0.34,1.56,0.64,1), box-shadow 120ms ease;\n}\n.clickly-pin:hover {\n transform: scale(1.18);\n box-shadow: 0 4px 16px rgba(16,185,129,0.5), 0 0 0 2px #fff;\n}\n.clickly-pin-num { display: block; }\n\n/* \u2500\u2500\u2500 Pin hover preview (dark tooltip) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.pin-preview {\n position: absolute;\n right: calc(100% + 10px);\n top: 50%;\n transform: translateY(-50%);\n width: 220px;\n padding: 8px 10px;\n background: rgba(9, 14, 28, 0.96);\n color: #f1f5f9;\n border-radius: 10px;\n box-shadow: 0 8px 24px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.07) inset;\n font: 12px/1.45 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n text-align: left;\n cursor: default;\n pointer-events: none;\n z-index: 11;\n animation: clickly-fade-in 100ms ease-out;\n white-space: normal;\n}\n\n.pin-preview-meta {\n font-size: 10.5px;\n color: #64748b;\n font-family: ui-monospace, \"SF Mono\", Menlo, monospace;\n margin-bottom: 4px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.pin-preview-comment {\n font-size: 12px;\n color: #e2e8f0;\n word-break: break-word;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* \u2500\u2500\u2500 Pin edit popup \u2014 same white card as .clickly-popup \u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.pin-edit {\n /* Positioning: floats to the LEFT of the pin */\n position: absolute;\n right: calc(100% + 12px);\n top: 50%;\n transform: translateY(-50%);\n /* Appearance: identical to .clickly-popup */\n width: 300px;\n padding: 12px;\n background: #fff;\n color: #0f172a;\n border-radius: 10px;\n box-shadow: 0 12px 32px rgba(2,6,23,0.18), 0 0 0 1px rgba(15,23,42,0.06);\n font: 13px/1.5 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n text-align: left;\n cursor: default;\n z-index: 11;\n animation: clickly-fade-in 120ms cubic-bezier(0.16,1,0.3,1);\n /* Allow inner popup-styles to scroll */\n max-height: 80vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n/* Reuse .clickly-popup textarea inside pin-edit */\n.pin-edit textarea {\n width: 100%;\n min-height: 64px;\n max-height: 120px;\n padding: 8px;\n border: 1px solid #e2e8f0;\n border-radius: 6px;\n resize: vertical;\n font: inherit;\n color: inherit;\n background: #fff;\n box-sizing: border-box;\n}\n.pin-edit textarea:focus {\n outline: none;\n border-color: #0ea5e9;\n box-shadow: 0 0 0 3px rgba(14,165,233,0.18);\n}\n\n/* Actions row */\n.pin-edit-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 10px;\n}\n\n.pin-edit-delete {\n display: grid;\n place-items: center;\n width: 28px;\n height: 28px;\n flex-shrink: 0;\n background: transparent;\n border: 1px solid #fee2e2;\n border-radius: 6px;\n color: #ef4444;\n cursor: pointer;\n padding: 0;\n transition: background 100ms, border-color 100ms;\n}\n.pin-edit-delete:hover { background: #fef2f2; border-color: #fca5a5; }\n.pin-edit-delete svg { width: 13px; height: 13px; }\n\n/* \u2500\u2500\u2500 Annotation list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.clickly-list {\n position: fixed;\n width: 320px;\n max-height: 55vh;\n background: #fff;\n border-radius: 14px;\n box-shadow: 0 16px 48px rgba(2,6,23,0.20), 0 0 0 1px rgba(15,23,42,0.07);\n color: #0f172a;\n font: 13px/1.5 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n pointer-events: auto;\n z-index: 2;\n animation: clickly-fade-in 150ms cubic-bezier(0.16, 1, 0.3, 1);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.list-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 14px 10px;\n border-bottom: 1px solid #f1f5f9;\n flex-shrink: 0;\n}\n\n.list-title {\n font-size: 13px;\n font-weight: 600;\n color: #0f172a;\n letter-spacing: -0.01em;\n flex: 1;\n}\n\n.list-count {\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n background: #f1f5f9;\n color: #475569;\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\n display: grid;\n place-items: center;\n}\n\n.list-items {\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n}\n\n.list-empty {\n padding: 24px;\n text-align: center;\n color: #94a3b8;\n font-size: 12px;\n}\n\n/* \u2500\u2500\u2500 Annotation card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.list-card {\n padding: 10px 12px;\n border-bottom: 1px solid #f8fafc;\n transition: background 80ms ease;\n}\n.list-card:last-child { border-bottom: none; }\n.list-card:hover { background: #fafafa; }\n\n.list-card-header {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 4px;\n}\n\n.list-card-num {\n font-size: 11px;\n font-weight: 700;\n color: #94a3b8;\n flex-shrink: 0;\n min-width: 20px;\n}\n\n.list-card-path {\n flex: 1;\n min-width: 0;\n font-family: ui-monospace, \"SF Mono\", Menlo, monospace;\n font-size: 10.5px;\n color: #475569;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.list-card-actions {\n display: flex;\n gap: 3px;\n flex-shrink: 0;\n}\n\n.list-action-btn {\n display: grid;\n place-items: center;\n width: 24px;\n height: 24px;\n background: transparent;\n border: none;\n border-radius: 6px;\n color: #94a3b8;\n cursor: pointer;\n padding: 0;\n transition: background 80ms ease, color 80ms ease;\n}\n.list-action-btn svg { width: 12px; height: 12px; }\n.list-action-btn:hover { background: #f1f5f9; color: #475569; }\n.list-action-btn.copied { color: #10b981; }\n.list-action-btn.list-action-delete:hover { background: #fef2f2; color: #ef4444; }\n\n.list-card-comment {\n font-size: 12px;\n color: #1e293b;\n line-height: 1.45;\n margin: 0 0 6px;\n word-break: break-word;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* CSS changes badge */\n.list-card-css {\n background: rgba(124, 58, 237, 0.05);\n border: 1px solid rgba(124, 58, 237, 0.12);\n border-radius: 6px;\n padding: 5px 8px;\n margin-top: 4px;\n}\n\n.list-card-css-label {\n display: block;\n font-size: 10px;\n font-weight: 600;\n color: #7c3aed;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n margin-bottom: 3px;\n}\n\n.list-card-css-code {\n font-family: ui-monospace, \"SF Mono\", Menlo, monospace;\n font-size: 10px;\n color: #475569;\n line-height: 1.5;\n margin: 0;\n white-space: pre-wrap;\n word-break: break-all;\n max-height: 60px;\n overflow: hidden;\n}\n";
7
- //# sourceMappingURL=styles.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/internal/styles.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,YAAY,oo0BAshCxB,CAAC"}
@@ -1,5 +0,0 @@
1
- import type { Annotation } from "@useclickly/core";
2
- import type { OutputDetail } from "../state/settings";
3
- export declare function annotationsToMarkdown(annotations: Annotation[], detail?: OutputDetail): string;
4
- export declare function formatOne(a: Annotation, index: number, detail: OutputDetail): string;
5
- //# sourceMappingURL=markdown.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/output/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,UAAU,EAAE,EACzB,MAAM,GAAE,YAAyB,GAChC,MAAM,CAGR;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAkCpF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=markdown.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"markdown.test.d.ts","sourceRoot":"","sources":["../../src/output/markdown.test.ts"],"names":[],"mappings":""}
@@ -1,21 +0,0 @@
1
- import type { Annotation } from "@useclickly/core";
2
- export interface AnnotationsStore {
3
- byId: Record<string, Annotation>;
4
- order: string[];
5
- add: (a: Annotation) => void;
6
- remove: (id: string) => void;
7
- update: (id: string, patch: Partial<Annotation>) => void;
8
- clear: () => void;
9
- /** Imperative read. Hooks should use `useAnnotationsList()` instead. */
10
- list: () => Annotation[];
11
- }
12
- export declare const useAnnotations: import("zustand").UseBoundStore<import("zustand").StoreApi<AnnotationsStore>>;
13
- /**
14
- * Subscribe to the annotation list with shallow equality — re-renders
15
- * only when items add/remove/reorder/update. Always use this from
16
- * component code; never call `useAnnotations(s => s.list())`, which
17
- * returns a new array reference on every store change and infinite-loops
18
- * `useSyncExternalStore`.
19
- */
20
- export declare function useAnnotationsList(): Annotation[];
21
- //# sourceMappingURL=annotations.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/state/annotations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,EAAE,CAAC;IAEhB,GAAG,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7B,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACzD,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB,wEAAwE;IACxE,IAAI,EAAE,MAAM,UAAU,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,cAAc,+EA+BxB,CAAC;AAEJ;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,EAAE,CAIjD"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=annotations.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"annotations.test.d.ts","sourceRoot":"","sources":["../../src/state/annotations.test.ts"],"names":[],"mappings":""}
@@ -1,14 +0,0 @@
1
- export type OutputDetail = "compact" | "standard" | "detailed" | "forensic";
2
- export interface Settings {
3
- outputDetail: OutputDetail;
4
- copyOnAdd: boolean;
5
- showReactComponents: boolean;
6
- markerColor: string;
7
- }
8
- export interface SettingsStore extends Settings {
9
- set: (patch: Partial<Settings>) => void;
10
- reset: () => void;
11
- }
12
- export declare const DEFAULTS: Settings;
13
- export declare const useSettings: import("zustand").UseBoundStore<import("zustand").StoreApi<SettingsStore>>;
14
- //# sourceMappingURL=settings.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/state/settings.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;AAE5E,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAc,SAAQ,QAAQ;IAC7C,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IACxC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,QAAQ,EAAE,QAKtB,CAAC;AAyBF,eAAO,MAAM,WAAW,4EAYrB,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=settings.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"settings.test.d.ts","sourceRoot":"","sources":["../../src/state/settings.test.ts"],"names":[],"mappings":""}
@@ -1,7 +0,0 @@
1
- import type { EngineState, SelectionEngine } from "@useclickly/core";
2
- /**
3
- * React-friendly accessor for the SelectionEngine's external store.
4
- * Engine is already a `Subscribable<EngineState>` — zero adapter code.
5
- */
6
- export declare function useEngineState(engine: SelectionEngine | null): EngineState;
7
- //# sourceMappingURL=useEngineState.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useEngineState.d.ts","sourceRoot":"","sources":["../../src/state/useEngineState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAErE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,GAAG,WAAW,CAM1E"}
@@ -1,7 +0,0 @@
1
- /**
2
- * jsdom test setup. Phase 5 ships only state/store unit tests — DOM
3
- * component tests arrive in Phase 12 via Playwright. The setup is kept
4
- * so future component tests have a single place to extend matchers.
5
- */
6
- export {};
7
- //# sourceMappingURL=setup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,CAAC"}