@satanwagen/reviewkit 0.1.2 → 0.1.3

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 (56) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/README.md +134 -63
  3. package/dist/activate.cjs +150 -0
  4. package/dist/activate.cjs.map +1 -0
  5. package/dist/activate.d.cts +59 -0
  6. package/dist/activate.d.ts +59 -0
  7. package/dist/activate.js +21 -0
  8. package/dist/activate.js.map +1 -0
  9. package/dist/{chunk-4YNLMSCK.js → chunk-DG6O5XIC.js} +36 -10
  10. package/dist/chunk-DG6O5XIC.js.map +1 -0
  11. package/dist/chunk-ETAGGIDN.js +119 -0
  12. package/dist/chunk-ETAGGIDN.js.map +1 -0
  13. package/dist/{chunk-YWBFAV57.js → chunk-NSXRFM75.js} +853 -1544
  14. package/dist/chunk-NSXRFM75.js.map +1 -0
  15. package/dist/chunk-Q7U43PXE.js +36 -0
  16. package/dist/chunk-Q7U43PXE.js.map +1 -0
  17. package/dist/client/index.cjs +4530 -4237
  18. package/dist/client/index.cjs.map +1 -1
  19. package/dist/client/index.d.cts +1 -1
  20. package/dist/client/index.d.ts +1 -1
  21. package/dist/client/index.js +49 -3
  22. package/dist/client/index.js.map +1 -1
  23. package/dist/effects-EWKHKUDP.js +851 -0
  24. package/dist/effects-EWKHKUDP.js.map +1 -0
  25. package/dist/index-BUSmAweg.d.ts +77 -0
  26. package/dist/index-Dl2Fl0qr.d.cts +77 -0
  27. package/dist/index.cjs +4544 -4256
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +35 -3
  32. package/dist/index.js.map +1 -1
  33. package/dist/lazy.cjs +8988 -0
  34. package/dist/lazy.cjs.map +1 -0
  35. package/dist/lazy.d.cts +7 -0
  36. package/dist/lazy.d.ts +7 -0
  37. package/dist/lazy.js +8 -0
  38. package/dist/lazy.js.map +1 -0
  39. package/dist/next.cjs +8989 -0
  40. package/dist/next.cjs.map +1 -0
  41. package/dist/next.d.cts +4 -0
  42. package/dist/next.d.ts +4 -0
  43. package/dist/next.js +9 -0
  44. package/dist/next.js.map +1 -0
  45. package/dist/schema.cjs +53 -16
  46. package/dist/schema.cjs.map +1 -1
  47. package/dist/schema.d.cts +20 -5
  48. package/dist/schema.d.ts +20 -5
  49. package/dist/schema.js +30 -2
  50. package/dist/schema.js.map +1 -1
  51. package/package.json +21 -8
  52. package/cli/emblema-sync.mjs +0 -675
  53. package/dist/chunk-4YNLMSCK.js.map +0 -1
  54. package/dist/chunk-YWBFAV57.js.map +0 -1
  55. package/dist/index-BbucFgZi.d.ts +0 -49
  56. package/dist/index-CBlJrKkm.d.cts +0 -49
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/activate.ts","../src/client/env.ts","../src/client/pointer.ts","../src/client/tokens.ts","../src/client/styles.ts","../src/client/target.ts","../src/integrations/emblema.ts","../src/schema.ts","../src/client/id.ts","../src/client/store.tsx","../src/client/persist.ts","../src/client/reveal.ts","../src/client/preview.ts","../src/client/effectCatalog.ts","../src/client/effects.ts","../src/client/effectsLazy.ts","../src/client/exportSession.ts","../src/client/shortcuts.ts","../src/client/emblemaPush.ts","../realtime/client/rkSync.ts","../src/client/identity.ts","../src/client/sync.ts","../src/client/dragPosition.ts","../src/client/components/Badge.tsx","../src/client/components/icons.tsx","../src/client/components/CheatSheet.tsx","../src/client/components/EmblemaConnect.tsx","../src/client/components/CoachMark.tsx","../src/client/components/Confirm.tsx","../src/client/position.ts","../src/client/useAnchored.ts","../src/client/components/ImageEditor.tsx","../src/client/components/InlineEditor.tsx","../src/client/components/NoteComposer.tsx","../src/client/components/Panel.tsx","../src/client/components/Presence.tsx","../src/client/components/QuickComment.tsx","../src/client/components/PickLayer.tsx","../src/client/components/Pins.tsx","../src/client/components/Toolbar.tsx","../src/client/components/Toast.tsx","../src/client/App.tsx","../src/client/ReviewKit.tsx","../src/client/index.ts","../src/next.tsx","../src/LazyReviewKit.tsx"],"sourcesContent":["/**\n * `@satanwagen/reviewkit/activate` — the activation decision, React-free.\n *\n * Hosts that lazy-load the review layer need to know BEFORE importing any\n * React code whether this page load should show the layer at all. This\n * module is that decision, and the only supported way to read ReviewKit's\n * persisted opt-in state (the sessionStorage format is private and may\n * change; `shouldActivate` will not).\n *\n * Rules (no exceptions, no environment sniffing):\n *\n * - `enabled: false` → never.\n * - hostname ∉ `allowedHosts` → never (when an allowlist is given).\n * - `?review=off` → never; also clears the in-tab opt-in.\n * - no `token` configured → never. `?review=x` without a token logs\n * a warning and stays off.\n * - `?review=<token>` → yes.\n * - valid in-tab sticky session → yes (started by an earlier `?review=<token>`\n * load in this tab, bound to the token,\n * ~4 h sliding expiry).\n * - `devAutoOn: true` → yes, regardless of URL/token. The host\n * decides when (e.g. `import.meta.env.DEV`);\n * the library never reads NODE_ENV.\n */\n\nexport interface ActivationOptions {\n /** The review token. Without it the layer never activates (except `devAutoOn`). */\n token?: string;\n /** Master switch. `false` short-circuits everything. Default `true`. */\n enabled?: boolean;\n /** Hostname allowlist with `*` wildcards. Unset = any host. */\n allowedHosts?: string[];\n /** Force the layer on for this page load (dev convenience; host-controlled). */\n devAutoOn?: boolean;\n}\n\n/** @internal sessionStorage key of the per-tab opt-in. Format is private. */\nexport const STICKY_KEY = 'review-kit:sticky';\nconst STICKY_TTL_MS = 4 * 60 * 60 * 1000;\n\ninterface Sticky {\n token: string;\n until: number;\n}\n\nfunction safeRemove(storage: () => Storage, key: string): void {\n try {\n storage().removeItem(key);\n } catch {\n /* storage unavailable */\n }\n}\n\nfunction readSticky(): Sticky | null {\n try {\n const raw = window.sessionStorage.getItem(STICKY_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n typeof (parsed as Sticky).token === 'string' &&\n typeof (parsed as Sticky).until === 'number'\n ) {\n return parsed as Sticky;\n }\n } catch {\n /* unreadable */\n }\n return null;\n}\n\n/** @internal Is the per-tab opt-in present, unexpired and bound to `token`? */\nexport function isStickyEnabled(token: string | undefined): boolean {\n if (token === undefined || token === '') return false;\n const sticky = readSticky();\n if (!sticky) return false;\n if (sticky.until < Date.now() || sticky.token !== token) {\n safeRemove(() => window.sessionStorage, STICKY_KEY);\n return false;\n }\n return true;\n}\n\n/** @internal Start / renew / end the per-tab opt-in. No-op without a token. */\nexport function setSticky(token: string | undefined, on: boolean): void {\n try {\n if (on && token !== undefined && token !== '') {\n const value: Sticky = { token, until: Date.now() + STICKY_TTL_MS };\n window.sessionStorage.setItem(STICKY_KEY, JSON.stringify(value));\n } else {\n window.sessionStorage.removeItem(STICKY_KEY);\n }\n } catch {\n /* storage unavailable — the choice just won't persist */\n }\n}\n\n/** @internal Clear the per-tab opt-in. */\nexport function clearSticky(): void {\n safeRemove(() => window.sessionStorage, STICKY_KEY);\n}\n\n/** @internal The raw `?review` value of the current URL, or null. */\nexport function reviewParam(): string | null {\n try {\n return new URLSearchParams(window.location.search).get('review');\n } catch {\n return null;\n }\n}\n\n/** Does the current hostname match one of the allowed patterns?\n * '*' matches any characters ('*.dev.example' → a.dev.example, a.b.dev.example). */\nexport function hostAllowed(allowedHosts: string[] | undefined): boolean {\n if (!allowedHosts || allowedHosts.length === 0) return true;\n let host = '';\n try {\n host = window.location.hostname.toLowerCase();\n } catch {\n return false;\n }\n return allowedHosts.some((pattern) => {\n const regex = new RegExp(\n '^' +\n pattern\n .toLowerCase()\n .split('*')\n .map((part) => part.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n .join('.*') +\n '$',\n );\n return regex.test(host);\n });\n}\n\n/** Loopback hosts where a missing allowlist is expected, not a smell. */\nexport function isLocalHost(): boolean {\n try {\n const host = window.location.hostname.toLowerCase();\n return host === 'localhost' || host === '127.0.0.1' || host === '[::1]' || host.endsWith('.localhost');\n } catch {\n return false;\n }\n}\n\nlet warnedNoToken = false;\nlet warnedMismatch = false;\n\n/**\n * Should the review layer be active for this page load?\n *\n * Read-only except for one deliberate side effect: `?review=off` clears the\n * in-tab opt-in, so a host that gates a lazy import on this function still\n * honours \"off\" on the next load. Safe to call on the server (returns false).\n */\nexport function shouldActivate(options: ActivationOptions = {}): boolean {\n if (typeof window === 'undefined') return false;\n if (options.enabled === false) return false;\n if (!hostAllowed(options.allowedHosts)) return false;\n\n const param = reviewParam();\n if (param === 'off') {\n clearSticky();\n return false;\n }\n if (options.devAutoOn === true) return true;\n\n const token = options.token;\n if (token === undefined || token === '') {\n if (param !== null && param !== '' && !warnedNoToken) {\n warnedNoToken = true;\n console.warn(\n '[review-kit] `?review` is present but no `token` is configured; the layer stays off. ' +\n 'Pass `token` to <ReviewKit /> (or `devAutoOn` for local development).',\n );\n }\n return false;\n }\n if (param !== null && param !== '') {\n if (param === token) return true;\n if (!warnedMismatch) {\n warnedMismatch = true;\n console.warn('[review-kit] `?review` token does not match the configured token; staying inactive.');\n }\n return false;\n }\n return isStickyEnabled(token);\n}\n","/**\n * Activation glue for the mounted layer.\n *\n * The decision itself lives in `src/activate.ts` (React-free, public as\n * `@satanwagen/reviewkit/activate`). This module adds the side effects a\n * real mount needs: starting/renewing the per-tab sticky session on a valid\n * link, cleaning legacy keys from older versions, and the \"End review\"\n * teardown. Nothing here reads NODE_ENV or a localStorage dev flag any more —\n * without a token the layer is simply off (see CHANGELOG 0.1.3).\n */\n\nimport type { ActivationOptions } from '../activate';\nimport { clearSticky, hostAllowed, isLocalHost, isStickyEnabled, reviewParam, setSticky, shouldActivate } from '../activate';\n\nexport { hostAllowed, isStickyEnabled, setSticky };\n\nconst LEGACY_SESSION_KEY = 'review-kit:active';\nconst LEGACY_LOCAL_FLAG = 'reviewkit';\n\n/** Fired on window when the reviewer ends the session from the UI. */\nexport const DEACTIVATE_EVENT = 'review-kit:deactivate';\n\nfunction safeRemove(storage: () => Storage, key: string): void {\n try {\n storage().removeItem(key);\n } catch {\n /* storage unavailable */\n }\n}\n\n/** Pre-0.1.3 auto-persist keys: never activate anything, always cleaned up. */\nfunction clearLegacyKeys(): void {\n safeRemove(() => window.sessionStorage, LEGACY_SESSION_KEY);\n safeRemove(() => window.localStorage, LEGACY_LOCAL_FLAG);\n}\n\n/**\n * End the review session from the UI: clear every persisted activation\n * trace, drop `?review` from the URL (so a reload stays clean) and tell the\n * mounted layer to unmount.\n */\nexport function deactivateReview(): void {\n clearSticky();\n clearLegacyKeys();\n try {\n const url = new URL(window.location.href);\n if (url.searchParams.has('review')) {\n url.searchParams.delete('review');\n window.history.replaceState(window.history.state, '', url.toString());\n }\n } catch {\n /* leave the URL alone */\n }\n try {\n window.dispatchEvent(new CustomEvent(DEACTIVATE_EVENT));\n } catch {\n /* ignore */\n }\n}\n\nlet warnedNoAllowlist = false;\n\n/**\n * Decide whether the review UI should be active for this page load and\n * apply the mount-time side effects:\n *\n * - a valid `?review=<token>` starts the per-tab sticky session,\n * - an active sticky session is renewed (sliding expiry),\n * - legacy keys are always removed,\n * - a token activation on a public hostname without `allowedHosts` logs a\n * one-time console warning (see README \"Production recipe\").\n */\nexport function resolveActivation(options: ActivationOptions): boolean {\n if (typeof window === 'undefined') return false;\n clearLegacyKeys();\n const active = shouldActivate(options);\n if (!active) return false;\n\n const token = options.token;\n const param = reviewParam();\n if (token !== undefined && token !== '' && (param === token || isStickyEnabled(token))) {\n setSticky(token, true);\n if (param === token && !options.allowedHosts?.length && !isLocalHost() && !warnedNoAllowlist) {\n warnedNoAllowlist = true;\n console.warn(\n '[review-kit] Review mode activated by URL token on a public hostname with no `allowedHosts`. ' +\n 'For production pass `allowedHosts` next to `token` so the layer cannot be opened on hosts you did not intend.',\n );\n }\n }\n return true;\n}\n\n/* ------------------------------------------------------------------ */\n/* Cross-page focus hand-off */\n/* ------------------------------------------------------------------ */\n\nconst FOCUS_KEY = 'review-kit:focus';\n\n/** Remember which item to select/scroll to after the next page load\n * (clicking a panel row that lives on another route navigates there). */\nexport function rememberFocusItem(id: string): void {\n try {\n window.sessionStorage.setItem(FOCUS_KEY, JSON.stringify({ id, until: Date.now() + 60_000 }));\n } catch {\n /* storage unavailable — the click still navigates, just without focus */\n }\n}\n\n/** One-shot read of the pending focus item (cleared on read, TTL-guarded). */\nexport function takeFocusItem(): string | null {\n try {\n const raw = window.sessionStorage.getItem(FOCUS_KEY);\n if (!raw) return null;\n window.sessionStorage.removeItem(FOCUS_KEY);\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n typeof (parsed as { id?: unknown }).id === 'string' &&\n typeof (parsed as { until?: unknown }).until === 'number' &&\n (parsed as { until: number }).until >= Date.now()\n ) {\n return (parsed as { id: string }).id;\n }\n } catch {\n /* unreadable */\n }\n return null;\n}\n","/** Last known pointer position + shadow-root handle, shared across modules\n * (the `/` composer and the cursor sender both need them outside React). */\n\nexport const lastPointer = { x: 0, y: 0, has: false };\n\nexport function trackPointer(): () => void {\n const onMove = (event: PointerEvent) => {\n lastPointer.x = event.clientX;\n lastPointer.y = event.clientY;\n lastPointer.has = true;\n };\n document.addEventListener('pointermove', onMove, { passive: true });\n return () => document.removeEventListener('pointermove', onMove);\n}\n\n/** The mounted layer's .rk-root element (for effect layers). */\nexport let layerRoot: HTMLElement | null = null;\nexport function setLayerRoot(el: HTMLElement | null): void {\n layerRoot = el;\n}\n","/**\n * Design tokens — the single source for all plugin styling.\n * Emitted as CSS custom properties on the shadow root; every rule in\n * `styles.ts` reads from these. No color, size or curve may appear in\n * `styles.ts` that isn't derived from here.\n *\n * The system: a quiet, native-feeling overlay. One periwinkle accent\n * (complementary to the host site's greens, so it reads as \"system\", not\n * \"content\"), neutral vibrancy surfaces with backdrop blur + saturation,\n * hairline borders, layered shadows with a top inner highlight, an\n * 8px-based spacing grid and a five-step type scale.\n * Status colors are reserved for state and always paired with an icon or\n * label — contrast against both surfaces validated ≥ 3:1 (AA for text\n * usage ≥ 4.5:1 checked per token).\n */\n\nexport const sharedTokens = {\n /* type — system stack; the host page's fonts never leak into the layer */\n fontStack:\n \"-apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Inter, Roboto, 'Helvetica Neue', Arial, sans-serif\",\n monoStack: \"ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace\",\n fsXs: '11px',\n fsS: '12px',\n fsM: '13px',\n fsL: '15px',\n fsXl: '17px',\n trackTight: '-0.02em',\n trackWide: '0.06em',\n\n /* radii — capsule for bars, 12–16 for cards */\n rS: '8px',\n rM: '12px',\n rL: '16px',\n rPill: '999px',\n\n /* spacing — 8px grid with a 4px half-step */\n s1: '4px',\n s2: '6px',\n s3: '8px',\n s4: '12px',\n s5: '16px',\n s6: '20px',\n s7: '24px',\n\n /* motion — damped ease for movement, gentle spring for entrances */\n ease: 'cubic-bezier(0.32, 0.72, 0, 1)',\n spring: 'cubic-bezier(0.3, 1.36, 0.5, 1)',\n tFast: '120ms',\n tMed: '200ms',\n tSlow: '280ms',\n\n /* material — real vibrancy: blur + saturation boost behind every surface */\n blur: 'blur(28px) saturate(1.9)',\n blurSoft: 'blur(16px) saturate(1.6)',\n} as const;\n\nexport const darkTokens = {\n accent: '#7d8cfa',\n accentFg: '#0e0f16',\n accentSoft: 'rgba(125, 140, 250, 0.16)',\n accentGlow: 'rgba(125, 140, 250, 0.4)',\n danger: '#ff6b70',\n dangerSoft: 'rgba(255, 107, 112, 0.14)',\n success: '#3ecf8e',\n warn: '#f0a742',\n\n bg: 'rgba(24, 25, 31, 0.76)',\n bgElev: 'rgba(33, 34, 42, 0.82)',\n bgInput: 'rgba(255, 255, 255, 0.055)',\n bgHover: 'rgba(255, 255, 255, 0.07)',\n bgActive: 'rgba(255, 255, 255, 0.11)',\n\n fg: 'rgba(242, 243, 249, 0.96)',\n fgMuted: 'rgba(242, 243, 249, 0.64)',\n fgFaint: 'rgba(242, 243, 249, 0.42)',\n\n hairline: 'rgba(255, 255, 255, 0.1)',\n hairlineStrong: 'rgba(255, 255, 255, 0.18)',\n\n /* layered elevation: top inner highlight (glass edge) + contact + ambient */\n shadowS:\n 'inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 0 0 0.5px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.26)',\n shadowM:\n 'inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 0 0 0.5px rgba(0, 0, 0, 0.32), 0 2px 5px rgba(0, 0, 0, 0.3), 0 12px 32px rgba(0, 0, 0, 0.34)',\n shadowL:\n 'inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 0 0 0.5px rgba(0, 0, 0, 0.34), 0 4px 10px rgba(0, 0, 0, 0.32), 0 18px 44px rgba(0, 0, 0, 0.38), 0 40px 96px rgba(0, 0, 0, 0.42)',\n} as const;\n\nexport const lightTokens: Record<keyof typeof darkTokens, string> = {\n accent: '#4c58e6',\n accentFg: '#ffffff',\n accentSoft: 'rgba(76, 88, 230, 0.11)',\n accentGlow: 'rgba(76, 88, 230, 0.32)',\n danger: '#dc3d43',\n dangerSoft: 'rgba(220, 61, 67, 0.1)',\n success: '#0f8a5f',\n warn: '#b97502',\n\n bg: 'rgba(250, 250, 252, 0.8)',\n bgElev: 'rgba(255, 255, 255, 0.86)',\n bgInput: 'rgba(10, 12, 24, 0.045)',\n bgHover: 'rgba(10, 12, 24, 0.05)',\n bgActive: 'rgba(10, 12, 24, 0.09)',\n\n fg: 'rgba(18, 19, 26, 0.95)',\n fgMuted: 'rgba(18, 19, 26, 0.62)',\n fgFaint: 'rgba(18, 19, 26, 0.4)',\n\n hairline: 'rgba(10, 12, 24, 0.1)',\n hairlineStrong: 'rgba(10, 12, 24, 0.18)',\n\n shadowS:\n 'inset 0 1px 0 rgba(255, 255, 255, 0.85), 0 0 0 0.5px rgba(16, 20, 40, 0.06), 0 1px 2px rgba(16, 20, 40, 0.07), 0 4px 12px rgba(16, 20, 40, 0.06)',\n shadowM:\n 'inset 0 1px 0 rgba(255, 255, 255, 0.85), 0 0 0 0.5px rgba(16, 20, 40, 0.07), 0 2px 5px rgba(16, 20, 40, 0.07), 0 12px 32px rgba(16, 20, 40, 0.11)',\n shadowL:\n 'inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 0 0 0.5px rgba(16, 20, 40, 0.08), 0 4px 10px rgba(16, 20, 40, 0.08), 0 18px 44px rgba(16, 20, 40, 0.13), 0 40px 96px rgba(16, 20, 40, 0.14)',\n};\n\nfunction kebab(name: string): string {\n return name.replace(/([A-Z])/g, '-$1').toLowerCase();\n}\n\nfunction declarations(tokens: Record<string, string>): string {\n return Object.entries(tokens)\n .map(([name, value]) => ` --rk-${kebab(name)}: ${value};`)\n .join('\\n');\n}\n\n/** CSS custom property blocks for the shadow root, light/dark via media query. */\nexport function tokenCss(): string {\n return `:host {\n${declarations(sharedTokens)}\n${declarations(darkTokens)}\n color-scheme: dark;\n}\n@media (prefers-color-scheme: light) {\n :host {\n${declarations(lightTokens)}\n color-scheme: light;\n }\n}`;\n}\n","/**\n * All plugin CSS, injected into the shadow root. Driven entirely by\n * `tokens.ts` — no ad-hoc colors or sizes in here.\n *\n * Layout conventions:\n * - every floating surface = vibrancy background + hairline border + layered\n * shadow token (which carries the top inner highlight);\n * - anchored elements are positioned with an inline \\`transform\\`, so entrance\n * animations only ever touch \\`opacity\\`, \\`scale\\` and \\`translate\\` — never\n * \\`transform\\` (a both-fill transform animation would override the position);\n * - interactive controls have a >= 40px effective hit area (padding or an\n * ::after inset extension).\n */\n\nimport { tokenCss } from './tokens';\n\nexport function buildStylesheet(): string {\n return `${tokenCss()}\n\n*, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\n:host {\n font-family: var(--rk-font-stack);\n font-size: var(--rk-fs-m);\n line-height: 1.45;\n -webkit-font-smoothing: antialiased;\n text-rendering: optimizeLegibility;\n}\n\n.rk-root {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 0;\n color: var(--rk-fg);\n}\n\nbutton {\n font: inherit;\n color: inherit;\n background: none;\n border: 0;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n}\n\ninput, textarea, select {\n font: inherit;\n color: inherit;\n}\n\n:focus { outline: none; }\n:focus-visible {\n outline: 2px solid var(--rk-accent);\n outline-offset: 2px;\n border-radius: var(--rk-r-s);\n}\n\n::selection { background: var(--rk-accent-soft); }\n\n/* ---------------------------------------------------------------- */\n/* Primitives */\n/* ---------------------------------------------------------------- */\n\n.rk-surface {\n background: var(--rk-bg);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-m);\n}\n\n.rk-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--rk-s2);\n height: 32px;\n padding: 0 var(--rk-s4);\n border-radius: var(--rk-r-s);\n font-size: var(--rk-fs-m);\n font-weight: 500;\n white-space: nowrap;\n position: relative;\n transition: background var(--rk-t-fast) var(--rk-ease), opacity var(--rk-t-fast) var(--rk-ease), scale var(--rk-t-fast) var(--rk-ease), box-shadow var(--rk-t-fast) var(--rk-ease);\n pointer-events: auto;\n}\n.rk-btn::after { content: ''; position: absolute; inset: -4px; border-radius: inherit; }\n.rk-btn:active { scale: 0.97; }\n.rk-btn-primary {\n background: var(--rk-accent);\n color: var(--rk-accent-fg);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 1px 2px rgba(0, 0, 0, 0.18);\n}\n.rk-btn-primary:hover { filter: brightness(1.07); }\n.rk-btn-ghost {\n background: var(--rk-bg-input);\n border: 1px solid var(--rk-hairline);\n color: var(--rk-fg);\n}\n.rk-btn-ghost:hover { background: var(--rk-bg-hover); }\n.rk-btn-danger {\n background: var(--rk-danger);\n color: #fff;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 1px 2px rgba(0, 0, 0, 0.18);\n}\n.rk-btn-danger:hover { filter: brightness(1.07); }\n.rk-btn:disabled { opacity: 0.42; cursor: default; }\n.rk-btn:disabled:hover { filter: none; background: var(--rk-bg-input); }\n.rk-btn-primary:disabled:hover { background: var(--rk-accent); }\n\n.rk-icon-btn {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: var(--rk-r-s);\n color: var(--rk-fg-muted);\n transition: background var(--rk-t-fast) var(--rk-ease), color var(--rk-t-fast) var(--rk-ease), scale var(--rk-t-fast) var(--rk-ease);\n pointer-events: auto;\n flex: none;\n}\n.rk-icon-btn::after { content: ''; position: absolute; inset: -6px; border-radius: inherit; }\n.rk-icon-btn:hover { background: var(--rk-bg-hover); color: var(--rk-fg); }\n.rk-icon-btn:active { scale: 0.94; }\n\n.rk-input, .rk-textarea {\n width: 100%;\n background: var(--rk-bg-input);\n border: 1px solid var(--rk-hairline);\n border-radius: var(--rk-r-s);\n padding: 7px 10px;\n font-size: var(--rk-fs-m);\n color: var(--rk-fg);\n transition: border-color var(--rk-t-fast) var(--rk-ease), background var(--rk-t-fast) var(--rk-ease), box-shadow var(--rk-t-fast) var(--rk-ease);\n pointer-events: auto;\n}\n.rk-input::placeholder, .rk-textarea::placeholder { color: var(--rk-fg-faint); }\n.rk-input:focus-visible, .rk-textarea:focus-visible {\n outline: none;\n border-color: var(--rk-accent);\n box-shadow: 0 0 0 3px var(--rk-accent-soft);\n}\n.rk-textarea { resize: vertical; min-height: 64px; line-height: 1.5; }\n\n.rk-label {\n display: block;\n font-size: var(--rk-fs-xs);\n font-weight: 600;\n letter-spacing: var(--rk-track-wide);\n text-transform: uppercase;\n color: var(--rk-fg-faint);\n margin-bottom: var(--rk-s2);\n}\n\n.rk-seg {\n display: inline-flex;\n background: var(--rk-bg-input);\n border: 1px solid var(--rk-hairline);\n border-radius: var(--rk-r-s);\n padding: 2px;\n gap: 2px;\n pointer-events: auto;\n}\n.rk-seg button {\n height: 26px;\n padding: 0 11px;\n border-radius: calc(var(--rk-r-s) - 2px);\n font-size: var(--rk-fs-s);\n font-weight: 500;\n color: var(--rk-fg-muted);\n transition: background var(--rk-t-fast) var(--rk-ease), color var(--rk-t-fast) var(--rk-ease), box-shadow var(--rk-t-fast) var(--rk-ease);\n}\n.rk-seg button:hover { color: var(--rk-fg); }\n.rk-seg button[aria-pressed='true'] {\n background: var(--rk-accent);\n color: var(--rk-accent-fg);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), 0 1px 2px rgba(0, 0, 0, 0.14);\n}\n\n.rk-kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 5px;\n border: 1px solid var(--rk-hairline-strong);\n border-bottom-width: 2px;\n background: var(--rk-bg-input);\n font-family: var(--rk-mono-stack);\n font-size: var(--rk-fs-xs);\n color: var(--rk-fg-muted);\n}\n\n/* ---------------------------------------------------------------- */\n/* Badge */\n/* ---------------------------------------------------------------- */\n\n.rk-badge {\n position: fixed;\n display: flex;\n align-items: center;\n gap: var(--rk-s3);\n height: 40px;\n padding: 0 var(--rk-s5);\n border-radius: var(--rk-r-pill);\n background: var(--rk-bg);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-m);\n font-size: var(--rk-fs-m);\n font-weight: 600;\n letter-spacing: 0.01em;\n color: var(--rk-fg);\n cursor: grab;\n user-select: none;\n -webkit-user-select: none;\n touch-action: none;\n pointer-events: auto;\n transition: box-shadow var(--rk-t-med) var(--rk-ease);\n animation: rk-pop var(--rk-t-slow) var(--rk-spring) both;\n}\n.rk-badge.rk-dragging { cursor: grabbing; box-shadow: var(--rk-shadow-l); }\n.rk-badge:hover { box-shadow: var(--rk-shadow-l); }\n\n.rk-badge-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--rk-accent);\n box-shadow: 0 0 0 3px var(--rk-accent-soft);\n flex: none;\n}\n.rk-badge.rk-picking .rk-badge-dot { animation: rk-pulse 1.6s var(--rk-ease) infinite; }\n\n.rk-badge-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 19px;\n height: 19px;\n padding: 0 6px;\n border-radius: var(--rk-r-pill);\n background: var(--rk-accent-soft);\n color: var(--rk-accent);\n font-size: var(--rk-fs-xs);\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n}\n\n/* ---------------------------------------------------------------- */\n/* Pick layer: hover outline, label chip, selection ring */\n/* ---------------------------------------------------------------- */\n\n.rk-outline, .rk-select-ring, .rk-hl-ring, .rk-edit-ring {\n position: fixed;\n top: 0;\n left: 0;\n pointer-events: none;\n border-radius: 5px;\n will-change: transform, width, height;\n}\n\n.rk-outline {\n border: 1.5px solid var(--rk-accent);\n background: var(--rk-accent-soft);\n transition: transform 90ms var(--rk-ease), width 90ms var(--rk-ease), height 90ms var(--rk-ease), opacity var(--rk-t-fast) var(--rk-ease);\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.14);\n}\n\n.rk-select-ring {\n border: 1.5px solid var(--rk-accent);\n box-shadow: 0 0 0 4px var(--rk-accent-soft), 0 0 28px var(--rk-accent-glow);\n transition: transform 90ms var(--rk-ease), width 90ms var(--rk-ease), height 90ms var(--rk-ease);\n animation: rk-fade var(--rk-t-fast) var(--rk-ease) both;\n}\n\n.rk-hl-ring {\n border: 1.5px dashed var(--rk-accent);\n background: var(--rk-accent-soft);\n animation: rk-fade var(--rk-t-fast) var(--rk-ease) both;\n}\n\n.rk-edit-ring {\n border: 1.5px solid transparent;\n box-shadow: 0 0 0 4px var(--rk-accent-soft);\n border-radius: 6px;\n}\n.rk-edit-ring::after {\n content: '';\n position: absolute;\n left: 6px;\n right: 6px;\n bottom: -7px;\n height: 2px;\n border-radius: 2px;\n background: linear-gradient(90deg, transparent, var(--rk-accent) 18%, var(--rk-accent) 82%, transparent);\n background-size: 200% 100%;\n animation: rk-shimmer 1.8s linear infinite;\n}\n\n.rk-outline-label {\n position: fixed;\n top: 0;\n left: 0;\n display: flex;\n align-items: center;\n gap: var(--rk-s2);\n max-width: 340px;\n padding: 5px 11px;\n border-radius: var(--rk-r-pill);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur-soft);\n backdrop-filter: var(--rk-blur-soft);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-s);\n font-size: var(--rk-fs-s);\n color: var(--rk-fg-muted);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n pointer-events: none;\n transition: transform 90ms var(--rk-ease);\n}\n.rk-outline-label .rk-tag {\n color: var(--rk-accent);\n font-family: var(--rk-mono-stack);\n font-weight: 600;\n font-size: var(--rk-fs-xs);\n}\n\n/* ---------------------------------------------------------------- */\n/* Selection toolbar — floating capsule, bottom center */\n/* ---------------------------------------------------------------- */\n\n.rk-toolbar {\n /* \\`translate\\` (not \\`transform\\`) does the centering so no transform\n animation or inline transform can cancel it. */\n position: fixed;\n bottom: 50px;\n left: 50%;\n translate: -50%;\n max-width: calc(100vw - 16px);\n display: flex;\n flex-wrap: wrap;\n justify-content: center;\n align-items: center;\n gap: 2px;\n padding: var(--rk-s1);\n border-radius: var(--rk-r-pill);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-m);\n pointer-events: auto;\n animation: rk-drop-in var(--rk-t-med) var(--rk-spring) both;\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n -webkit-user-drag: none;\n transition: opacity var(--rk-t-med) var(--rk-ease);\n}\n.rk-toolbar * { -webkit-user-drag: none; }\n/* While picking, let the page underneath show through */\n.rk-toolbar.rk-ghost { opacity: 0.55; }\n.rk-toolbar.rk-ghost:hover, .rk-toolbar.rk-ghost:focus-within { opacity: 1; }\n.rk-toolbar.rk-toolbar-dragging { transition: none; cursor: grabbing; }\n/* A dragged position drives left/top inline — bottom must not fight it. */\n.rk-toolbar.rk-toolbar-free { bottom: auto; }\n@media (max-width: 480px) {\n .rk-toolbar { bottom: 16px; }\n}\n.rk-toolbar-grip {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n align-self: stretch;\n min-height: 32px;\n border-radius: var(--rk-r-pill);\n color: var(--rk-fg-faint);\n cursor: grab;\n flex: none;\n}\n.rk-toolbar-grip:hover { color: var(--rk-fg-muted); background: var(--rk-bg-hover); }\n.rk-toolbar-grip:active { cursor: grabbing; }\n.rk-toolbar-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--rk-s2);\n height: 36px;\n padding: 0 var(--rk-s4);\n border-radius: var(--rk-r-pill);\n font-size: var(--rk-fs-m);\n font-weight: 500;\n color: var(--rk-fg-muted);\n transition: background var(--rk-t-fast) var(--rk-ease), color var(--rk-t-fast) var(--rk-ease), scale var(--rk-t-fast) var(--rk-ease);\n white-space: nowrap;\n}\n.rk-toolbar-btn:hover { background: var(--rk-bg-hover); color: var(--rk-fg); }\n.rk-toolbar-btn:active { scale: 0.96; }\n.rk-toolbar-btn svg { color: var(--rk-fg-faint); transition: color var(--rk-t-fast) var(--rk-ease); }\n.rk-toolbar-btn:hover svg { color: var(--rk-accent); }\n.rk-toolbar-btn.rk-danger:hover { background: var(--rk-danger-soft); color: var(--rk-danger); }\n.rk-toolbar-btn.rk-danger:hover svg { color: var(--rk-danger); }\n.rk-toolbar-sep {\n width: 1px;\n height: 20px;\n background: var(--rk-hairline);\n margin: 0 var(--rk-s1);\n flex: none;\n}\n.rk-toolbar .rk-icon-btn { width: 32px; height: 32px; border-radius: var(--rk-r-pill); }\n.rk-view-toggle { border-radius: var(--rk-r-pill); margin-left: 2px; }\n.rk-view-toggle button { height: 28px; border-radius: var(--rk-r-pill); }\n.rk-tool-seg { border-radius: var(--rk-r-pill); }\n.rk-tool-seg button {\n width: 32px;\n height: 28px;\n padding: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--rk-r-pill);\n}\n\n/* Presence: avatars in the toolbar, remote cursors + selection rings */\n.rk-presence { display: inline-flex; align-items: center; padding: 0 2px; }\n.rk-presence .rk-avatar + .rk-avatar { margin-left: -6px; }\n.rk-avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n border: 2px solid var(--rk-bg-elev);\n color: #fff;\n font-size: 9px;\n font-weight: 700;\n letter-spacing: 0.02em;\n text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);\n user-select: none;\n}\n.rk-avatar-more { background: var(--rk-bg-input); color: var(--rk-fg-muted); text-shadow: none; }\n\n.rk-peer-cursor {\n position: fixed;\n top: 0;\n left: 0;\n display: flex;\n align-items: flex-start;\n gap: 2px;\n pointer-events: none;\n transition: transform 90ms linear, opacity var(--rk-t-med) var(--rk-ease);\n will-change: transform;\n z-index: 3;\n}\n.rk-peer-name {\n margin-top: 12px;\n padding: 2px 8px;\n border-radius: var(--rk-r-pill);\n color: #fff;\n font-size: var(--rk-fs-xs);\n font-weight: 600;\n white-space: nowrap;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n}\n.rk-peer-cursor.rk-peer-edge svg { opacity: 0.7; }\n.rk-peer-cursor svg { transition: transform 120ms var(--rk-ease); will-change: transform; }\n\n.rk-quick {\n position: fixed;\n top: 0;\n left: 0;\n width: 280px;\n padding: var(--rk-s3);\n display: flex;\n flex-direction: column;\n gap: var(--rk-s2);\n border-radius: var(--rk-r-m);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-l);\n pointer-events: auto;\n animation: rk-pop var(--rk-t-fast) var(--rk-spring) both;\n}\n.rk-quick-head {\n display: flex;\n align-items: center;\n gap: var(--rk-s2);\n font-size: var(--rk-fs-xs);\n font-weight: 600;\n color: var(--rk-fg-muted);\n}\n.rk-quick-head svg { color: var(--rk-accent); }\n.rk-quick-head .rk-hint { margin-left: auto; font-weight: 400; }\n.rk-quick .rk-textarea { min-height: 40px; font-size: var(--rk-fs-m); }\n\n.rk-fx-layer {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 10;\n overflow: hidden;\n}\n.rk-fx-sound {\n position: fixed;\n bottom: 18px;\n left: 50%;\n translate: -50%;\n padding: 8px 16px;\n border-radius: var(--rk-r-pill);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-m);\n color: var(--rk-fg);\n font-size: var(--rk-fs-m);\n font-weight: 600;\n pointer-events: auto;\n cursor: pointer;\n}\n.rk-fx-banner {\n position: fixed;\n top: 40%;\n left: 0;\n width: 200vw;\n white-space: nowrap;\n font-size: 46px;\n font-weight: 800;\n letter-spacing: 0.06em;\n color: #ff3b30;\n text-shadow: 0 2px 0 rgba(0,0,0,0.35);\n animation: rk-fx-marquee 13.8s linear both;\n pointer-events: none;\n}\n.rk-fx-banner-still {\n animation: none;\n width: auto;\n left: 50%;\n translate: -50%;\n font-size: 28px;\n}\n.rk-fx-band {\n position: fixed;\n left: -4vw;\n width: 108vw;\n top: -80px;\n -webkit-backdrop-filter: hue-rotate(130deg) saturate(2.1) contrast(1.15) blur(1px);\n backdrop-filter: hue-rotate(130deg) saturate(2.1) contrast(1.15) blur(1px);\n animation-name: rk-fx-band-slide;\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n pointer-events: none;\n}\n\n.rk-fx-letter {\n position: fixed;\n color: rgba(255, 255, 255, 0.92);\n text-shadow: 2px 0 rgba(255, 0, 90, 0.7), -2px 0 rgba(0, 190, 255, 0.7), 0 1px 2px rgba(0,0,0,0.5);\n font-weight: 700;\n pointer-events: none;\n animation: rk-fx-letter-fall 3.4s cubic-bezier(0.35, 0, 0.8, 0.4) both;\n}\n\n.rk-fx-matrix {\n font-family: ui-monospace, monospace;\n color: #22c55e;\n text-shadow: 0 0 8px rgba(34, 197, 94, 0.8);\n font-weight: 700;\n}\n.rk-fx-laser {\n position: absolute;\n top: -20%;\n width: 3px;\n height: 140%;\n transform-origin: 50% 0;\n animation: rk-fx-laser-sweep 4s ease-in-out infinite alternate;\n filter: blur(1px);\n mix-blend-mode: screen;\n}\n.rk-fx-kura {\n position: absolute;\n bottom: 8px;\n left: -60px;\n font-size: 42px;\n transform: scaleX(-1);\n animation: rk-fx-kura-walk 11s linear both;\n}\n.rk-fx-egg {\n position: absolute;\n bottom: 10px;\n font-size: 22px;\n animation: rk-pop var(--rk-t-fast) var(--rk-spring) both;\n}\n.rk-fx-toast {\n position: absolute;\n right: 16px;\n max-width: 300px;\n padding: 10px 14px;\n border-radius: var(--rk-r-m);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-l);\n font-size: var(--rk-fs-m);\n font-weight: 600;\n color: var(--rk-fg);\n animation: rk-fx-toast-in 420ms var(--rk-spring) both;\n}\n.rk-fx-drip {\n position: absolute;\n top: -18vh;\n width: 4px;\n height: 16vh;\n border-radius: 999px;\n opacity: 0.75;\n filter: blur(0.5px);\n animation-name: rk-fx-drip-fall;\n animation-timing-function: cubic-bezier(0.5, 0, 0.9, 0.6);\n animation-fill-mode: both;\n}\n.rk-fx-cracks {\n position: absolute;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n}\n.rk-fx-cracks span {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 150vmax;\n height: 1.5px;\n margin-left: -75vmax;\n background: linear-gradient(90deg, transparent 4%, rgba(255, 255, 255, 0.55) 30%, rgba(190, 225, 255, 0.7) 50%, rgba(255, 255, 255, 0.55) 70%, transparent 96%);\n transform-origin: 50% 50%;\n animation: rk-fx-crack-flare 11s ease-in-out infinite;\n}\n.rk-fx-crt { position: absolute; inset: 0; pointer-events: none; }\n.rk-fx-crt-scan {\n position: absolute;\n inset: 0;\n background: repeating-linear-gradient(180deg, rgba(0, 0, 0, 0.28) 0 1px, transparent 1px 3px);\n opacity: 0.7;\n}\n.rk-fx-crt-roll {\n position: absolute;\n left: 0;\n right: 0;\n height: 90px;\n background: linear-gradient(180deg, transparent, rgba(190, 255, 200, 0.14), transparent);\n animation: rk-fx-crt-roll 5.5s linear infinite;\n}\n.rk-fx-crt-vignette {\n position: absolute;\n inset: 0;\n border-radius: 26px;\n box-shadow: inset 0 0 140px 50px rgba(0, 0, 0, 0.82);\n background: radial-gradient(ellipse at center, transparent 58%, rgba(0, 0, 0, 0.45) 100%);\n}\n.rk-fx-crt-osd {\n position: absolute;\n top: 26px;\n right: 34px;\n font-family: ui-monospace, monospace;\n font-size: 20px;\n font-weight: 700;\n letter-spacing: 0.14em;\n color: rgba(120, 255, 160, 0.9);\n text-shadow: 0 0 10px rgba(80, 255, 140, 0.8);\n animation: rk-fx-crt-osd 3.2s ease-in-out infinite;\n}\n.rk-fx-particle {\n position: fixed;\n top: 0;\n left: 0;\n will-change: transform, opacity;\n pointer-events: none;\n}\n\n.rk-egg {\n margin-top: var(--rk-s2);\n font-size: var(--rk-fs-xs);\n color: var(--rk-fg-faint);\n}\n\n.rk-peer-ring {\n position: fixed;\n top: 0;\n left: 0;\n border: 1.5px solid;\n border-radius: 5px;\n pointer-events: none;\n transition: opacity var(--rk-t-med) var(--rk-ease);\n will-change: transform, width, height;\n}\n\n/* Quiet connection state in the panel sub line */\n.rk-sync { display: inline-flex; align-items: center; gap: 4px; margin-left: 8px; }\n.rk-sync-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--rk-fg-faint); }\n.rk-sync-online .rk-sync-dot { background: var(--rk-success); }\n.rk-sync-connecting .rk-sync-dot { background: var(--rk-warn); }\n/* Automatic Emblema push hint (same quiet language) */\n.rk-epush-ok .rk-sync-dot { background: var(--rk-success); }\n.rk-epush-sending .rk-sync-dot { background: var(--rk-warn); }\n.rk-epush-offline .rk-sync-dot { background: var(--rk-fg-faint); }\n.rk-epush-rejected .rk-sync-dot { background: var(--rk-danger, #d33); }\n\n/* ---------------------------------------------------------------- */\n/* Floating editor cards */\n/* ---------------------------------------------------------------- */\n\n.rk-card {\n position: fixed;\n top: 0;\n left: 0;\n width: 336px;\n max-width: calc(100vw - 16px);\n border-radius: var(--rk-r-l);\n background: var(--rk-bg);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-l);\n pointer-events: auto;\n animation: rk-pop var(--rk-t-med) var(--rk-spring) both;\n overflow: hidden;\n}\n.rk-card-head {\n display: flex;\n align-items: center;\n gap: var(--rk-s3);\n padding: var(--rk-s4) var(--rk-s5);\n border-bottom: 1px solid var(--rk-hairline);\n font-weight: 600;\n font-size: var(--rk-fs-m);\n letter-spacing: var(--rk-track-tight);\n}\n.rk-card-head svg { color: var(--rk-accent); flex: none; }\n.rk-card-head .rk-spacer { flex: 1; }\n.rk-card-body {\n padding: var(--rk-s5);\n display: flex;\n flex-direction: column;\n gap: var(--rk-s4);\n}\n.rk-card-foot {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--rk-s3);\n padding: var(--rk-s4) var(--rk-s5);\n border-top: 1px solid var(--rk-hairline);\n}\n.rk-card-foot .rk-actions { display: flex; gap: var(--rk-s3); margin-left: auto; }\n.rk-hint { font-size: var(--rk-fs-xs); color: var(--rk-fg-faint); }\n.rk-hint .rk-kbd { margin: 0 1px; }\n\n/* Inline copy editor: before/after diff */\n.rk-diff {\n display: flex;\n flex-direction: column;\n gap: var(--rk-s3);\n font-size: var(--rk-fs-s);\n border: 1px solid var(--rk-hairline);\n border-radius: var(--rk-r-m);\n padding: var(--rk-s4);\n background: var(--rk-bg-input);\n max-height: 132px;\n overflow: auto;\n}\n.rk-diff-row { display: flex; gap: var(--rk-s3); align-items: baseline; }\n/* textarea baselines are unreliable across browsers — top-align the After row */\n.rk-diff-row.rk-diff-after { align-items: flex-start; }\n.rk-diff-row .rk-diff-tag {\n flex: none;\n width: 44px;\n font-size: var(--rk-fs-xs);\n font-weight: 700;\n letter-spacing: var(--rk-track-wide);\n text-transform: uppercase;\n}\n.rk-diff-before .rk-diff-tag { color: var(--rk-danger); }\n.rk-diff-after .rk-diff-tag { color: var(--rk-success); }\n.rk-diff-text {\n color: var(--rk-fg-muted);\n overflow-wrap: anywhere;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.rk-diff-before .rk-diff-text { text-decoration: line-through; text-decoration-color: var(--rk-danger); text-decoration-thickness: 1px; opacity: 0.7; }\n.rk-diff-after .rk-diff-text { color: var(--rk-fg); }\n.rk-diff-input,\n.rk-textarea.rk-diff-input {\n flex: 1;\n background: none;\n border: 0;\n border-radius: 0;\n padding: 0;\n font-size: var(--rk-fs-s);\n line-height: 1.5;\n color: var(--rk-fg);\n resize: none;\n overflow: hidden;\n min-height: 1.5em;\n}\n.rk-size-note {\n display: flex;\n flex-direction: column;\n gap: 2px;\n font-size: var(--rk-fs-xs);\n line-height: 1.5;\n color: var(--rk-fg-faint);\n}\n.rk-size-note .rk-clip-note { color: var(--rk-warn); }\n\n.rk-delta {\n font-variant-numeric: tabular-nums;\n font-size: var(--rk-fs-xs);\n font-weight: 400;\n letter-spacing: 0;\n color: var(--rk-fg-faint);\n}\n.rk-delta .rk-plus { color: var(--rk-success); }\n.rk-delta .rk-minus { color: var(--rk-danger); }\n\n/* Image editor */\n.rk-drop {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--rk-s2);\n min-height: 96px;\n border: 1.5px dashed var(--rk-hairline-strong);\n border-radius: var(--rk-r-m);\n color: var(--rk-fg-muted);\n font-size: var(--rk-fs-s);\n text-align: center;\n padding: var(--rk-s4);\n cursor: pointer;\n transition: border-color var(--rk-t-fast) var(--rk-ease), background var(--rk-t-fast) var(--rk-ease);\n pointer-events: auto;\n}\n.rk-drop:hover, .rk-drop.rk-over {\n border-color: var(--rk-accent);\n background: var(--rk-accent-soft);\n color: var(--rk-fg);\n}\n.rk-drop svg { color: var(--rk-accent); }\n\n/* URL row of the image editor — mirrors the search field pattern */\n.rk-url {\n position: relative;\n display: flex;\n align-items: center;\n}\n.rk-url > svg, .rk-url > .rk-spinner {\n position: absolute;\n left: 10px;\n color: var(--rk-fg-faint);\n pointer-events: none;\n}\n.rk-url .rk-input { padding-left: 31px; height: 32px; }\n.rk-spinner {\n width: 13px;\n height: 13px;\n border-radius: 50%;\n border: 1.5px solid var(--rk-hairline-strong);\n border-top-color: var(--rk-accent);\n animation: rk-spin 700ms linear infinite;\n}\n\n.rk-thumbs { display: flex; gap: var(--rk-s4); align-items: stretch; }\n.rk-thumb {\n position: relative;\n flex: 1;\n min-width: 0;\n border-radius: var(--rk-r-s);\n border: 1px solid var(--rk-hairline);\n overflow: hidden;\n background: var(--rk-bg-input);\n}\n.rk-thumb img { display: block; width: 100%; height: 84px; object-fit: cover; }\n.rk-thumb figcaption {\n position: absolute;\n left: 6px;\n bottom: 6px;\n padding: 1px 8px;\n border-radius: var(--rk-r-pill);\n background: rgba(10, 10, 16, 0.72);\n -webkit-backdrop-filter: var(--rk-blur-soft);\n backdrop-filter: var(--rk-blur-soft);\n color: rgba(255, 255, 255, 0.94);\n font-size: var(--rk-fs-xs);\n font-weight: 600;\n letter-spacing: var(--rk-track-wide);\n text-transform: uppercase;\n}\n.rk-thumb-pair { position: relative; flex: 1; min-width: 0; }\n.rk-thumb-pair .rk-thumb { position: absolute; inset: 0; transition: opacity var(--rk-t-slow) var(--rk-ease); }\n.rk-thumb-pair .rk-thumb:last-child { position: relative; }\n.rk-thumb-pair:hover .rk-thumb:last-child { opacity: 0; }\n\n/* ---------------------------------------------------------------- */\n/* Pins */\n/* ---------------------------------------------------------------- */\n\n.rk-pin-wrap {\n position: fixed;\n top: 0;\n left: 0;\n pointer-events: none;\n will-change: transform;\n}\n.rk-pin-ghost { opacity: 0.55; }\n.rk-pin-ghost .rk-pin { pointer-events: none; }\n.rk-pin {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n margin: -12px 0 0 -12px;\n border-radius: 50% 50% 50% 5px;\n background: var(--rk-accent);\n color: var(--rk-accent-fg);\n font-size: var(--rk-fs-xs);\n font-weight: 700;\n font-variant-numeric: tabular-nums;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 0 0 2px var(--rk-bg-elev), 0 2px 6px rgba(0, 0, 0, 0.3);\n cursor: pointer;\n pointer-events: auto;\n transition: scale var(--rk-t-fast) var(--rk-spring), background var(--rk-t-fast) var(--rk-ease), box-shadow var(--rk-t-fast) var(--rk-ease);\n animation: rk-pin-in var(--rk-t-slow) var(--rk-spring) both;\n}\n/* comfortable touch target around the 24px pin */\n.rk-pin::after { content: ''; position: absolute; inset: -8px; border-radius: 50%; }\n.rk-pin:hover { scale: 1.16; z-index: 2; }\n.rk-pin.rk-new { animation: rk-pin-in var(--rk-t-slow) var(--rk-spring) both, rk-pulse 1.4s var(--rk-ease) 2; }\n.rk-pin.rk-cluster { border-radius: 50%; background: var(--rk-bg-elev); color: var(--rk-accent); border: 1.5px solid var(--rk-accent); }\n\n/* Status looks — same color language as the panel's status chips:\n open = accent (default), accepted = success fill, applied = success\n outline (done), rejected = dimmed danger outline. */\n.rk-pin.rk-st-accepted { background: var(--rk-success); color: var(--rk-accent-fg); }\n.rk-pin.rk-st-applied { background: var(--rk-bg-elev); color: var(--rk-success); border: 1.5px solid var(--rk-success); }\n.rk-pin.rk-st-rejected { background: var(--rk-bg-elev); color: var(--rk-danger); border: 1.5px solid var(--rk-danger); opacity: 0.72; }\n.rk-pin.rk-cluster.rk-st-accepted { background: var(--rk-bg-elev); color: var(--rk-success); border-color: var(--rk-success); }\n.rk-pin.rk-cluster.rk-st-applied { color: var(--rk-success); border-color: var(--rk-success); }\n.rk-pin.rk-cluster.rk-st-rejected { color: var(--rk-danger); border-color: var(--rk-danger); }\n\n/* Panel filters active and nothing in this pin matches: fade out of the way. */\n.rk-pin.rk-dim { opacity: 0.22; }\n.rk-pin.rk-dim:hover { opacity: 0.85; }\n\n/* Status swatch in the filter menu (matches the pin colors). */\n.rk-status-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--rk-accent); }\n.rk-status-dot.rk-st-accepted { background: var(--rk-success); }\n.rk-status-dot.rk-st-applied { background: transparent; border: 1.5px solid var(--rk-success); }\n.rk-status-dot.rk-st-rejected { background: transparent; border: 1.5px solid var(--rk-danger); }\n.rk-pin.rk-active { scale: 1.16; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 0 0 2px var(--rk-bg-elev), 0 0 0 6px var(--rk-accent-soft), 0 2px 6px rgba(0, 0, 0, 0.3); }\n\n.rk-tray {\n position: fixed;\n display: flex;\n align-items: center;\n gap: var(--rk-s3);\n height: 36px;\n padding: 0 var(--rk-s5);\n border-radius: var(--rk-r-pill);\n background: var(--rk-bg);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px dashed var(--rk-hairline-strong);\n box-shadow: var(--rk-shadow-s);\n color: var(--rk-fg-muted);\n font-size: var(--rk-fs-s);\n pointer-events: auto;\n cursor: pointer;\n transition: background var(--rk-t-fast) var(--rk-ease), color var(--rk-t-fast) var(--rk-ease);\n}\n.rk-tray:hover { background: var(--rk-bg-elev); color: var(--rk-fg); }\n.rk-tray svg { color: var(--rk-warn); }\n\n/* ---------------------------------------------------------------- */\n/* Side panel */\n/* ---------------------------------------------------------------- */\n\n.rk-panel {\n position: fixed;\n top: 12px;\n bottom: 12px;\n width: 348px;\n max-width: calc(100vw - 24px);\n display: flex;\n flex-direction: column;\n border-radius: var(--rk-r-l);\n background: var(--rk-bg);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-l);\n pointer-events: auto;\n overflow: hidden;\n}\n.rk-panel.rk-right { right: 12px; animation: rk-slide-left var(--rk-t-slow) var(--rk-ease) both; }\n.rk-panel.rk-left { left: 12px; animation: rk-slide-right var(--rk-t-slow) var(--rk-ease) both; }\n.rk-sheet-handle { display: none; }\n\n.rk-panel-head {\n display: flex;\n align-items: center;\n gap: var(--rk-s3);\n padding: var(--rk-s5) var(--rk-s5) var(--rk-s4);\n border-bottom: 1px solid var(--rk-hairline);\n}\n.rk-panel-title { font-size: var(--rk-fs-xl); font-weight: 600; letter-spacing: var(--rk-track-tight); line-height: 1.2; }\n.rk-panel-sub { font-size: var(--rk-fs-s); color: var(--rk-fg-faint); margin-top: 2px; }\n.rk-panel-head .rk-spacer { flex: 1; }\n\n.rk-view-row {\n display: flex;\n align-items: center;\n gap: var(--rk-s4);\n padding: var(--rk-s3) var(--rk-s5);\n border-bottom: 1px solid var(--rk-hairline);\n}\n.rk-view-info { flex: 1; min-width: 0; }\n.rk-view-title { font-size: var(--rk-fs-m); font-weight: 600; letter-spacing: var(--rk-track-tight); }\n.rk-view-desc { font-size: var(--rk-fs-xs); color: var(--rk-fg-faint); margin-top: 1px; line-height: 1.4; }\n\n.rk-panel-tools {\n display: flex;\n flex-direction: column;\n gap: var(--rk-s3);\n padding: var(--rk-s4) var(--rk-s5);\n border-bottom: 1px solid var(--rk-hairline);\n}\n.rk-panel-tools .rk-btn-primary { height: 36px; border-radius: var(--rk-r-m); }\n.rk-search {\n position: relative;\n display: flex;\n align-items: center;\n}\n.rk-search svg {\n position: absolute;\n left: 10px;\n color: var(--rk-fg-faint);\n pointer-events: none;\n}\n.rk-search .rk-input { padding-left: 30px; height: 32px; border-radius: var(--rk-r-m); }\n\n/* Popover menus (filter, session settings) */\n.rk-menu-anchor { position: relative; }\n.rk-menu-title {\n padding: 6px 10px 2px;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: var(--rk-track-wide);\n text-transform: uppercase;\n color: var(--rk-fg-faint);\n}\n.rk-menu-title:not(:first-child) { margin-top: 4px; border-top: 1px solid var(--rk-hairline); padding-top: 8px; }\n.rk-menu {\n position: absolute;\n top: calc(100% + 6px);\n right: 0;\n min-width: 208px;\n padding: var(--rk-s1);\n display: flex;\n flex-direction: column;\n border-radius: var(--rk-r-m);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-l);\n z-index: 5;\n animation: rk-pop var(--rk-t-fast) var(--rk-spring) both;\n}\n.rk-menu-item {\n display: flex;\n align-items: center;\n gap: var(--rk-s3);\n height: 30px;\n padding: 0 var(--rk-s3);\n border-radius: var(--rk-r-s);\n font-size: var(--rk-fs-m);\n color: var(--rk-fg);\n text-align: left;\n pointer-events: auto;\n}\n.rk-menu-item:hover { background: var(--rk-bg-hover); }\n.rk-menu-item:disabled { opacity: 0.4; }\n.rk-menu-item .rk-menu-label { text-transform: capitalize; }\n.rk-menu-count { margin-left: auto; font-size: var(--rk-fs-xs); color: var(--rk-fg-faint); font-variant-numeric: tabular-nums; }\n.rk-menu-check {\n width: 14px;\n height: 14px;\n border-radius: 4px;\n border: 1.5px solid var(--rk-hairline-strong);\n flex: none;\n}\n.rk-menu-check.rk-on {\n background: var(--rk-accent);\n border-color: var(--rk-accent);\n box-shadow: inset 0 0 0 3px var(--rk-bg-elev);\n}\n.rk-menu-danger { color: var(--rk-danger); }\n.rk-connect-cmd,\n.rk-connect-key {\n display: block;\n margin-top: var(--rk-s2);\n padding: var(--rk-s2) var(--rk-s3);\n border-radius: var(--rk-r-s);\n border: 1px solid var(--rk-hairline);\n background: var(--rk-bg-input);\n font-family: var(--rk-mono-stack);\n font-size: var(--rk-fs-xs);\n color: var(--rk-fg-muted);\n user-select: text;\n -webkit-user-select: text;\n word-break: break-all;\n}\n.rk-connect-key { color: var(--rk-fg); max-height: 88px; overflow: auto; }\n.rk-connect-id { color: var(--rk-fg-faint); font-size: var(--rk-fs-xs); }\n.rk-connect-bad { color: var(--rk-danger); }\n.rk-connect-actions { display: flex; gap: var(--rk-s2); align-items: center; }\n.rk-connect-revoke { color: var(--rk-danger); }\n\n.rk-emblema-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n flex: none;\n background: var(--rk-fg-faint);\n}\n.rk-emblema-dot[data-state='live'] { background: var(--rk-success); }\n.rk-emblema-dot[data-state='offline'] { background: var(--rk-danger); }\n.rk-emblema-dot[data-state='stale'] { background: var(--rk-warn); }\n.rk-emblema-dot[data-state='revoked'] { background: var(--rk-danger); }\n.rk-menu-clear { justify-content: center; color: var(--rk-fg-muted); border-top: 1px solid var(--rk-hairline); border-radius: 0; margin-top: 2px; }\n\n.rk-search-row { display: flex; gap: var(--rk-s2); align-items: center; }\n.rk-search-row .rk-search { flex: 1; }\n.rk-filter-btn { height: 32px; padding: 0 10px; font-size: var(--rk-fs-s); gap: 5px; }\n.rk-filter-btn .rk-badge-count { min-width: 16px; height: 16px; }\n\n.rk-author { display: inline-flex; align-items: center; gap: 5px; font-size: var(--rk-fs-xs); color: var(--rk-fg-muted); }\n.rk-author-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }\n.rk-time { color: var(--rk-fg-faint); }\n.rk-detail-byline { display: flex; align-items: center; gap: 6px; font-size: var(--rk-fs-xs); color: var(--rk-fg-muted); }\n\n.rk-diffview {\n display: flex;\n flex-direction: column;\n gap: var(--rk-s2);\n font-size: var(--rk-fs-s);\n border: 1px solid var(--rk-hairline);\n border-radius: var(--rk-r-s);\n padding: var(--rk-s3);\n background: var(--rk-bg-input);\n}\n.rk-diffview mark { background: transparent; }\n.rk-diffview .rk-del { background: var(--rk-danger-soft); color: var(--rk-danger); text-decoration: line-through; border-radius: 3px; padding: 0 1px; }\n.rk-diffview .rk-ins { background: rgba(62, 207, 142, 0.16); color: var(--rk-success); border-radius: 3px; padding: 0 1px; }\n.rk-diff-len { font-size: var(--rk-fs-xs); color: var(--rk-fg-faint); font-variant-numeric: tabular-nums; }\n\n.rk-imgdetail { display: flex; flex-direction: column; gap: var(--rk-s2); }\n.rk-imgdetail-meta { font-size: var(--rk-fs-xs); color: var(--rk-fg-muted); }\n.rk-imgdetail-url {\n font-size: var(--rk-fs-xs);\n color: var(--rk-accent);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n pointer-events: auto;\n}\n.rk-imgdetail-actions { display: flex; gap: var(--rk-s2); }\n.rk-imgdetail-actions .rk-btn { height: 26px; padding: 0 9px; font-size: var(--rk-fs-xs); }\n.rk-thumb-missing { display: flex; align-items: center; justify-content: center; height: 84px; font-size: var(--rk-fs-xs); color: var(--rk-fg-faint); }\n\n.rk-chips { display: flex; flex-wrap: wrap; gap: var(--rk-s2); }\n.rk-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 26px;\n padding: 0 var(--rk-s4);\n border-radius: var(--rk-r-pill);\n border: 1px solid var(--rk-hairline);\n background: var(--rk-bg-input);\n font-size: var(--rk-fs-xs);\n font-weight: 500;\n color: var(--rk-fg-muted);\n transition: background var(--rk-t-fast) var(--rk-ease), color var(--rk-t-fast) var(--rk-ease), border-color var(--rk-t-fast) var(--rk-ease);\n pointer-events: auto;\n}\n.rk-chip:hover { background: var(--rk-bg-hover); color: var(--rk-fg); }\n.rk-chip[aria-pressed='true'] {\n background: var(--rk-accent-soft);\n border-color: var(--rk-accent);\n color: var(--rk-accent);\n}\n\n.rk-unplaced {\n padding: var(--rk-s3) var(--rk-s5);\n border-bottom: 1px solid var(--rk-hairline);\n font-size: var(--rk-fs-xs);\n line-height: 1.5;\n color: var(--rk-warn);\n background: var(--rk-bg-input);\n}\n\n.rk-panel-list {\n flex: 1;\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: var(--rk-s3);\n}\n.rk-group-title {\n padding: var(--rk-s3) var(--rk-s3) var(--rk-s1);\n font-size: var(--rk-fs-xs);\n font-weight: 600;\n letter-spacing: var(--rk-track-wide);\n text-transform: uppercase;\n color: var(--rk-fg-faint);\n font-family: var(--rk-mono-stack);\n}\n\n.rk-item {\n width: 100%;\n display: flex;\n gap: var(--rk-s3);\n padding: var(--rk-s3);\n border-radius: var(--rk-r-m);\n text-align: left;\n transition: background var(--rk-t-fast) var(--rk-ease);\n border: 1px solid transparent;\n pointer-events: auto;\n cursor: pointer;\n}\n.rk-item:hover { background: var(--rk-bg-hover); }\n.rk-item.rk-active { background: var(--rk-accent-soft); border-color: var(--rk-accent); }\n.rk-item-icon {\n flex: none;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: var(--rk-r-s);\n background: var(--rk-bg-input);\n border: 1px solid var(--rk-hairline);\n color: var(--rk-accent);\n}\n.rk-item.rk-orphan .rk-item-icon { color: var(--rk-fg-faint); border-style: dashed; }\n.rk-item-body { flex: 1; min-width: 0; }\n.rk-item-snippet {\n display: block;\n font-size: var(--rk-fs-xs);\n color: var(--rk-fg-faint);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-family: var(--rk-mono-stack);\n}\n.rk-item-change {\n font-size: var(--rk-fs-m);\n color: var(--rk-fg);\n margin-top: 2px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n overflow-wrap: anywhere;\n}\n.rk-item-meta {\n display: flex;\n align-items: center;\n gap: var(--rk-s2);\n margin-top: 5px;\n flex-wrap: wrap;\n}\n.rk-badge-mini {\n display: inline-flex;\n align-items: center;\n height: 18px;\n padding: 0 7px;\n border-radius: var(--rk-r-pill);\n font-size: var(--rk-fs-xs);\n font-weight: 600;\n background: var(--rk-bg-input);\n border: 1px solid var(--rk-hairline);\n color: var(--rk-fg-muted);\n}\n.rk-badge-mini.rk-must { color: var(--rk-warn); border-color: currentColor; background: transparent; }\n.rk-badge-mini.rk-accepted { color: var(--rk-success); }\n.rk-badge-mini.rk-rejected { color: var(--rk-danger); }\n.rk-badge-mini.rk-orphaned { color: var(--rk-warn); border-style: dashed; }\n.rk-badge-mini.rk-hidden-el { color: var(--rk-fg-faint); border-style: dashed; }\n.rk-item-num {\n flex: none;\n font-size: var(--rk-fs-xs);\n font-weight: 700;\n color: var(--rk-fg-faint);\n font-variant-numeric: tabular-nums;\n padding-top: 3px;\n}\n\n.rk-item-actions { display: flex; gap: 2px; flex: none; opacity: 0; transition: opacity var(--rk-t-fast) var(--rk-ease); }\n.rk-item:hover .rk-item-actions, .rk-item.rk-active .rk-item-actions, .rk-item:focus-within .rk-item-actions { opacity: 1; }\n.rk-item-actions .rk-icon-btn { width: 24px; height: 24px; }\n\n.rk-item-edit { padding: var(--rk-s2) var(--rk-s3) var(--rk-s4) 47px; display: flex; flex-direction: column; gap: var(--rk-s3); }\n\n.rk-panel-foot {\n display: flex;\n align-items: center;\n gap: var(--rk-s1);\n padding: var(--rk-s3) var(--rk-s4);\n border-top: 1px solid var(--rk-hairline);\n /* The action set outgrew one row (Exit review, Undo): wrap instead of\n clipping — the panel body scrolls, the footer must always be whole. */\n flex-wrap: wrap;\n row-gap: var(--rk-s1);\n}\n.rk-panel-foot .rk-spacer { flex: 1; }\n.rk-panel-foot .rk-btn { height: 30px; padding: 0 8px; font-size: var(--rk-fs-s); white-space: nowrap; flex: none; }\n\n.rk-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--rk-s4);\n padding: 48px 28px;\n text-align: center;\n color: var(--rk-fg-muted);\n}\n.rk-empty-art {\n width: 56px;\n height: 56px;\n border-radius: 18px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--rk-accent-soft);\n color: var(--rk-accent);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n.rk-empty-title { font-weight: 600; color: var(--rk-fg); font-size: var(--rk-fs-l); letter-spacing: var(--rk-track-tight); }\n.rk-empty-text { font-size: var(--rk-fs-s); max-width: 230px; line-height: 1.55; }\n\n/* ---------------------------------------------------------------- */\n/* Toasts */\n/* ---------------------------------------------------------------- */\n\n.rk-toasts {\n position: fixed;\n bottom: 64px;\n left: 50%;\n translate: -50%;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--rk-s3);\n pointer-events: none;\n}\n.rk-toast {\n display: flex;\n align-items: center;\n gap: var(--rk-s3);\n max-width: min(420px, calc(100vw - 32px));\n min-height: 36px;\n padding: var(--rk-s2) var(--rk-s5);\n border-radius: var(--rk-r-pill);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-m);\n font-size: var(--rk-fs-m);\n font-weight: 500;\n color: var(--rk-fg);\n animation: rk-slide-up var(--rk-t-med) var(--rk-spring) both;\n pointer-events: auto;\n}\n.rk-toast svg { flex: none; }\n.rk-toast.rk-success svg { color: var(--rk-success); }\n.rk-toast.rk-error svg { color: var(--rk-danger); }\n.rk-toast.rk-info svg { color: var(--rk-accent); }\n\n/* ---------------------------------------------------------------- */\n/* Modals: confirm, cheatsheet, coach mark */\n/* ---------------------------------------------------------------- */\n\n.rk-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(8, 9, 14, 0.42);\n -webkit-backdrop-filter: blur(3px);\n backdrop-filter: blur(3px);\n pointer-events: auto;\n animation: rk-fade var(--rk-t-fast) var(--rk-ease) both;\n}\n.rk-modal {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 344px;\n max-width: calc(100vw - 32px);\n max-height: calc(100vh - 64px);\n overflow: auto;\n border-radius: var(--rk-r-l);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-l);\n pointer-events: auto;\n animation: rk-modal-in var(--rk-t-med) var(--rk-spring) both;\n}\n.rk-modal-body { padding: var(--rk-s6); display: flex; flex-direction: column; gap: var(--rk-s4); }\n.rk-modal-title { font-size: var(--rk-fs-xl); font-weight: 600; letter-spacing: var(--rk-track-tight); line-height: 1.25; }\n.rk-modal-text { font-size: var(--rk-fs-m); color: var(--rk-fg-muted); line-height: 1.55; }\n.rk-modal-actions { display: flex; justify-content: flex-end; gap: var(--rk-s3); padding: 0 var(--rk-s6) var(--rk-s6); }\n\n/* Shortcut cheat sheet — two columns of grouped cards on wide screens */\n.rk-cheatsheet { width: 640px; }\n.rk-cheat-head {\n display: flex;\n align-items: center;\n gap: var(--rk-s3);\n padding: var(--rk-s5) var(--rk-s6) var(--rk-s4);\n border-bottom: 1px solid var(--rk-hairline);\n}\n.rk-cheat-head-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border-radius: var(--rk-r-s);\n background: var(--rk-accent-soft);\n color: var(--rk-accent);\n flex: none;\n}\n.rk-cheat-title { font-size: var(--rk-fs-xl); font-weight: 600; letter-spacing: var(--rk-track-tight); }\n.rk-cheat-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--rk-s4);\n padding: var(--rk-s5) var(--rk-s6) var(--rk-s2);\n}\n@media (max-width: 560px) {\n .rk-cheatsheet { width: 344px; }\n .rk-cheat-grid { grid-template-columns: 1fr; }\n}\n.rk-cheat-group {\n display: flex;\n flex-direction: column;\n gap: var(--rk-s3);\n padding: var(--rk-s4);\n border: 1px solid var(--rk-hairline);\n border-radius: var(--rk-r-m);\n background: var(--rk-bg-input);\n animation: rk-rise var(--rk-t-med) var(--rk-ease) both;\n}\n.rk-cheat-group:nth-child(2) { animation-delay: 40ms; }\n.rk-cheat-group:nth-child(3) { animation-delay: 80ms; }\n.rk-cheat-group:nth-child(4) { animation-delay: 120ms; }\n.rk-cheat-group-title {\n margin: 0 0 2px;\n font-size: var(--rk-fs-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--rk-fg-faint);\n}\n.rk-shortcut-row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--rk-s4); min-height: 24px; }\n.rk-shortcut-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }\n.rk-shortcut-title { font-size: var(--rk-fs-m); color: var(--rk-fg); line-height: 1.4; }\n.rk-shortcut-desc { font-size: var(--rk-fs-xs); color: var(--rk-fg-muted); opacity: 0.9; line-height: 1.45; }\n/* chips line up with the title line, not the block center */\n.rk-shortcut-row .rk-keys { display: flex; gap: 3px; flex: none; margin-top: -1px; }\n.rk-cheatsheet .rk-kbd { min-width: 22px; height: 22px; font-size: var(--rk-fs-s); border-radius: 6px; }\n.rk-cheatsheet .rk-egg { padding: 0 var(--rk-s6) var(--rk-s5); margin: 0; }\n\n.rk-coach {\n position: fixed;\n bottom: 60px;\n left: 50%;\n /* \\`translate\\`, not \\`transform\\` — the rk-slide-up transform animation\n (fill: both) would permanently override a transform here. */\n translate: -50%;\n width: 372px;\n max-width: calc(100vw - 24px);\n border-radius: var(--rk-r-l);\n background: var(--rk-bg-elev);\n -webkit-backdrop-filter: var(--rk-blur);\n backdrop-filter: var(--rk-blur);\n border: 1px solid var(--rk-hairline);\n box-shadow: var(--rk-shadow-l);\n pointer-events: auto;\n animation: rk-slide-up var(--rk-t-slow) var(--rk-spring) both;\n overflow: hidden;\n}\n.rk-coach-accent {\n height: 2px;\n background: linear-gradient(90deg, transparent, var(--rk-accent), transparent);\n}\n.rk-coach-body { padding: var(--rk-s6); display: flex; flex-direction: column; gap: var(--rk-s4); }\n.rk-coach-keys {\n display: flex;\n flex-wrap: wrap;\n gap: var(--rk-s3) var(--rk-s4);\n font-size: var(--rk-fs-xs);\n color: var(--rk-fg-muted);\n}\n.rk-coach-keys > span { display: inline-flex; align-items: center; gap: 5px; }\n\n/* ---------------------------------------------------------------- */\n/* Responsive: bottom sheet on small screens */\n/* ---------------------------------------------------------------- */\n\n@media (max-width: 520px) {\n .rk-panel, .rk-panel.rk-right, .rk-panel.rk-left {\n top: auto;\n left: 8px;\n right: 8px;\n bottom: 8px;\n width: auto;\n max-width: none;\n max-height: 72vh;\n animation: rk-sheet-up var(--rk-t-slow) var(--rk-ease) both;\n }\n .rk-sheet-handle {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--rk-s3) 0 var(--rk-s1);\n cursor: grab;\n touch-action: none;\n }\n .rk-sheet-handle::before {\n content: '';\n width: 38px;\n height: 4px;\n border-radius: var(--rk-r-pill);\n background: var(--rk-hairline-strong);\n }\n .rk-panel-head { padding-top: var(--rk-s1); }\n .rk-card {\n top: auto !important;\n left: 8px !important;\n right: 8px;\n bottom: 8px;\n width: auto;\n }\n /* The bottom-anchored card owns the bottom edge — tuck the badge away.\n visibility, not opacity: the rk-pop entrance animation (fill: both)\n pins opacity and would override this rule. */\n .rk-root:has(.rk-card) .rk-badge { visibility: hidden; pointer-events: none; }\n .rk-toolbar { border-radius: var(--rk-r-l); }\n .rk-toolbar-btn { height: 34px; padding: 0 10px; }\n .rk-empty { padding: 28px 20px; }\n}\n\n/* ---------------------------------------------------------------- */\n/* Keyframes — entrances animate opacity/scale/translate only, never */\n/* \\`transform\\` on elements that are positioned by an inline transform */\n/* ---------------------------------------------------------------- */\n\n@keyframes rk-pop {\n from { opacity: 0; scale: 0.96; }\n to { opacity: 1; scale: 1; }\n}\n/* \\`to\\` deliberately omits opacity: with \\`both\\` fill it would pin opacity at 1\n forever and override state styling like the pick-mode ghost. */\n@keyframes rk-rise {\n from { opacity: 0; translate: 0 6px; }\n to { opacity: 1; translate: 0 0; }\n}\n@keyframes rk-drop-in {\n from { opacity: 0; scale: 0.97; margin-top: -6px; }\n to { scale: 1; margin-top: 0; }\n}\n@keyframes rk-fade {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n@keyframes rk-slide-up {\n from { opacity: 0; transform: translateY(10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes rk-sheet-up {\n from { opacity: 0; transform: translateY(24px); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes rk-slide-left {\n from { opacity: 0; transform: translateX(16px); }\n to { opacity: 1; transform: translateX(0); }\n}\n@keyframes rk-slide-right {\n from { opacity: 0; transform: translateX(-16px); }\n to { opacity: 1; transform: translateX(0); }\n}\n@keyframes rk-modal-in {\n from { opacity: 0; transform: translate(-50%, -50%) scale(0.96); }\n to { opacity: 1; transform: translate(-50%, -50%) scale(1); }\n}\n@keyframes rk-pin-in {\n from { opacity: 0; scale: 0.4; }\n to { opacity: 1; scale: 1; }\n}\n@keyframes rk-pulse {\n 0%, 100% { box-shadow: 0 0 0 0 var(--rk-accent-glow); }\n 50% { box-shadow: 0 0 0 7px rgba(0, 0, 0, 0); }\n}\n/* \\`rotate\\` property, so it can never collide with positioning transforms */\n@keyframes rk-spin {\n to { rotate: 360deg; }\n}\n@keyframes rk-fx-letter-fall {\n 0% { transform: translate(0, 0) rotate(0); opacity: 1; }\n 100% { transform: translate(var(--fx-drift, 0px), 105vh) rotate(220deg); opacity: 0.2; }\n}\n@keyframes rk-fx-band-slide {\n 0% { transform: translateY(-80px) skewY(-0.8deg); }\n 100% { transform: translateY(110vh) skewY(0.8deg); }\n}\n@keyframes rk-fx-drip-fall {\n from { translate: 0 0; scale: 1 0.4; }\n to { translate: 0 130vh; scale: 1 1.4; }\n}\n@keyframes rk-fx-crack-flare {\n 0%, 12% { opacity: 0; }\n 20%, 48% { opacity: 1; }\n 70%, 100% { opacity: 0; }\n}\n@keyframes rk-fx-crt-roll {\n from { top: -90px; }\n to { top: 100%; }\n}\n@keyframes rk-fx-crt-osd {\n 0%, 100% { opacity: 0.9; }\n 50% { opacity: 0.55; }\n}\n@keyframes rk-fx-laser-sweep {\n from { transform: rotate(-32deg); }\n to { transform: rotate(32deg); }\n}\n@keyframes rk-fx-kura-walk {\n from { translate: 0 0; }\n 25% { translate: calc(28vw) -6px; }\n 50% { translate: calc(55vw) 0; }\n 75% { translate: calc(82vw) -6px; }\n to { translate: calc(100vw + 80px) 0; }\n}\n@keyframes rk-fx-toast-in {\n from { opacity: 0; translate: 40px 0; }\n to { opacity: 1; translate: 0 0; }\n}\n@keyframes rk-fx-marquee {\n from { transform: translateX(100vw); }\n to { transform: translateX(-200vw); }\n}\n@keyframes rk-fx-fall {\n 0% { transform: translate3d(var(--fx-x0), var(--fx-y0), 0) rotate(0deg); opacity: 0; }\n 8% { opacity: 1; }\n 100% { transform: translate3d(var(--fx-x1), var(--fx-y1), 0) rotate(300deg); opacity: 0.9; }\n}\n@keyframes rk-shimmer {\n from { background-position: 200% 0; }\n to { background-position: -200% 0; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n`;\n}\n","/** Element ⇄ ReviewTarget: capture on selection, re-resolve with degradation. */\n\nimport type { BoundingBox, ReviewTarget, TargetAttrs } from '../schema';\n\nexport const HOST_ATTR = 'data-review-kit-host';\n\n/** True for elements that belong to the plugin itself (never pickable). */\nexport function isPluginElement(node: EventTarget | null): boolean {\n return node instanceof Element && node.closest(`[${HOST_ATTR}]`) !== null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Picking (which element does a point mean?) */\n/* ------------------------------------------------------------------ */\n\n/** Elements a reviewer plausibly means when clicking them. */\nconst INTERACTIVE_SELECTOR = [\n 'button',\n 'a[href]',\n 'input',\n 'select',\n 'textarea',\n 'summary',\n 'label',\n 'img',\n 'picture',\n 'video',\n 'audio',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"switch\"]',\n '[role=\"option\"]',\n '[contenteditable=\"true\"]',\n].join(', ');\n\n/** Anything bigger than this fraction of the viewport is a section/overlay\n * scale surface — never the pick while a smaller candidate sits under the\n * cursor. */\nconst MAX_PICK_AREA_FRACTION = 0.45;\n\nexport function isPickableElement(el: Element | null): el is HTMLElement {\n if (!(el instanceof HTMLElement)) return false;\n if (isPluginElement(el)) return false;\n const tag = el.tagName;\n if (tag === 'HTML' || tag === 'BODY' || tag === 'SCRIPT' || tag === 'STYLE') return false;\n return true;\n}\n\nfunction viewportAreaFraction(el: Element): number {\n const rect = el.getBoundingClientRect();\n return (rect.width * rect.height) / Math.max(1, window.innerWidth * window.innerHeight);\n}\n\nfunction rectContains(el: Element, x: number, y: number): boolean {\n const rect = el.getBoundingClientRect();\n return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;\n}\n\n/**\n * The element a reviewer MEANS at a viewport point. `elementFromPoint` alone\n * returns the topmost hit — on hero/banner sections that is a full-bleed\n * overlay or container div, so a click meant for the button inside targeted\n * the whole section. Instead walk the full hit-test stack (top → bottom):\n *\n * 1. As soon as an entry is interactive — itself, or through a wrapping\n * interactive ancestor (span inside a button) — that element wins,\n * unless it is itself page-scale.\n * 2. A non-interactive entry that is not a full-bleed surface wins as-is:\n * digging stops at the first concrete thing under the cursor.\n * 3. Only full-bleed surfaces are skipped; if everything under the point is\n * page-scale (empty section background), the topmost one is the honest\n * answer.\n */\nexport function pickElementAt(x: number, y: number): HTMLElement | null {\n const stack = document.elementsFromPoint(x, y).filter(isPickableElement);\n if (stack.length === 0) return null;\n for (const el of stack) {\n const interactive = el.matches(INTERACTIVE_SELECTOR) ? el : el.closest(INTERACTIVE_SELECTOR);\n if (\n isPickableElement(interactive) &&\n viewportAreaFraction(interactive) <= MAX_PICK_AREA_FRACTION &&\n rectContains(interactive, x, y)\n ) {\n return interactive;\n }\n if (viewportAreaFraction(el) <= MAX_PICK_AREA_FRACTION) return el;\n }\n return stack[0];\n}\n\n/** Fractional position of a viewport point inside an element's box — the pin\n * anchor, so even a large target shows its pin where the user clicked. */\nexport function pointAnchor(el: Element, x: number, y: number): { ox: number; oy: number } {\n const rect = el.getBoundingClientRect();\n return {\n ox: rect.width > 0 ? Math.min(1, Math.max(0, (x - rect.left) / rect.width)) : 0.5,\n oy: rect.height > 0 ? Math.min(1, Math.max(0, (y - rect.top) / rect.height)) : 0.5,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Capture */\n/* ------------------------------------------------------------------ */\n\n/** Heuristic: classes that look generated (CSS modules, styled-components, Tailwind JIT hashes). */\nexport function isVolatileClass(cls: string): boolean {\n if (/^(css|sc|jsx|svelte|astro|emotion)-/i.test(cls)) return true;\n if (/_[a-z0-9_-]{5,}$/i.test(cls) && /\\d/.test(cls)) return true;\n if (/[0-9a-f]{6,}/i.test(cls)) return true;\n if (cls.length >= 10 && /\\d/.test(cls) && !/[-_]/.test(cls)) return true;\n return false;\n}\n\nfunction cssEscape(value: string): string {\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') return CSS.escape(value);\n return value.replace(/[^a-zA-Z0-9_-]/g, (c) => `\\\\${c}`);\n}\n\nfunction nthOfTypeIndex(el: Element): number {\n let index = 1;\n let sibling = el.previousElementSibling;\n while (sibling) {\n if (sibling.tagName === el.tagName) index++;\n sibling = sibling.previousElementSibling;\n }\n return index;\n}\n\n/** Build a stable selector path from the nearest unique-id ancestor (or body) down. */\nexport function buildSelector(el: Element): string {\n const segments: string[] = [];\n let node: Element | null = el;\n while (node && node !== document.body && node !== document.documentElement) {\n const id = node.getAttribute('id');\n if (id && !/\\d{3,}/.test(id)) {\n const idSelector = `#${cssEscape(id)}`;\n try {\n if (document.querySelectorAll(idSelector).length === 1) {\n segments.unshift(idSelector);\n return segments.join(' > ');\n }\n } catch {\n /* invalid id for selector use — fall through to tag path */\n }\n }\n const tag = node.tagName.toLowerCase();\n segments.unshift(`${tag}:nth-of-type(${nthOfTypeIndex(node)})`);\n node = node.parentElement;\n }\n segments.unshift('body');\n return segments.join(' > ');\n}\n\n/** nth-of-type index chain from body down to the element (1-based). */\nexport function buildNthPath(el: Element): number[] {\n const path: number[] = [];\n let node: Element | null = el;\n while (node && node !== document.body && node !== document.documentElement) {\n path.unshift(nthOfTypeIndex(node));\n node = node.parentElement;\n }\n return path;\n}\n\nexport function textSnippetOf(el: Element): string {\n const text = (el.textContent ?? '').replace(/\\s+/g, ' ').trim();\n return text.length > 120 ? `${text.slice(0, 120)}…` : text;\n}\n\nfunction captureAttrs(el: Element): TargetAttrs {\n const attrs: TargetAttrs = {};\n const id = el.getAttribute('id');\n if (id) attrs.id = id;\n const classList = Array.from(el.classList);\n if (classList.length > 0) attrs.classList = classList;\n const alt = el.getAttribute('alt');\n if (alt !== null) attrs.alt = alt;\n const src = el.getAttribute('src');\n if (src !== null) attrs.src = src;\n const href = el.getAttribute('href');\n if (href !== null) attrs.href = href;\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel !== null) attrs.ariaLabel = ariaLabel;\n const data: Record<string, string> = {};\n let hasData = false;\n for (const attr of Array.from(el.attributes)) {\n if (attr.name.startsWith('data-')) {\n data[attr.name.slice(5)] = attr.value;\n hasData = true;\n }\n }\n if (hasData) attrs.data = data;\n return attrs;\n}\n\nexport function captureTarget(el: Element): ReviewTarget {\n const rect = el.getBoundingClientRect();\n const boundingBox: BoundingBox = {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n };\n return {\n selector: buildSelector(el),\n tagName: el.tagName.toLowerCase(),\n textSnippet: textSnippetOf(el),\n attrs: captureAttrs(el),\n nthOfType: buildNthPath(el),\n boundingBox,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Resolution (graceful degradation) */\n/* ------------------------------------------------------------------ */\n\nexport type ResolveMethod = 'exact' | 'structure' | 'text' | 'fuzzy';\n\nexport interface Resolved {\n element: Element;\n method: ResolveMethod;\n}\n\n/** Does the element's tag match the target's? A target with no recorded\n * tagName (partial data from sync/import) can't disprove a match. */\nfunction tagMatches(el: Element, target: ReviewTarget): boolean {\n return typeof target.tagName !== 'string' || target.tagName === '' || el.tagName.toLowerCase() === target.tagName;\n}\n\nfunction bySelector(target: ReviewTarget): Element | null {\n if (typeof target.selector === 'string' && target.selector !== '') {\n try {\n const el = document.querySelector(target.selector);\n if (el && tagMatches(el, target)) return el;\n } catch {\n /* selector no longer parseable */\n }\n }\n // Items from sync or import may carry a partial target — attrs is not\n // guaranteed to be an object (this exact read used to crash every render).\n const id = target.attrs?.id;\n if (id) {\n const el = document.getElementById(id);\n if (el && tagMatches(el, target)) return el;\n }\n return null;\n}\n\nfunction byStructure(target: ReviewTarget): Element | null {\n // Walk the nth-of-type chain from body down. Tag names per level aren't\n // stored, so at each level pick the child whose per-tag index matches and\n // accept the result only if the final tag matches the target's. Without a\n // recorded tagName the result can't be verified — treat as unresolvable.\n if (!Array.isArray(target.nthOfType) || typeof target.tagName !== 'string' || target.tagName === '') return null;\n let node: Element | null = document.body;\n for (const index of target.nthOfType) {\n if (!node) return null;\n let found: Element | null = null;\n const counters = new Map<string, number>();\n for (const child of Array.from(node.children)) {\n const n = (counters.get(child.tagName) ?? 0) + 1;\n counters.set(child.tagName, n);\n if (n === index && found === null) found = child;\n }\n node = found;\n }\n if (node && node.tagName.toLowerCase() === target.tagName) return node;\n return null;\n}\n\nfunction normalize(text: string): string {\n return text.replace(/\\s+/g, ' ').trim().toLowerCase();\n}\n\n/** Dice coefficient over character bigrams — small, dependency-free fuzziness. */\nfunction similarity(a: string, b: string): number {\n if (a === b) return 1;\n if (a.length < 2 || b.length < 2) return 0;\n const bigrams = new Map<string, number>();\n for (let i = 0; i < a.length - 1; i++) {\n const bg = a.slice(i, i + 2);\n bigrams.set(bg, (bigrams.get(bg) ?? 0) + 1);\n }\n let hits = 0;\n for (let i = 0; i < b.length - 1; i++) {\n const bg = b.slice(i, i + 2);\n const n = bigrams.get(bg) ?? 0;\n if (n > 0) {\n bigrams.set(bg, n - 1);\n hits++;\n }\n }\n return (2 * hits) / (a.length - 1 + (b.length - 1));\n}\n\nfunction byText(target: ReviewTarget, fuzzy: boolean): Element | null {\n if (typeof target.textSnippet !== 'string' || typeof target.tagName !== 'string' || target.tagName === '') return null;\n const want = normalize(target.textSnippet.replace(/…$/, ''));\n if (want.length < 3) return null;\n const candidates = Array.from(document.querySelectorAll(target.tagName));\n let best: Element | null = null;\n let bestScore = 0;\n for (const el of candidates) {\n if (isPluginElement(el)) continue;\n const text = normalize((el.textContent ?? '').slice(0, 240));\n if (!fuzzy) {\n if (text.startsWith(want) || want.startsWith(text.slice(0, want.length))) return el;\n continue;\n }\n const score = similarity(want, text.slice(0, want.length + 40));\n if (score > bestScore) {\n bestScore = score;\n best = el;\n }\n }\n return fuzzy && bestScore >= 0.6 ? best : null;\n}\n\n/**\n * Re-find an element from a target. Degrades: exact selector → structural\n * nth-of-type walk → exact text match → fuzzy text match → null (orphaned).\n */\nexport function resolveTarget(target: ReviewTarget): Resolved | null {\n // Remote peers and imported sessions can hand us anything — a malformed\n // target must resolve to \"orphaned\", never throw (a throw here takes down\n // every consumer: Panel, Pins, outlines).\n if (typeof target !== 'object' || target === null) return null;\n const exact = bySelector(target);\n if (exact) return { element: exact, method: 'exact' };\n const structural = byStructure(target);\n if (structural) return { element: structural, method: 'structure' };\n const textual = byText(target, false);\n if (textual) return { element: textual, method: 'text' };\n const fuzzy = byText(target, true);\n if (fuzzy) return { element: fuzzy, method: 'fuzzy' };\n return null;\n}\n\n/** Human-readable one-line label for an element, e.g. `h1 · \"Predávate pôdu?\"`. */\nexport function describeElement(el: Element): string {\n const tag = el.tagName.toLowerCase();\n const snippet = textSnippetOf(el);\n if (snippet) return `${tag} · “${snippet.length > 42 ? `${snippet.slice(0, 42)}…` : snippet}”`;\n if (el instanceof HTMLImageElement && el.alt) return `${tag} · ${el.alt}`;\n return tag;\n}\n\n/**\n * Is the element actually visible on the page (mounted, not display:none /\n * visibility:hidden, not inside a closed container, non-zero box)?\n */\nexport function isElementVisible(el: Element): boolean {\n if (!el.isConnected) return false;\n const maybe = el as Element & { checkVisibility?: (o?: object) => boolean };\n if (typeof maybe.checkVisibility === 'function') {\n return maybe.checkVisibility({ checkVisibilityCSS: true });\n }\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) return false;\n return getComputedStyle(el).visibility !== 'hidden';\n}\n\n/** The image element for a target, if the element is or contains one. */\nexport function findImage(el: Element): HTMLImageElement | null {\n if (el instanceof HTMLImageElement) return el;\n return el.querySelector('img');\n}\n","/**\n * ReviewKit → Emblema dispatch (Workstream B of INTEGRATION-EMBLEMA.md).\n *\n * This file is the AUTHORITATIVE definition of the EmblemaReviewDispatch v1\n * contract — Emblema vendors a copy of the type (its\n * src/lib/review-intake-contract.ts points back here). Do not rename or add\n * payload fields without bumping REVIEW_DISPATCH_VERSION; the receiving end\n * rejects any other `v`.\n *\n * Transport per the spec: GET /intake/ping to find a live app, then one\n * POST /intake/review with the whole batch. One-way in v1 — Emblema shows an\n * approval card; nothing flows back to the page. No queueing: if the app is\n * not running the caller shows a toast and gives up.\n */\n\nimport type { ReviewItem, ReviewSession } from '../schema';\n\nexport const REVIEW_DISPATCH_VERSION = 1;\n\n/** Fixed intake ports, in probe order (spec §3.1: 48752, fallbacks if busy). */\nexport const EMBLEMA_INTAKE_PORTS = [48752, 48753, 48754, 48755] as const;\n\n/**\n * ReviewKitConfig.emblema — enables the Emblema bridge. `{}` is a valid\n * value: the repo Emblema should edit is Emblema's own local knowledge (it\n * knows which project it opened; the `reviewkit-emblema` agent has it in\n * `.reviewkit/emblema-sync.json`), so an absolute path from the reviewer's\n * machine never has to appear in the host site's code.\n */\nexport interface EmblemaConfig {\n /**\n * Override the repo path sent with each batch. Normally omitted: the\n * intake advertises its own `repoPath` in the `/intake/ping` answer, and\n * when it does not, the field is left out and Emblema falls back to its\n * active project.\n */\n repoPath?: string;\n /** Pin the intake to one port instead of probing the default list. */\n port?: number;\n}\n\n/** The v1 payload of POST /intake/review — field names are frozen. */\nexport interface EmblemaReviewDispatch {\n v: typeof REVIEW_DISPATCH_VERSION;\n source: 'review-kit';\n batchId: string;\n /** ISO 8601 */\n sentAt: string;\n /**\n * Absolute repo path — `emblema.repoPath` if configured, else the path the\n * intake advertised on ping. Omitted when neither is known; the receiver\n * then uses its active project. (Optional since 0.1.3; still `v: 1`.)\n */\n repoPath?: string;\n site: {\n origin: string;\n reviewUrl: string;\n };\n sessionAuthor: string;\n /** 1..200 verbatim ReviewItems (spec sends only actionable statuses). */\n items: ReviewItem[];\n}\n\nexport type SendResult =\n | { ok: true; batchId: string; sent: number; port: number }\n | { ok: false; reason: 'offline' | 'rejected' | 'no-items'; detail?: string };\n\n/** Max items per batch (spec §3.2). */\nexport const MAX_DISPATCH_ITEMS = 200;\n\nfunction batchId(): string {\n return `rk-batch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction portsFor(config: EmblemaConfig): number[] {\n return config.port !== undefined ? [config.port] : [...EMBLEMA_INTAKE_PORTS];\n}\n\n/**\n * Order items the way Emblema's route-grouping consumes them (spec §3.3):\n * grouped by route, `must` before `nice` inside a group, then oldest first.\n * The payload stays a flat array — grouping itself happens on the Emblema side.\n */\nexport function orderForDispatch(items: ReviewItem[]): ReviewItem[] {\n const routeOrder: string[] = [];\n for (const item of items) if (!routeOrder.includes(item.route)) routeOrder.push(item.route);\n return [...items].sort((a, b) => {\n const byRoute = routeOrder.indexOf(a.route) - routeOrder.indexOf(b.route);\n if (byRoute !== 0) return byRoute;\n if (a.priority !== b.priority) return a.priority === 'must' ? -1 : 1;\n return a.createdAt < b.createdAt ? -1 : a.createdAt > b.createdAt ? 1 : 0;\n });\n}\n\n/** Build the v1 payload. Caller pre-filters items to the statuses it wants sent. */\nexport function buildDispatch(\n session: ReviewSession | null,\n items: ReviewItem[],\n config: EmblemaConfig,\n advertisedRepoPath?: string,\n): EmblemaReviewDispatch {\n const origin = window.location.origin;\n const repoPath = config.repoPath ?? advertisedRepoPath;\n return {\n v: REVIEW_DISPATCH_VERSION,\n source: 'review-kit',\n batchId: batchId(),\n sentAt: new Date().toISOString(),\n ...(repoPath ? { repoPath } : {}),\n site: {\n origin,\n reviewUrl: window.location.href,\n },\n sessionAuthor: session?.author ?? '',\n items: orderForDispatch(items).slice(0, MAX_DISPATCH_ITEMS),\n };\n}\n\nasync function fetchJson(url: string, init: RequestInit, timeoutMs: number): Promise<Response> {\n const abort = new AbortController();\n const timer = window.setTimeout(() => abort.abort(), timeoutMs);\n try {\n return await fetch(url, { ...init, signal: abort.signal });\n } finally {\n window.clearTimeout(timer);\n }\n}\n\nexport interface EmblemaProbe {\n port: number;\n /** Repo the intake is bound to, when the ping answer advertises one. */\n repoPath?: string;\n}\n\n/**\n * Find a live intake: first port whose /intake/ping answers as Emblema.\n * The answer may carry `repoPath` (the project Emblema has open for this\n * pairing); it becomes the batch's `repoPath` unless the config overrides it.\n */\nexport async function probeEmblema(config: EmblemaConfig): Promise<EmblemaProbe | null> {\n for (const port of portsFor(config)) {\n try {\n const res = await fetchJson(`http://127.0.0.1:${port}/intake/ping`, { method: 'GET' }, 1200);\n if (!res.ok) continue;\n const body: unknown = await res.json();\n if (typeof body === 'object' && body !== null && (body as { app?: unknown }).app === 'emblema') {\n const repoPath = (body as { repoPath?: unknown }).repoPath;\n return typeof repoPath === 'string' && repoPath !== '' ? { port, repoPath } : { port };\n }\n } catch {\n /* connection refused / timeout — try the next port */\n }\n }\n return null;\n}\n\n/** Port of a live intake, or null. Thin wrapper over `probeEmblema`. */\nexport async function pingEmblema(config: EmblemaConfig): Promise<number | null> {\n const probe = await probeEmblema(config);\n return probe?.port ?? null;\n}\n\n/** Ping, then POST the batch. Never queues; never retries. */\nexport async function sendToEmblema(\n session: ReviewSession | null,\n items: ReviewItem[],\n config: EmblemaConfig,\n): Promise<SendResult> {\n if (items.length === 0) return { ok: false, reason: 'no-items' };\n const probe = await probeEmblema(config);\n if (probe === null) return { ok: false, reason: 'offline' };\n const { port } = probe;\n const payload = buildDispatch(session, items, config, probe.repoPath);\n try {\n const res = await fetchJson(\n `http://127.0.0.1:${port}/intake/review`,\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n 10_000,\n );\n if (!res.ok) return { ok: false, reason: 'rejected', detail: `HTTP ${res.status}` };\n const body: unknown = await res.json().catch(() => null);\n const returnedId =\n typeof body === 'object' && body !== null && typeof (body as { batchId?: unknown }).batchId === 'string'\n ? ((body as { batchId: string }).batchId)\n : payload.batchId;\n return { ok: true, batchId: returnedId, sent: payload.items.length, port };\n } catch {\n return { ok: false, reason: 'offline' };\n }\n}\n\n/* ---------------- pairing (contract v2) ---------------- */\n\n/** Local sync agent (reviewkit-emblema serve) management API ports. */\nexport const EMBLEMA_SYNC_PORTS = [48770, 48771, 48772, 48773] as const;\n\nexport interface EmblemaSyncState {\n ok: true;\n paired: boolean;\n revoked: boolean;\n id: string;\n name: string;\n url: string;\n lastAck: string | null;\n findings: number;\n}\n\nasync function localFetch(path: string, init?: RequestInit): Promise<Response | null> {\n for (const port of EMBLEMA_SYNC_PORTS) {\n try {\n const abort = new AbortController();\n const timer = window.setTimeout(() => abort.abort(), 1200);\n const res = await fetch(`http://127.0.0.1:${port}${path}`, { ...init, signal: abort.signal });\n window.clearTimeout(timer);\n return res;\n } catch {\n /* next port */\n }\n }\n return null;\n}\n\n/** State of the local pairing agent; null when it isn't running. */\nexport async function fetchSyncState(): Promise<EmblemaSyncState | null> {\n const res = await localFetch('/api/emblema/local/state');\n if (!res || !res.ok) return null;\n const body: unknown = await res.json().catch(() => null);\n return typeof body === 'object' && body !== null && (body as { ok?: unknown }).ok === true\n ? (body as EmblemaSyncState)\n : null;\n}\n\n/** Generate (or rotate — same operation) the pairing key; returns emk_… */\nexport async function generateSyncKey(): Promise<string | null> {\n const res = await localFetch('/api/emblema/local/generate', { method: 'POST' });\n if (!res || !res.ok) return null;\n const body: unknown = await res.json().catch(() => null);\n const key = (body as { key?: unknown } | null)?.key;\n return typeof key === 'string' ? key : null;\n}\n\n/** Current key without rotating (Copy button). */\nexport async function fetchSyncKey(): Promise<string | null> {\n const res = await localFetch('/api/emblema/local/key');\n if (!res || !res.ok) return null;\n const body: unknown = await res.json().catch(() => null);\n const key = (body as { key?: unknown } | null)?.key;\n return typeof key === 'string' ? key : null;\n}\n\nexport async function revokeSyncKey(): Promise<boolean> {\n const res = await localFetch('/api/emblema/local/revoke', { method: 'POST' });\n return res !== null && res.ok;\n}\n","/**\n * review-kit session schema — the contract everything else depends on.\n *\n * Forward compatibility rules:\n * - Every object carries an index signature, so unknown fields parsed from a\n * file are kept in memory and survive a load → save round-trip.\n * - Item `type` is open-ended: unknown types are preserved as\n * {@link UnknownReviewItem} and never dropped.\n *\n * Kept in sync with `schema/review-session.schema.json`.\n */\n\nexport const SCHEMA_VERSION = 1;\n\nexport type ItemStatus = 'open' | 'accepted' | 'rejected' | 'applied';\nexport type ItemPriority = 'must' | 'nice';\nexport type KnownItemType = 'copy' | 'image' | 'comment' | 'delete' | 'move' | 'style';\n\nexport const ITEM_STATUSES: readonly ItemStatus[] = ['open', 'accepted', 'rejected', 'applied'];\nexport const KNOWN_ITEM_TYPES: readonly KnownItemType[] = [\n 'copy',\n 'image',\n 'comment',\n 'delete',\n 'move',\n 'style',\n];\n\n/** Extra fields from future schema versions are preserved, never dropped. */\nexport interface Extensible {\n [extra: string]: unknown;\n}\n\nexport interface BoundingBox extends Extensible {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface TargetAttrs extends Extensible {\n id?: string;\n classList?: string[];\n alt?: string;\n src?: string;\n href?: string;\n ariaLabel?: string;\n /** All `data-*` attributes, keyed without the `data-` prefix. */\n data?: Record<string, string>;\n}\n\n/**\n * Everything needed to find the element again — by the plugin (to re-pin it)\n * and by a coding agent (to locate it in source).\n */\nexport interface ReviewTarget extends Extensible {\n /** Stable CSS selector path (id-anchored where possible, no hashed classes). */\n selector: string;\n tagName: string;\n /** Trimmed, whitespace-collapsed text content, first ~120 chars. */\n textSnippet: string;\n attrs: TargetAttrs;\n /** nth-of-type index chain from <body> down to the element (1-based). */\n nthOfType: number[];\n /** Viewport-relative bounding box at capture time. */\n boundingBox: BoundingBox;\n /** Reserved for phase 4 (source mapping). */\n sourceFile?: string;\n sourceLine?: number;\n /** Fractional point inside the element's box (0..1) the item refers to. */\n anchor?: { ox: number; oy: number } & Extensible;\n}\n\nexport interface CopyPayload extends Extensible {\n before: string;\n after: string;\n}\n\nexport interface ImagePayload extends Extensible {\n beforeSrc: string;\n /**\n * Replacement image by reference — an external URL that couldn't be\n * embedded (CORS) or exceeded the embed cap. Exclusive with afterDataUrl.\n */\n afterSrc?: string;\n /** Replacement image embedded inline as a data: URL (2 MB cap at capture). */\n afterDataUrl?: string;\n description?: string;\n}\n\nexport interface CommentPayload extends Extensible {\n text: string;\n}\n\nexport interface DeletePayload extends Extensible {\n reason?: string;\n}\n\nexport interface MovePayload extends Extensible {\n direction?: 'up' | 'down' | 'first' | 'last';\n targetDescription?: string;\n}\n\nexport interface StylePayload extends Extensible {\n description: string;\n}\n\nexport interface ReviewItemBase extends Extensible {\n id: string;\n /** ISO 8601 */\n createdAt: string;\n /** Who created the item (additive; older sessions may lack it). */\n author?: { id: string; name: string; color?: string } & Extensible;\n type: string;\n status: ItemStatus;\n /** Pathname where the item was captured. */\n route: string;\n target: ReviewTarget;\n /** Optional free text from the reviewer, in addition to the payload. */\n note?: string;\n priority: ItemPriority;\n}\n\nexport interface CopyItem extends ReviewItemBase {\n type: 'copy';\n payload: CopyPayload;\n}\nexport interface ImageItem extends ReviewItemBase {\n type: 'image';\n payload: ImagePayload;\n}\nexport interface CommentItem extends ReviewItemBase {\n type: 'comment';\n payload: CommentPayload;\n}\nexport interface DeleteItem extends ReviewItemBase {\n type: 'delete';\n payload: DeletePayload;\n}\nexport interface MoveItem extends ReviewItemBase {\n type: 'move';\n payload: MovePayload;\n}\nexport interface StyleItem extends ReviewItemBase {\n type: 'style';\n payload: StylePayload;\n}\n\nexport type KnownReviewItem = CopyItem | ImageItem | CommentItem | DeleteItem | MoveItem | StyleItem;\n\n/** An item of a type this build doesn't know about — carried through untouched. */\nexport interface UnknownReviewItem extends ReviewItemBase {\n payload?: unknown;\n}\n\nexport type ReviewItem = KnownReviewItem | UnknownReviewItem;\n\nexport interface SiteInfo extends Extensible {\n origin: string;\n /** Pathname of the route the session was started on. */\n route: string;\n viewport: { width: number; height: number } & Extensible;\n userAgent: string;\n}\n\nexport interface ReviewSession extends Extensible {\n schemaVersion: number;\n id: string;\n /** ISO 8601 */\n createdAt: string;\n /** ISO 8601 */\n updatedAt: string;\n site: SiteInfo;\n /** Free-text reviewer name, typed once. */\n author: string;\n items: ReviewItem[];\n}\n\n/* ------------------------------------------------------------------ */\n/* Type guards */\n/* ------------------------------------------------------------------ */\n\nexport function isKnownItemType(type: string): type is KnownItemType {\n return (KNOWN_ITEM_TYPES as readonly string[]).includes(type);\n}\n\nexport function isCopyItem(item: ReviewItem): item is CopyItem {\n return item.type === 'copy';\n}\nexport function isImageItem(item: ReviewItem): item is ImageItem {\n return item.type === 'image';\n}\nexport function isCommentItem(item: ReviewItem): item is CommentItem {\n return item.type === 'comment';\n}\nexport function isDeleteItem(item: ReviewItem): item is DeleteItem {\n return item.type === 'delete';\n}\nexport function isMoveItem(item: ReviewItem): item is MoveItem {\n return item.type === 'move';\n}\nexport function isStyleItem(item: ReviewItem): item is StyleItem {\n return item.type === 'style';\n}\n\n/* ------------------------------------------------------------------ */\n/* Validation */\n/* ------------------------------------------------------------------ */\n\nexport type ParseResult =\n | { ok: true; session: ReviewSession }\n | { ok: false; error: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction fail(error: string): ParseResult {\n return { ok: false, error };\n}\n\n/**\n * Validate an unknown value (already JSON-parsed) into a ReviewSession.\n * Tolerant of unknown fields and unknown item types (forward compatibility);\n * strict about the structural minimum each item needs to be useful.\n * Missing `status` defaults to 'open', missing `priority` to 'nice'.\n */\nexport function parseSession(value: unknown): ParseResult {\n if (!isRecord(value)) return fail('Not a JSON object.');\n if (typeof value.schemaVersion !== 'number') {\n return fail('Missing or invalid \"schemaVersion\" (expected a number).');\n }\n if (typeof value.id !== 'string' || value.id.length === 0) {\n return fail('Missing or invalid session \"id\".');\n }\n if (!isRecord(value.site) || typeof value.site.origin !== 'string') {\n return fail('Missing or invalid \"site\" (expected { origin, route, viewport, userAgent }).');\n }\n if (!Array.isArray(value.items)) {\n return fail('Missing or invalid \"items\" (expected an array).');\n }\n\n const items: ReviewItem[] = [];\n for (let i = 0; i < value.items.length; i++) {\n const raw: unknown = value.items[i];\n if (!isRecord(raw)) return fail(`Item ${i + 1} is not an object.`);\n if (typeof raw.id !== 'string' || raw.id.length === 0) {\n return fail(`Item ${i + 1} is missing an \"id\".`);\n }\n if (typeof raw.type !== 'string' || raw.type.length === 0) {\n return fail(`Item ${i + 1} (\"${raw.id}\") is missing a \"type\".`);\n }\n if (!isRecord(raw.target) || typeof raw.target.selector !== 'string') {\n return fail(`Item ${i + 1} (\"${raw.id}\") is missing a valid \"target\".`);\n }\n const status: ItemStatus = (ITEM_STATUSES as readonly string[]).includes(String(raw.status))\n ? (raw.status as ItemStatus)\n : 'open';\n const priority: ItemPriority = raw.priority === 'must' ? 'must' : 'nice';\n items.push({\n ...raw,\n status,\n priority,\n createdAt: typeof raw.createdAt === 'string' ? raw.createdAt : new Date(0).toISOString(),\n route: typeof raw.route === 'string' ? raw.route : '/',\n target: raw.target as ReviewTarget,\n } as ReviewItem);\n }\n\n const site = value.site;\n const viewport = isRecord(site.viewport) ? site.viewport : {};\n const session: ReviewSession = {\n ...value,\n schemaVersion: value.schemaVersion,\n id: value.id,\n createdAt: typeof value.createdAt === 'string' ? value.createdAt : new Date(0).toISOString(),\n updatedAt: typeof value.updatedAt === 'string' ? value.updatedAt : new Date(0).toISOString(),\n author: typeof value.author === 'string' ? value.author : '',\n site: {\n ...site,\n origin: typeof site.origin === 'string' ? site.origin : '',\n route: typeof site.route === 'string' ? site.route : '/',\n viewport: {\n ...viewport,\n width: typeof viewport.width === 'number' ? viewport.width : 0,\n height: typeof viewport.height === 'number' ? viewport.height : 0,\n },\n userAgent: typeof site.userAgent === 'string' ? site.userAgent : '',\n },\n items,\n };\n return { ok: true, session };\n}\n\n/** Parse a raw JSON string into a session, with a readable error on failure. */\nexport function parseSessionJson(json: string): ParseResult {\n let value: unknown;\n try {\n value = JSON.parse(json);\n } catch {\n return fail('File is not valid JSON.');\n }\n return parseSession(value);\n}\n\n// Emblema integration contract (authoritative definition lives in\n// src/integrations/emblema.ts; re-exported here so review-kit/schema carries it).\nexport type { EmblemaReviewDispatch, EmblemaConfig } from './integrations/emblema';\nexport { REVIEW_DISPATCH_VERSION } from './integrations/emblema';\n","/** Tiny dependency-free id generator: time prefix + 64 bits of randomness. */\nexport function rkId(): string {\n const time = Date.now().toString(36);\n let rand = '';\n const cryptoObj = typeof crypto !== 'undefined' ? crypto : undefined;\n if (cryptoObj?.getRandomValues) {\n const bytes = cryptoObj.getRandomValues(new Uint8Array(8));\n for (const b of bytes) rand += b.toString(36).padStart(2, '0');\n } else {\n for (let i = 0; i < 4; i++) {\n rand += Math.floor(Math.random() * 36 ** 4)\n .toString(36)\n .padStart(4, '0');\n }\n }\n return `rk-${time}-${rand}`;\n}\n","/** Plugin state: session + UI, reducer-based, with a bounded undo stack. */\n\nimport { createContext, useContext, useMemo, useReducer } from 'react';\nimport type { Dispatch, ReactNode } from 'react';\nimport type { ItemStatus, ReviewItem, ReviewSession } from '../schema';\nimport type { EmblemaConfig } from '../integrations/emblema';\nimport { SCHEMA_VERSION } from '../schema';\nimport { rkId } from './id';\nimport type { ReviewTarget } from '../schema';\n\nexport type BadgeCorner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n\nexport interface ReviewKitConfig {\n /**\n * Master switch. `false` renders nothing and installs nothing — no\n * listeners, no storage reads, no network. Default `true`. Lets a host\n * write `<ReviewKit enabled={Boolean(TOKEN)} token={TOKEN} />` instead of\n * `if (!TOKEN) return null`.\n */\n enabled?: boolean;\n /**\n * Activation token: the layer turns on only via `?review=<token>` (or the\n * per-tab session such a link starts). REQUIRED for any activation —\n * without it the component stays off, whatever the URL says. Public in the\n * bundle by nature; a gate against casual visitors, not a secret.\n */\n token?: string;\n /**\n * Force the layer on for this page load regardless of URL/token. Meant for\n * local development (`devAutoOn={import.meta.env.DEV}`); the library never\n * reads NODE_ENV itself. Still subject to `enabled` and `allowedHosts`.\n */\n devAutoOn?: boolean;\n /**\n * Shared secret for the realtime sync server. Public in the browser by\n * nature (anyone with the review URL + bundle can read it) — it gates\n * casual access, not determined attackers. Sync runs only when BOTH\n * `syncToken` and `syncUrl` are set; otherwise solo mode, no network.\n */\n syncToken?: string;\n /**\n * WebSocket endpoint of your sync server (`realtime/server`), e.g.\n * `wss://your-site.tld/rk-sync`. No default — there is no public server.\n * Unreachable/invalid = silent local mode. Remember the host page's CSP\n * must allow it in `connect-src` (see README \"CSP\").\n */\n syncUrl?: string;\n /**\n * Optional host allowlist for where review may activate at all — e.g.\n * ['localhost', '*.dev.mojweb.sk', 'test.mojweb.sk']. Outside it nothing\n * activates, even with the right token. Unset = works everywhere; a URL\n * activation on a public host without it logs a one-time console warning.\n */\n allowedHosts?: string[];\n defaultAuthor?: string;\n /**\n * Base URL of the static assets the `/` command effects use for sound\n * (currently `rick.mp3` for /ondro). Default: the public ReviewKit assets\n * host `https://2-59-219-26.sslip.io/rk-assets`. Override to self-host;\n * the origin must be allowed by CSP `media-src`.\n */\n fxAssetsUrl?: string;\n /**\n * Enables the Emblema bridge: review items push to a locally running\n * Emblema app automatically as they change (debounced, silent-fail), and\n * the panel's session menu gains a \"Resend all to Emblema\" fallback\n * (see INTEGRATION-EMBLEMA.md).\n */\n emblema?: EmblemaConfig;\n position?: BadgeCorner;\n storageKey?: string;\n onSessionChange?: (session: ReviewSession) => void;\n}\n\nexport type EditorKind = 'copy' | 'image' | 'comment' | 'delete' | 'move' | 'style';\n\n/** Armed pick-mode tool: what the next click on the page does. */\nexport type ToolKind = 'select' | 'comment' | 'copy' | 'image';\n\nexport interface EditorState {\n kind: EditorKind;\n element: HTMLElement;\n target: ReviewTarget;\n}\n\nexport interface SelectionState {\n element: HTMLElement;\n target: ReviewTarget;\n}\n\nexport type ToastTone = 'info' | 'success' | 'error';\n\nexport type SyncStatus = 'disabled' | 'connecting' | 'online' | 'offline';\n\n/** Automatic Emblema push: 'idle' until the first attempt, then last outcome. */\nexport type EmblemaPushStatus = 'idle' | 'sending' | 'ok' | 'offline' | 'rejected';\n\nexport interface PeerCursor {\n /** Normalized document-fraction fallback (0..1). */\n x: number;\n y: number;\n /** Element anchor: selector + fractional offset inside its box. */\n sel?: string;\n ox?: number;\n oy?: number;\n}\n\nexport interface PeerState {\n id: string;\n name: string;\n color: string;\n cursor: PeerCursor | null;\n selecting: string | null;\n typingItemId: string | null;\n typingActive: boolean;\n}\n\n/** The `/` quick-comment composer, opened at the pointer position. */\nexport interface QuickComposer {\n /** Unique per opening — keys the composer so each open starts fresh. */\n id: string;\n x: number;\n y: number;\n element: HTMLElement;\n target: ReviewTarget;\n}\n\nexport interface ToastData {\n id: string;\n message: string;\n tone: ToastTone;\n}\n\nexport interface ConfirmState {\n title: string;\n message: string;\n confirmLabel: string;\n danger: boolean;\n onConfirm: () => void;\n}\n\nexport interface State {\n session: ReviewSession | null;\n route: string;\n /** Edited view on (saved changes mirrored into the page) vs pristine original. */\n preview: boolean;\n /** Saved changes that couldn't be placed on the current page in edited view. */\n unapplied: number;\n badgeCorner: BadgeCorner;\n mode: 'idle' | 'pick';\n tool: ToolKind;\n /** Presentation mode: whole review layer hidden, page shown clean. */\n hidden: boolean;\n selection: SelectionState | null;\n editor: EditorState | null;\n panelOpen: boolean;\n activeItemId: string | null;\n toasts: ToastData[];\n confirm: ConfirmState | null;\n cheatsheetOpen: boolean;\n emblemaConnectOpen: boolean;\n coachOpen: boolean;\n undoStack: ReviewItem[][];\n syncStatus: SyncStatus;\n emblemaPush: EmblemaPushStatus;\n peers: PeerState[];\n quick: QuickComposer | null;\n /** Panel filters mirrored for the pin layer (null = no filter active). */\n filter: ItemFilter | null;\n}\n\n/** Active panel filters; empty arrays mean \"no constraint\" for that facet. */\nexport interface ItemFilter {\n types: string[];\n priorities: string[];\n statuses: string[];\n}\n\n/** Does an item pass the combinable type / priority / status filters? */\nexport function itemMatchesFilter(item: ReviewItem, filter: ItemFilter | null): boolean {\n if (!filter) return true;\n if (filter.types.length > 0 && !filter.types.includes(item.type)) return false;\n if (filter.priorities.length > 0 && !filter.priorities.includes(item.priority)) return false;\n if (filter.statuses.length > 0 && !filter.statuses.includes(item.status)) return false;\n return true;\n}\n\nexport type Action =\n | { type: 'INIT_SESSION'; session: ReviewSession }\n | { type: 'SET_ROUTE'; route: string }\n | { type: 'SET_MODE'; mode: 'idle' | 'pick' }\n | { type: 'SET_FILTER'; filter: ItemFilter | null }\n | { type: 'SET_TOOL'; tool: ToolKind }\n | { type: 'SET_HIDDEN'; on: boolean }\n | { type: 'SELECT'; selection: SelectionState | null }\n | { type: 'OPEN_EDITOR'; editor: EditorState }\n | { type: 'CLOSE_EDITOR' }\n | { type: 'ADD_ITEM'; item: ReviewItem }\n | { type: 'UPDATE_ITEM'; id: string; patch: Partial<ReviewItem> }\n | { type: 'SET_ITEM_STATUS'; id: string; status: ItemStatus }\n | { type: 'DELETE_ITEM'; id: string }\n | { type: 'REPLACE_SESSION'; session: ReviewSession }\n | { type: 'CLEAR_ITEMS' }\n | { type: 'SET_AUTHOR'; author: string }\n | { type: 'UNDO' }\n | { type: 'SET_PANEL'; open: boolean }\n | { type: 'SET_ACTIVE_ITEM'; id: string | null }\n | { type: 'PUSH_TOAST'; toast: ToastData }\n | { type: 'DISMISS_TOAST'; id: string }\n | { type: 'SET_CONFIRM'; confirm: ConfirmState | null }\n | { type: 'SET_PREVIEW'; on: boolean }\n | { type: 'SET_UNAPPLIED'; count: number }\n | { type: 'SET_CHEATSHEET'; open: boolean }\n | { type: 'SET_EMBLEMA_CONNECT'; open: boolean }\n | { type: 'SET_COACH'; open: boolean }\n | { type: 'SET_CORNER'; corner: BadgeCorner }\n | { type: 'SYNC_STATUS'; status: SyncStatus }\n | { type: 'EMBLEMA_PUSH_STATUS'; status: EmblemaPushStatus }\n | { type: 'SYNC_SNAPSHOT'; items: ReviewItem[] }\n | { type: 'PEERS_SET'; peers: PeerState[] }\n | { type: 'PEER_JOIN'; peer: PeerState }\n | { type: 'PEER_LEAVE'; peerId: string }\n | { type: 'PEER_CURSOR'; peerId: string; cursor: PeerCursor }\n | { type: 'OPEN_QUICK'; quick: QuickComposer }\n | { type: 'CLOSE_QUICK' }\n | { type: 'PEER_SELECTING'; peerId: string; selector: string | null }\n | { type: 'PEER_TYPING'; peerId: string; itemId: string | null; active: boolean }\n | { type: 'REMOTE_ADD'; item: ReviewItem }\n | { type: 'REMOTE_PATCH'; id: string; patch: Record<string, unknown> }\n | { type: 'REMOTE_STATUS'; id: string; status: ItemStatus }\n | { type: 'REMOTE_DELETE'; id: string };\n\nconst UNDO_LIMIT = 50;\n\nexport function createSession(author: string): ReviewSession {\n const now = new Date().toISOString();\n return {\n schemaVersion: SCHEMA_VERSION,\n id: rkId(),\n createdAt: now,\n updatedAt: now,\n site: {\n origin: window.location.origin,\n route: window.location.pathname,\n viewport: { width: window.innerWidth, height: window.innerHeight },\n userAgent: navigator.userAgent,\n },\n author,\n items: [],\n };\n}\n\nfunction touch(session: ReviewSession): ReviewSession {\n return { ...session, updatedAt: new Date().toISOString() };\n}\n\nfunction pushUndo(stack: ReviewItem[][], items: ReviewItem[]): ReviewItem[][] {\n const next = [...stack, items];\n return next.length > UNDO_LIMIT ? next.slice(next.length - UNDO_LIMIT) : next;\n}\n\nexport function reducer(state: State, action: Action): State {\n switch (action.type) {\n case 'INIT_SESSION':\n return { ...state, session: action.session };\n case 'SET_ROUTE':\n return state.route === action.route\n ? state\n : { ...state, route: action.route, selection: null, editor: null, mode: 'idle' };\n case 'SET_MODE':\n return {\n ...state,\n mode: action.mode,\n tool: action.mode === 'pick' ? state.tool : 'select',\n selection: action.mode === 'pick' ? state.selection : null,\n };\n case 'SET_FILTER':\n return { ...state, filter: action.filter };\n // Arming a tool always enters pick mode; the next page click applies it.\n case 'SET_TOOL':\n return { ...state, mode: 'pick', tool: action.tool, selection: null };\n case 'SET_HIDDEN':\n return action.on\n ? {\n ...state,\n hidden: true,\n mode: 'idle',\n tool: 'select',\n selection: null,\n editor: null,\n panelOpen: false,\n confirm: null,\n cheatsheetOpen: false,\n emblemaConnectOpen: false,\n }\n : { ...state, hidden: false };\n case 'SELECT':\n return { ...state, selection: action.selection };\n // Editors need pick listeners off (the inline editor makes the page element\n // contenteditable — capture-phase swallowing would eat caret clicks), so an\n // editor session parks mode at 'idle' and every exit resumes 'pick'.\n // Editors only ever open from pick mode, so the resume is always correct.\n case 'OPEN_EDITOR':\n return { ...state, editor: action.editor, selection: null, mode: 'idle' };\n case 'CLOSE_EDITOR':\n return { ...state, editor: null, mode: 'pick' };\n case 'ADD_ITEM': {\n if (!state.session) return state;\n return {\n ...state,\n undoStack: pushUndo(state.undoStack, state.session.items),\n session: touch({ ...state.session, items: [...state.session.items, action.item] }),\n editor: null,\n mode: 'pick',\n };\n }\n case 'UPDATE_ITEM': {\n if (!state.session) return state;\n return {\n ...state,\n undoStack: pushUndo(state.undoStack, state.session.items),\n session: touch({\n ...state.session,\n items: state.session.items.map((item) =>\n item.id === action.id ? ({ ...item, ...action.patch } as ReviewItem) : item,\n ),\n }),\n };\n }\n case 'SET_ITEM_STATUS': {\n if (!state.session) return state;\n return {\n ...state,\n session: touch({\n ...state.session,\n items: state.session.items.map((item) =>\n item.id === action.id ? { ...item, status: action.status } : item,\n ),\n }),\n };\n }\n case 'DELETE_ITEM': {\n if (!state.session) return state;\n return {\n ...state,\n undoStack: pushUndo(state.undoStack, state.session.items),\n session: touch({\n ...state.session,\n items: state.session.items.filter((item) => item.id !== action.id),\n }),\n activeItemId: state.activeItemId === action.id ? null : state.activeItemId,\n };\n }\n case 'REPLACE_SESSION':\n return {\n ...state,\n undoStack: state.session ? pushUndo(state.undoStack, state.session.items) : state.undoStack,\n session: touch(action.session),\n activeItemId: null,\n };\n case 'CLEAR_ITEMS': {\n if (!state.session) return state;\n return {\n ...state,\n undoStack: pushUndo(state.undoStack, state.session.items),\n session: touch({ ...state.session, items: [] }),\n activeItemId: null,\n };\n }\n case 'SET_AUTHOR': {\n if (!state.session) return state;\n if (state.session.author === action.author) return state;\n return { ...state, session: touch({ ...state.session, author: action.author }) };\n }\n case 'UNDO': {\n if (!state.session || state.undoStack.length === 0) return state;\n const previous = state.undoStack[state.undoStack.length - 1];\n return {\n ...state,\n undoStack: state.undoStack.slice(0, -1),\n session: touch({ ...state.session, items: previous }),\n };\n }\n // Opening the panel leaves pick mode: the reviewer switched to list\n // management, and pick's capture-phase click swallowing must not run\n // under the panel (it would eat e.g. the export download click).\n case 'SET_PANEL':\n return action.open\n ? { ...state, panelOpen: true, mode: 'idle', selection: null }\n : { ...state, panelOpen: false };\n case 'SET_ACTIVE_ITEM':\n return { ...state, activeItemId: action.id };\n case 'PUSH_TOAST':\n return { ...state, toasts: [...state.toasts.slice(-3), action.toast] };\n case 'DISMISS_TOAST':\n return { ...state, toasts: state.toasts.filter((toast) => toast.id !== action.id) };\n case 'SET_CONFIRM':\n return { ...state, confirm: action.confirm };\n case 'SET_PREVIEW':\n return state.preview === action.on ? state : { ...state, preview: action.on };\n case 'SET_UNAPPLIED':\n return state.unapplied === action.count ? state : { ...state, unapplied: action.count };\n case 'SET_CHEATSHEET':\n return { ...state, cheatsheetOpen: action.open };\n case 'SET_EMBLEMA_CONNECT':\n return { ...state, emblemaConnectOpen: action.open };\n case 'SET_COACH':\n return { ...state, coachOpen: action.open };\n case 'SET_CORNER':\n return { ...state, badgeCorner: action.corner };\n case 'SYNC_STATUS':\n return state.syncStatus === action.status ? state : { ...state, syncStatus: action.status };\n case 'EMBLEMA_PUSH_STATUS':\n return state.emblemaPush === action.status ? state : { ...state, emblemaPush: action.status };\n /*\n * Remote mutations (server echoes included) are applied idempotently by\n * item id and never touch the undo stack — instead they invalidate it,\n * so a local undo can never mass-revert another reviewer's work.\n */\n case 'SYNC_SNAPSHOT': {\n if (!state.session) return state;\n const serverIds = new Set(action.items.map((item) => item.id));\n const localOnly = state.session.items.filter((item) => !serverIds.has(item.id));\n const merged = [...action.items, ...localOnly];\n if (JSON.stringify(merged) === JSON.stringify(state.session.items)) return state;\n return { ...state, undoStack: [], session: touch({ ...state.session, items: merged }) };\n }\n case 'REMOTE_ADD': {\n if (!state.session) return state;\n const existing = state.session.items.find((item) => item.id === action.item.id);\n if (existing && JSON.stringify(existing) === JSON.stringify(action.item)) return state;\n const items = existing\n ? state.session.items.map((item) => (item.id === action.item.id ? action.item : item))\n : [...state.session.items, action.item];\n return { ...state, undoStack: [], session: touch({ ...state.session, items }) };\n }\n case 'REMOTE_PATCH': {\n if (!state.session) return state;\n const existing = state.session.items.find((item) => item.id === action.id);\n if (!existing) return state;\n const next = { ...existing, ...action.patch } as ReviewItem;\n if (JSON.stringify(existing) === JSON.stringify(next)) return state;\n return {\n ...state,\n undoStack: [],\n session: touch({\n ...state.session,\n items: state.session.items.map((item) => (item.id === action.id ? next : item)),\n }),\n };\n }\n case 'REMOTE_STATUS': {\n if (!state.session) return state;\n const existing = state.session.items.find((item) => item.id === action.id);\n if (!existing || existing.status === action.status) return state;\n return {\n ...state,\n undoStack: [],\n session: touch({\n ...state.session,\n items: state.session.items.map((item) =>\n item.id === action.id ? { ...item, status: action.status } : item,\n ),\n }),\n };\n }\n case 'REMOTE_DELETE': {\n if (!state.session) return state;\n if (!state.session.items.some((item) => item.id === action.id)) return state;\n return {\n ...state,\n undoStack: [],\n activeItemId: state.activeItemId === action.id ? null : state.activeItemId,\n session: touch({\n ...state.session,\n items: state.session.items.filter((item) => item.id !== action.id),\n }),\n };\n }\n case 'OPEN_QUICK':\n return { ...state, quick: action.quick, selection: null, editor: null };\n case 'CLOSE_QUICK':\n return state.quick === null ? state : { ...state, quick: null };\n case 'PEERS_SET':\n return { ...state, peers: action.peers };\n case 'PEER_JOIN':\n return {\n ...state,\n peers: [...state.peers.filter((peer) => peer.id !== action.peer.id), action.peer],\n };\n case 'PEER_LEAVE':\n return { ...state, peers: state.peers.filter((peer) => peer.id !== action.peerId) };\n case 'PEER_CURSOR':\n return {\n ...state,\n peers: state.peers.map((peer) =>\n peer.id === action.peerId ? { ...peer, cursor: action.cursor } : peer,\n ),\n };\n case 'PEER_SELECTING':\n return {\n ...state,\n peers: state.peers.map((peer) =>\n peer.id === action.peerId ? { ...peer, selecting: action.selector } : peer,\n ),\n };\n case 'PEER_TYPING':\n return {\n ...state,\n peers: state.peers.map((peer) =>\n peer.id === action.peerId\n ? { ...peer, typingItemId: action.itemId, typingActive: action.active }\n : peer,\n ),\n };\n }\n}\n\n/**\n * localStorage key for the persisted Original/Edited view choice. v2: the old\n * key was written on every load (and the toggle once sat on 'V', a prime\n * mis-press), so many reviewers inherited a stuck \"Original\". The new key is\n * written only on a conscious toggle; absent = default \"Edited\".\n */\nexport const PREVIEW_KEY = 'review-kit:preview2';\n\nfunction storedPreview(): boolean {\n try {\n window.localStorage.removeItem('review-kit:preview'); // legacy, auto-written\n return window.localStorage.getItem(PREVIEW_KEY) !== '0';\n } catch {\n return true;\n }\n}\n\nexport function initialState(): State {\n return {\n session: null,\n route: typeof window !== 'undefined' ? window.location.pathname : '/',\n preview: typeof window !== 'undefined' ? storedPreview() : true,\n unapplied: 0,\n badgeCorner: 'bottom-right',\n mode: 'idle',\n tool: 'select',\n hidden: false,\n selection: null,\n editor: null,\n panelOpen: false,\n activeItemId: null,\n toasts: [],\n confirm: null,\n cheatsheetOpen: false,\n emblemaConnectOpen: false,\n coachOpen: false,\n undoStack: [],\n syncStatus: 'disabled',\n emblemaPush: 'idle',\n peers: [],\n quick: null,\n filter: null,\n };\n}\n\nconst StateContext = createContext<State | null>(null);\n/** Exported so the sync bridge in App can re-provide a mirrored dispatch. */\nexport const DispatchContext = createContext<Dispatch<Action> | null>(null);\nconst ConfigContext = createContext<ReviewKitConfig>({});\n\nexport function StoreProvider({ config, children }: { config: ReviewKitConfig; children: ReactNode }) {\n const [state, dispatch] = useReducer(reducer, undefined, initialState);\n const configValue = useMemo(\n () => config,\n // eslint-disable-next-line react-hooks/exhaustive-deps -- config object identity is per-render; depend on its fields\n [config.enabled, config.token, config.devAutoOn, config.syncToken, config.syncUrl, config.defaultAuthor, config.fxAssetsUrl, config.position, config.storageKey, config.onSessionChange, config.emblema],\n );\n return (\n <ConfigContext.Provider value={configValue}>\n <StateContext.Provider value={state}>\n <DispatchContext.Provider value={dispatch}>{children}</DispatchContext.Provider>\n </StateContext.Provider>\n </ConfigContext.Provider>\n );\n}\n\nexport function useStore(): State {\n const state = useContext(StateContext);\n if (!state) throw new Error('review-kit: useStore outside provider');\n return state;\n}\n\nexport function useDispatch(): Dispatch<Action> {\n const dispatch = useContext(DispatchContext);\n if (!dispatch) throw new Error('review-kit: useDispatch outside provider');\n return dispatch;\n}\n\nexport function useConfig(): ReviewKitConfig {\n return useContext(ConfigContext);\n}\n\n/** The reviewer's conscious Original/Edited choice: persist + apply. */\nexport function choosePreview(dispatch: Dispatch<Action>, on: boolean): void {\n try {\n window.localStorage.setItem(PREVIEW_KEY, on ? '1' : '0');\n } catch {\n /* ignore */\n }\n dispatch({ type: 'SET_PREVIEW', on });\n}\n\n/** Convenience: push a toast with a generated id. */\nexport function toast(dispatch: Dispatch<Action>, message: string, tone: ToastTone = 'info'): void {\n dispatch({ type: 'PUSH_TOAST', toast: { id: rkId(), message, tone } });\n}\n","/** Session persistence: IndexedDB with a localStorage fallback. */\n\nimport type { ReviewSession } from '../schema';\nimport { parseSessionJson, parseSession } from '../schema';\n\nconst DB_NAME = 'review-kit';\nconst STORE = 'sessions';\nconst LS_PREFIX = 'review-kit:session:';\n\nexport function defaultStorageKey(): string {\n const origin = typeof window !== 'undefined' ? window.location.origin : 'unknown';\n return origin;\n}\n\nfunction openDb(): Promise<IDBDatabase | null> {\n return new Promise((resolve) => {\n if (typeof indexedDB === 'undefined') {\n resolve(null);\n return;\n }\n try {\n const request = indexedDB.open(DB_NAME, 1);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE)) db.createObjectStore(STORE);\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => resolve(null);\n request.onblocked = () => resolve(null);\n } catch {\n resolve(null);\n }\n });\n}\n\nfunction idbGet(db: IDBDatabase, key: string): Promise<unknown> {\n return new Promise((resolve) => {\n try {\n const tx = db.transaction(STORE, 'readonly');\n const request = tx.objectStore(STORE).get(key);\n request.onsuccess = () => resolve(request.result as unknown);\n request.onerror = () => resolve(undefined);\n } catch {\n resolve(undefined);\n }\n });\n}\n\nfunction idbSet(db: IDBDatabase, key: string, value: unknown): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).put(value, key);\n tx.oncomplete = () => resolve(true);\n tx.onerror = () => resolve(false);\n tx.onabort = () => resolve(false);\n } catch {\n resolve(false);\n }\n });\n}\n\nfunction idbDelete(db: IDBDatabase, key: string): Promise<boolean> {\n return new Promise((resolve) => {\n try {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).delete(key);\n tx.oncomplete = () => resolve(true);\n tx.onerror = () => resolve(false);\n tx.onabort = () => resolve(false);\n } catch {\n resolve(false);\n }\n });\n}\n\nexport async function loadSession(key: string): Promise<ReviewSession | null> {\n const db = await openDb();\n if (db) {\n const raw = await idbGet(db, key);\n db.close();\n if (raw !== undefined && raw !== null) {\n const parsed = parseSession(raw);\n if (parsed.ok) return parsed.session;\n }\n }\n try {\n const raw = window.localStorage.getItem(LS_PREFIX + key);\n if (raw !== null) {\n const parsed = parseSessionJson(raw);\n if (parsed.ok) return parsed.session;\n }\n } catch {\n /* localStorage unavailable */\n }\n return null;\n}\n\nexport async function saveSession(key: string, session: ReviewSession): Promise<void> {\n // Structured-clone-safe: sessions are plain JSON data.\n const db = await openDb();\n if (db) {\n const ok = await idbSet(db, key, session);\n db.close();\n if (ok) return;\n }\n try {\n window.localStorage.setItem(LS_PREFIX + key, JSON.stringify(session));\n } catch {\n /* both stores failed (quota / private mode) — session lives in memory only */\n }\n}\n\nexport async function deleteSavedSession(key: string): Promise<void> {\n const db = await openDb();\n if (db) {\n await idbDelete(db, key);\n db.close();\n }\n try {\n window.localStorage.removeItem(LS_PREFIX + key);\n } catch {\n /* ignore */\n }\n}\n","/**\n * Reveal a hidden review target: when an item's element exists but sits in a\n * closed container (accordion, tab, collapsed menu), try to find and click\n * the control that opens it — up to a few steps. Non-destructive by design:\n * we only ever OPEN things through the page's own affordances (`<details>`,\n * `aria-expanded`/`aria-controls`, tabs); if nothing works we report failure\n * and touch nothing else. Unmounted content (e.g. React modals that render\n * nothing while closed) cannot be resolved, so it fails calmly too.\n */\n\nimport type { ReviewTarget } from '../schema';\nimport { isElementVisible, resolveTarget } from './target';\n\nconst wait = (ms: number) => new Promise<void>((resolve) => window.setTimeout(resolve, ms));\n\n/** One opening attempt for the nearest closed boundary above `el`. */\nfunction tryOpenStep(el: Element): boolean {\n // 1. <details> ancestors — open them directly.\n const details = el.closest('details:not([open])');\n if (details) {\n (details as HTMLDetailsElement).open = true;\n return true;\n }\n // 2. A collapsed controller pointing at a container of el\n // (aria-expanded=false + aria-controls covers menus, accordions, tabs).\n const controllers = document.querySelectorAll<HTMLElement>('[aria-expanded=\"false\"][aria-controls]');\n for (const controller of controllers) {\n const ids = (controller.getAttribute('aria-controls') ?? '').split(/\\s+/).filter(Boolean);\n for (const id of ids) {\n const controlled = document.getElementById(id);\n if (controlled && (controlled === el || controlled.contains(el))) {\n controller.click();\n return true;\n }\n }\n }\n // 3. An unselected tab whose panel contains el.\n const panel = el.closest('[role=\"tabpanel\"]');\n if (panel && panel.id) {\n const tab = document.querySelector<HTMLElement>(`[role=\"tab\"][aria-controls=\"${panel.id}\"][aria-selected=\"false\"]`);\n if (tab) {\n tab.click();\n return true;\n }\n }\n // 4. A hidden ancestor with the `hidden` attribute controlled by nothing we\n // can find — nothing safe to click.\n return false;\n}\n\nexport type RevealResult = 'visible' | 'revealed' | 'failed';\n\n/** Try to make the target visible; resolves with what happened. */\nexport async function revealTarget(target: ReviewTarget): Promise<RevealResult> {\n for (let step = 0; step < 3; step++) {\n const el = resolveTarget(target)?.element ?? null;\n if (!el) return 'failed';\n if (isElementVisible(el)) return step === 0 ? 'visible' : 'revealed';\n if (!tryOpenStep(el)) return 'failed';\n await wait(120); // give the page's own transition/render a beat\n }\n const el = resolveTarget(target)?.element ?? null;\n return el && isElementVisible(el) ? 'revealed' : 'failed';\n}\n","/**\n * Applied preview — mirrors saved copy/image changes into the live page DOM\n * so the reviewer sees the site as it would look after the changes land.\n *\n * Strictly a client-side, in-memory view: it only ever runs inside an active\n * (token-gated) review session, keeps the pristine original of every touched\n * element (full innerHTML / img src+srcset+sizes) and can restore it exactly.\n *\n * Host React apps may re-render and wipe applied changes at any time. A\n * MutationObserver (childList + characterData + src/srcset attributes only —\n * class/style churn from page animations is deliberately ignored) schedules a\n * throttled re-apply. Loops are prevented twice over: observer records from\n * our own writes are flushed away while an `applying` flag is up, and a pass\n * only writes when the DOM actually differs from the wanted state, so a\n * steady state produces no mutations at all.\n */\n\nimport { useEffect, useRef } from 'react';\nimport type { Dispatch } from 'react';\nimport { isCopyItem, isImageItem } from '../schema';\nimport type { Action, State } from './store';\nimport { findImage, isPluginElement, resolveTarget } from './target';\n\nconst EDITED_ATTR = 'data-rk-edited';\nconst STYLE_ID = 'rk-preview-style';\nconst RESCHEDULE_MS = 180;\n\n/* Quiet \"this is a proposal\" marking, injected into the host document only\n while the edited view is on (shadow styles can't reach host elements). */\nconst HOST_CSS = `[${EDITED_ATTR}=\"copy\"] {\n text-decoration-line: underline;\n text-decoration-style: dotted;\n text-decoration-color: rgba(125, 140, 250, 0.55);\n text-decoration-thickness: 1px;\n text-underline-offset: 3px;\n}\nimg[${EDITED_ATTR}=\"image\"] {\n outline: 1.5px dashed rgba(125, 140, 250, 0.45);\n outline-offset: 2px;\n}`;\n\ninterface Original {\n html?: string;\n imgSrc?: string | null;\n imgSrcset?: string | null;\n imgSizes?: string | null;\n hasImgAttrs?: boolean;\n}\n\n/**\n * Replace an element's visible text while preserving its non-text structure\n * (icons, images, nested wrappers keep their place — only text changes, so\n * CSS keeps styling exactly the same DOM shape). The new text goes into the\n * first substantial text node; remaining text nodes are emptied. Pure-text\n * elements use innerText (keeps multiline rendering via <br>).\n */\nexport function setElementText(el: HTMLElement, text: string): void {\n if (el.children.length === 0) {\n if (el.innerText !== text) el.innerText = text;\n return;\n }\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n const textNodes: Text[] = [];\n let node: Node | null;\n while ((node = walker.nextNode())) {\n if ((node.textContent ?? '').trim() !== '') textNodes.push(node as Text);\n }\n if (textNodes.length === 0) {\n el.appendChild(document.createTextNode(text));\n return;\n }\n if (textNodes[0].textContent !== text) textNodes[0].textContent = text;\n for (let i = 1; i < textNodes.length; i++) {\n if (textNodes[i].textContent !== '') textNodes[i].textContent = '';\n }\n}\n\nfunction setOrRemove(el: Element, attr: string, value: string | null): void {\n if (value === null) el.removeAttribute(attr);\n else el.setAttribute(attr, value);\n}\n\nfunction restore(el: Element, original: Original): void {\n if (original.html !== undefined) el.innerHTML = original.html;\n if (original.hasImgAttrs) {\n setOrRemove(el, 'src', original.imgSrc ?? null);\n setOrRemove(el, 'srcset', original.imgSrcset ?? null);\n setOrRemove(el, 'sizes', original.imgSizes ?? null);\n }\n el.removeAttribute(EDITED_ATTR);\n}\n\n/** Module-level handle so the toolbar can hand a pristine element to an\n * editor synchronously, before the editor mounts and reads its content. */\nlet activeController: { revertFor(el: Element): void } | null = null;\n\nexport function revertElementPreview(el: Element): void {\n activeController?.revertFor(el);\n}\n\nexport function useAppliedPreview(state: State, dispatch: Dispatch<Action>): void {\n const originals = useRef(new Map<Element, Original>());\n const applying = useRef(false);\n const timer = useRef<number | null>(null);\n const observerRef = useRef<MutationObserver | null>(null);\n const stateRef = useRef(state);\n stateRef.current = state;\n const lastUnapplied = useRef(0);\n\n const guarded = useRef((write: () => void) => {\n applying.current = true;\n try {\n write();\n } finally {\n observerRef.current?.takeRecords();\n applying.current = false;\n }\n });\n\n const runPass = useRef(() => {\n /* replaced below */\n });\n runPass.current = () => {\n const { session, route, preview, editor, hidden } = stateRef.current;\n if (!session || editor) return; // suspended while an editor owns an element\n const showEdited = preview && !hidden;\n\n const map = originals.current;\n for (const el of [...map.keys()]) if (!el.isConnected) map.delete(el);\n\n // Wanted end state per element; later items win over earlier ones.\n const wanted = new Map<Element, { text?: string; imgSrc?: string }>();\n let unapplied = 0;\n if (showEdited) {\n for (const item of session.items) {\n if (item.route !== route) continue;\n if (isCopyItem(item)) {\n const resolved = resolveTarget(item.target);\n if (!resolved) {\n unapplied++;\n continue;\n }\n wanted.set(resolved.element, { ...wanted.get(resolved.element), text: item.payload.after });\n } else if (isImageItem(item)) {\n const src = item.payload.afterDataUrl ?? item.payload.afterSrc;\n if (src === undefined) continue;\n const resolved = resolveTarget(item.target);\n const img = resolved ? findImage(resolved.element) : null;\n if (!img) {\n unapplied++;\n continue;\n }\n wanted.set(img, { ...wanted.get(img), imgSrc: src });\n }\n }\n }\n\n guarded.current(() => {\n for (const [el, original] of [...map.entries()]) {\n if (!wanted.has(el)) {\n restore(el, original);\n map.delete(el);\n }\n }\n for (const [el, want] of wanted) {\n let original = map.get(el);\n if (want.text !== undefined && el instanceof HTMLElement) {\n if (el.innerText !== want.text) {\n if (original?.html === undefined) {\n original = { ...original, html: el.innerHTML };\n map.set(el, original);\n }\n setElementText(el, want.text);\n el.setAttribute(EDITED_ATTR, 'copy');\n }\n }\n if (want.imgSrc !== undefined && el instanceof HTMLImageElement) {\n if (el.getAttribute('src') !== want.imgSrc || el.getAttribute(EDITED_ATTR) !== 'image') {\n if (!original?.hasImgAttrs) {\n original = {\n ...original,\n hasImgAttrs: true,\n imgSrc: el.getAttribute('src'),\n imgSrcset: el.getAttribute('srcset'),\n imgSizes: el.getAttribute('sizes'),\n };\n map.set(el, original);\n }\n el.removeAttribute('srcset');\n el.removeAttribute('sizes');\n el.setAttribute('src', want.imgSrc);\n el.setAttribute(EDITED_ATTR, 'image');\n }\n }\n }\n });\n\n if (unapplied !== lastUnapplied.current) {\n lastUnapplied.current = unapplied;\n dispatch({ type: 'SET_UNAPPLIED', count: unapplied });\n }\n };\n\n const schedule = useRef(() => {\n if (timer.current !== null) return;\n timer.current = window.setTimeout(() => {\n timer.current = null;\n runPass.current();\n }, RESCHEDULE_MS);\n });\n\n // Watch for the host app re-rendering over our applied changes.\n useEffect(() => {\n const observer = new MutationObserver((records) => {\n if (applying.current) return;\n if (records.every((record) => isPluginElement(record.target))) return;\n schedule.current();\n });\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: ['src', 'srcset'],\n });\n observerRef.current = observer;\n return () => {\n observer.disconnect();\n observerRef.current = null;\n };\n }, []);\n\n // Give editors a pristine element to read, synchronously via the toolbar.\n useEffect(() => {\n const controller = {\n revertFor(el: Element) {\n const map = originals.current;\n guarded.current(() => {\n for (const [key, original] of [...map.entries()]) {\n if (key === el || el.contains(key)) {\n restore(key, original);\n map.delete(key);\n }\n }\n });\n },\n };\n activeController = controller;\n return () => {\n if (activeController === controller) activeController = null;\n };\n }, []);\n\n // Re-apply on any relevant state change (item edits, toggle, editor close).\n const { session, preview, route, editor, hidden } = state;\n useEffect(() => {\n runPass.current();\n }, [session, preview, route, editor, hidden]);\n\n // The subtle \"edited\" marking exists only while the edited view is on.\n useEffect(() => {\n if (!preview || hidden) return;\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.textContent = HOST_CSS;\n document.head.appendChild(style);\n return () => style.remove();\n }, [preview, hidden]);\n\n // Full cleanup: leave the page exactly as we found it.\n useEffect(() => {\n const map = originals.current;\n const pendingTimer = timer;\n const applyingFlag = applying;\n return () => {\n if (pendingTimer.current !== null) window.clearTimeout(pendingTimer.current);\n applyingFlag.current = true;\n for (const [el, original] of map.entries()) {\n if (el.isConnected) restore(el, original);\n }\n map.clear();\n applyingFlag.current = false;\n };\n }, []);\n}\n","/**\n * Names of the `/` command effects — the only part of the effects module the\n * main chunk needs. The implementations (~40 KB of source) live in\n * `effects.ts` and load on demand the first time an effect actually runs;\n * `effects.ts` is typed against this list, so adding an effect without\n * registering its name here fails the build.\n */\n\nexport const EFFECT_NAMES = [\n 'ondro',\n 'lava',\n 'sklo',\n 'vir',\n 'crt',\n 'hovno',\n 'konfety',\n 'srdiecka',\n 'sneh',\n 'zemetrasenie',\n '69',\n 'kokot',\n 'vrtule',\n 'muchy',\n 'pes',\n 'pivo',\n 'nikotin',\n 'matrix',\n 'disko',\n 'zrkadlo',\n 'pohreb',\n 'laser',\n 'kura',\n 'spam',\n] as const;\n\nexport type EffectName = (typeof EFFECT_NAMES)[number];\n\nconst NAME_SET: ReadonlySet<string> = new Set<string>(EFFECT_NAMES);\n\n/** Known effect name, or the room-wide `stop` kill switch. */\nexport function isEffectCommand(name: string): boolean {\n return name === 'stop' || NAME_SET.has(name);\n}\n","/**\n * `/` command effects — short, purely visual room-wide fun. An effect never\n * touches page content, never stores anything (locally or on the server; the\n * transport broadcasts it as an ephemeral `fx` frame) and cleans up after\n * itself completely: injected styles, DOM nodes, timers, listeners and audio\n * all go away, leaving the page byte-identical. Escape cancels everything;\n * typing the kill word (\"hovno\") cancels for the whole room.\n *\n * Adding an effect = one entry in EFFECTS: either a particle spec, or a\n * `custom` entry whose start() returns its own cleanup.\n *\n * Photosensitivity: color/transform cycles stay slow (≥2 s per cycle, well\n * under 3 Hz), no high-contrast strobing; prefers-reduced-motion gets a far\n * tamer variant (hue drift only, fewer particles, no rotation/pulse).\n */\n\nimport type { EffectName } from './effectCatalog';\n\n/**\n * Where effect sounds live. Default: the ReviewKit assets host (nginx on the\n * satanwagen VPS, TLS via a sslip.io hostname so no domain can expire under\n * it; see realtime/README.md \"Assets host\"). `ReviewKitConfig.fxAssetsUrl`\n * overrides it. Expected files under the base: `rick.mp3` (/ondro).\n */\nexport const DEFAULT_FX_ASSETS_URL = 'https://2-59-219-26.sslip.io/rk-assets';\nlet fxAssetsUrl: string = DEFAULT_FX_ASSETS_URL;\nexport function setFxAssetsUrl(url: string | null): void {\n fxAssetsUrl = url && url !== '' ? url.replace(/\\/+$/, '') : DEFAULT_FX_ASSETS_URL;\n}\n\n/** /ondro runtime — the single knob for how long the madness lasts. */\nconst ONDRO_MS = 120_000;\n/** Every other page-wrecker (\"big\") effect runs this long. */\nconst BIG_MS = 45_000;\nconst NICE_MS = 6_900; // the user likes this number\n\n/** Page content minus the review layer and effect plumbing. */\nconst CHAOS_SEL = 'body > :not([data-review-kit-host]):not(script):not(style):not(svg[data-rk-fx])';\n\ninterface ParticleSpec {\n kind: 'rain' | 'burst';\n glyphs: string[];\n count: number;\n durationMs: number;\n shake?: boolean;\n className?: string;\n}\n\ninterface CustomSpec {\n kind: 'custom';\n durationMs: number;\n start(ctx: { layer: HTMLElement; reduced: boolean }): () => void;\n}\n\ntype EffectSpec = ParticleSpec | CustomSpec;\n\n/** Broadcast hook, injected by the sync layer (avoids an import cycle). */\nlet broadcast: ((name: string) => void) | null = null;\nexport function setEffectBroadcaster(fn: ((name: string) => void) | null): void {\n broadcast = fn;\n}\n\nconst active = new Set<() => void>();\n\n/** Cancel everything currently running (wired into the Esc cascade). */\nexport function cancelEffects(): boolean {\n if (active.size === 0) return false;\n for (const cancel of [...active]) cancel();\n return true;\n}\n\nfunction reducedMotion(): boolean {\n try {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n } catch {\n return false;\n }\n}\n\n/* ---------------- particle engine ---------------- */\n\nfunction spawnParticles(layer: HTMLElement, spec: ParticleSpec, reduced: boolean, duration: number): void {\n const count = reduced ? Math.min(10, spec.count) : spec.count;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n for (let i = 0; i < count; i++) {\n const particle = document.createElement('span');\n particle.className = spec.className ? `rk-fx-particle ${spec.className}` : 'rk-fx-particle';\n particle.textContent = spec.glyphs[i % spec.glyphs.length];\n const delay = (i / count) * duration * 0.4;\n const life = duration * (0.45 + (0.35 * ((i * 7) % 10)) / 10);\n particle.style.fontSize = `${14 + ((i * 13) % 18)}px`;\n if (spec.kind === 'rain') {\n const x = (((i * 61) % 100) / 100) * vw;\n const sway = (((i * 31) % 60) - 30) | 0;\n particle.style.setProperty('--fx-x0', `${x}px`);\n particle.style.setProperty('--fx-x1', `${x + sway}px`);\n particle.style.setProperty('--fx-y0', `-40px`);\n particle.style.setProperty('--fx-y1', `${vh + 40}px`);\n } else {\n const angle = (i / count) * Math.PI * 2;\n const radius = 120 + ((i * 47) % 240);\n particle.style.setProperty('--fx-x0', `${vw / 2}px`);\n particle.style.setProperty('--fx-y0', `${vh / 2}px`);\n particle.style.setProperty('--fx-x1', `${vw / 2 + Math.cos(angle) * radius}px`);\n particle.style.setProperty('--fx-y1', `${vh / 2 + Math.sin(angle) * radius + vh * 0.4}px`);\n }\n particle.style.animation = `rk-fx-fall ${reduced ? life * 0.8 : life}ms linear ${delay}ms both`;\n layer.appendChild(particle);\n }\n}\n\nfunction runShake(): () => void {\n const prev = document.body.style.animation;\n let styleTag = document.getElementById('rk-fx-shake-style');\n if (!styleTag) {\n styleTag = document.createElement('style');\n styleTag.id = 'rk-fx-shake-style';\n styleTag.textContent =\n '@keyframes rk-fx-shake { 0%,100% { transform: translate(0,0); } 25% { transform: translate(-5px,3px); } 50% { transform: translate(4px,-4px); } 75% { transform: translate(-3px,-2px); } }';\n document.head.appendChild(styleTag);\n }\n document.body.style.animation = 'rk-fx-shake 260ms ease-in-out 6';\n let done = false;\n const restore = () => {\n if (done) return;\n done = true;\n document.body.style.animation = prev;\n if (document.body.getAttribute('style') === '') document.body.removeAttribute('style');\n };\n window.setTimeout(restore, 1700);\n return restore;\n}\n\n/* ---------------- custom effects ---------------- */\n\n/** /ondro — 20 s of the page tearing itself apart, in three escalating\n * phases, for everyone in the room. All the violence lives in blur,\n * warp/displacement, hue, glitch bands, shake and particles — luminance\n * flips stay slow (a single eased invert wave per 4 s cycle, ≈0.25 Hz) and\n * there is no full-field strobing. The review layer stays untouched and\n * operable. */\nfunction startOndro({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const cleanups: Array<() => void> = [];\n const timers: number[] = [];\n const intervals: number[] = [];\n const later = (fn: () => void, ms: number) => timers.push(window.setTimeout(fn, ms));\n const every = (fn: () => void, ms: number) => intervals.push(window.setInterval(fn, ms));\n cleanups.push(() => {\n timers.forEach((t) => window.clearTimeout(t));\n intervals.forEach((t) => window.clearInterval(t));\n });\n\n const addStyle = (css: string) => {\n const style = document.createElement('style');\n style.setAttribute('data-rk-fx', 'ondro');\n style.textContent = css;\n document.head.appendChild(style);\n cleanups.push(() => style.remove());\n return style;\n };\n\n /** Particles in a disposable sub-layer so 2 minutes of waves can't pile up. */\n const wave = (spec: ParticleSpec) => {\n const sub = document.createElement('div');\n sub.className = 'rk-fx-layer';\n layer.appendChild(sub);\n spawnParticles(sub, spec, reduced, spec.durationMs);\n const t = window.setTimeout(() => sub.remove(), spec.durationMs + 1600);\n timers.push(t);\n cleanups.push(() => sub.remove());\n };\n\n if (reduced) {\n addStyle(`@keyframes rk-ondro { 0% { filter: none; } 50% { filter: hue-rotate(40deg) saturate(1.15); } 100% { filter: none; } }\n${CHAOS_SEL} { animation: rk-ondro 8s ease-in-out infinite; }`);\n wave({ kind: 'rain', glyphs: ['🤪', '💥', '🌀'], count: 8, durationMs: 8000 });\n every(() => wave({ kind: 'rain', glyphs: ['🤪', '🌀'], count: 6, durationMs: 8000 }), 15000);\n } else {\n // Freeze scrolling: the base zoom would otherwise grow scrollbars and let\n // the reviewer drift out of the stabilized focus point. Restored exactly.\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n const htmlOverflow = document.documentElement.style.overflow;\n document.documentElement.style.overflow = 'hidden';\n cleanups.push(() => {\n document.documentElement.style.overflow = htmlOverflow;\n if (document.documentElement.getAttribute('style') === '') document.documentElement.removeAttribute('style');\n window.scrollTo(scrollX, scrollY);\n });\n\n // Base zoom ~1.22 baked into every keyframe: rotation/tilt never reveals\n // the viewport edge (verified at max deflection on 1440/768/375). The\n // transform sits on body's CHILDREN (never on <body>): the review layer\n // host is a body child too and must stay crisp and in place. Page-fixed\n // elements (header, cookie bar) live inside #root, so they simply zoom\n // with the content. transform-origin is pinned to the frozen viewport\n // center so the zoom looks at what the reviewer was looking at.\n const originY = scrollY + window.innerHeight / 2;\n addStyle(`${CHAOS_SEL} { transform-origin: 50vw ${originY}px; }`);\n\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('data-rk-fx', 'ondro');\n svg.setAttribute('width', '0');\n svg.setAttribute('height', '0');\n svg.style.position = 'absolute';\n svg.innerHTML = `<defs>\n <filter id=\"rk-ondro-warp\" x=\"-10%\" y=\"-10%\" width=\"120%\" height=\"120%\">\n <feTurbulence type=\"turbulence\" baseFrequency=\"0.004 0.017\" numOctaves=\"2\" result=\"n\" seed=\"7\">\n <animate attributeName=\"baseFrequency\" dur=\"5.2s\" values=\"0.004 0.017;0.013 0.005;0.004 0.017\" repeatCount=\"indefinite\"/>\n </feTurbulence>\n <feDisplacementMap in=\"SourceGraphic\" in2=\"n\" scale=\"14\" xChannelSelector=\"R\" yChannelSelector=\"G\">\n <animate attributeName=\"scale\" dur=\"4.4s\" values=\"6;26;6\" repeatCount=\"indefinite\"/>\n </feDisplacementMap>\n </filter>\n <filter id=\"rk-ondro-ca\" x=\"-5%\" y=\"-5%\" width=\"110%\" height=\"110%\">\n <feColorMatrix in=\"SourceGraphic\" type=\"matrix\" values=\"1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"r\"/>\n <feColorMatrix in=\"SourceGraphic\" type=\"matrix\" values=\"0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"g\"/>\n <feColorMatrix in=\"SourceGraphic\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0\" result=\"b\"/>\n <feOffset in=\"r\" dx=\"4\" dy=\"0\" result=\"ro\"><animate attributeName=\"dx\" dur=\"2.9s\" values=\"1;6;1\" repeatCount=\"indefinite\"/></feOffset>\n <feOffset in=\"b\" dx=\"-4\" dy=\"1\" result=\"bo\"><animate attributeName=\"dx\" dur=\"3.3s\" values=\"-1;-6;-1\" repeatCount=\"indefinite\"/></feOffset>\n <feBlend in=\"ro\" in2=\"g\" mode=\"screen\" result=\"rg\"/>\n <feBlend in=\"rg\" in2=\"bo\" mode=\"screen\"/>\n </filter>\n </defs>`;\n document.body.appendChild(svg);\n cleanups.push(() => svg.remove());\n\n // Phase 1 (0–6 s): the page starts feeling wrong (already zoomed in).\n addStyle(`@keyframes rk-ondro1 {\n 0% { filter: none; transform: scale(1.22); }\n 25% { filter: hue-rotate(120deg) saturate(1.9) blur(1.6px); transform: scale(1.238) rotate(1.4deg) translateX(6px); }\n 50% { filter: hue-rotate(230deg) saturate(0.6) contrast(1.12) blur(0.6px); transform: scale(1.202) rotate(-1.2deg) translateY(5px); }\n 75% { filter: hue-rotate(310deg) saturate(2.1) blur(2.6px); transform: scale(1.22) skewX(1.1deg) translateX(-7px); }\n 100% { filter: hue-rotate(360deg); transform: scale(1.22); }\n}\n${CHAOS_SEL} { animation: rk-ondro1 2.6s ease-in-out infinite; }`);\n\n // Phase 2 (6–13 s): melting + chromatic aberration + typography decay.\n later(() => {\n addStyle(`@keyframes rk-ondro2 {\n 0% { filter: url(#rk-ondro-warp) hue-rotate(0deg) saturate(1.3); transform: scale(1.22); }\n 20% { filter: url(#rk-ondro-ca) hue-rotate(100deg) saturate(2.3) blur(3.4px); transform: scale(1.256) rotate(2.4deg) translate(12px, -6px); }\n 45% { filter: url(#rk-ondro-warp) hue-rotate(190deg) saturate(0.45) contrast(1.2) blur(1.4px); transform: scale(1.19) rotate(-2.2deg) translate(-13px, 8px) skewY(1.2deg); }\n 70% { filter: url(#rk-ondro-ca) hue-rotate(280deg) saturate(2.4) blur(4.6px); transform: scale(1.244) skewX(-1.8deg) translateY(-10px); }\n 100% { filter: url(#rk-ondro-warp) hue-rotate(360deg) saturate(1.3); transform: scale(1.22); }\n}\n${CHAOS_SEL} { animation: rk-ondro2 2.2s ease-in-out infinite; }\n@keyframes rk-ondro-shake { 0%,100% { transform: translate(0,0); } 20% { transform: translate(-6px,4px); } 40% { transform: translate(5px,-5px); } 60% { transform: translate(-4px,-3px); } 80% { transform: translate(6px,3px); } }\n@keyframes rk-ondro-text {\n 0%,100% { letter-spacing: normal; word-spacing: normal; text-shadow: none; }\n 30% { letter-spacing: 0.12em; word-spacing: 0.3em; text-shadow: 4px 0 rgba(255,0,90,0.6), -4px 1px rgba(0,190,255,0.6); }\n 60% { letter-spacing: -0.05em; word-spacing: -0.1em; text-shadow: -6px 0 rgba(255,0,90,0.55), 6px 2px rgba(0,190,255,0.55), 0 3px rgba(120,255,0,0.4); }\n 80% { letter-spacing: 0.2em; text-shadow: 2px -2px rgba(255,0,90,0.65), -2px 2px rgba(0,190,255,0.65); }\n}\nh1, h2, h3, h4, p, a, li, button, span { animation: rk-ondro-text 3.1s ease-in-out infinite; }`);\n startTextDecay(cleanups, every);\n spawnGlitchBands(layer, cleanups);\n wave({ kind: 'burst', glyphs: ['💥', '🧨', '🔥', '🌀'], count: 34, durationMs: 5000 });\n }, 6000);\n\n // Phase 3 (13 s → end): total collapse. One slow EASED invert wave per\n // 4 s cycle (≈0.25 Hz — far under the 3 Hz flash limit).\n later(() => {\n addStyle(`@keyframes rk-ondro3 {\n 0% { filter: url(#rk-ondro-warp) hue-rotate(0deg) saturate(1.6) invert(0); transform: scale(1.22); }\n 18% { filter: url(#rk-ondro-ca) hue-rotate(140deg) saturate(2.5) blur(6px) invert(0.35); transform: scale(1.27) rotate(3.2deg) translate(20px, -12px); }\n 38% { filter: url(#rk-ondro-warp) hue-rotate(220deg) saturate(0.4) blur(2px) invert(0.75); transform: scale(1.18) rotate(-3deg) translate(-22px, 12px) skewY(2deg); }\n 58% { filter: url(#rk-ondro-ca) hue-rotate(300deg) saturate(2.2) blur(7px) invert(0.3); transform: scale(1.25) skewX(2.4deg) translateY(-16px); }\n 80% { filter: url(#rk-ondro-warp) hue-rotate(340deg) saturate(1.8) blur(3px) invert(0.05); transform: scale(1.23) rotate(1.6deg) translate(14px, 6px); }\n 100% { filter: url(#rk-ondro-warp) hue-rotate(360deg) saturate(1.6) invert(0); transform: scale(1.22); }\n}\n${CHAOS_SEL} { animation: rk-ondro3 4s ease-in-out infinite; }\n@keyframes rk-ondro-shake3 { 0%,100% { transform: translate(0,0) rotate(0); } 25% { transform: translate(-9px,6px) rotate(-0.4deg); } 50% { transform: translate(8px,-8px) rotate(0.5deg); } 75% { transform: translate(-7px,-5px) rotate(-0.3deg); } }\nbody { animation: rk-ondro-shake3 620ms ease-in-out infinite; }`);\n wave({ kind: 'rain', glyphs: ['🤯', '💀', '🧠', '⚡️', '🫠', '🔩'], count: 60, durationMs: 7000 });\n }, 13000);\n\n // Rolling debris + falling letters for the whole 2 minutes, in bounded\n // disposable waves (nothing accumulates).\n wave({ kind: 'rain', glyphs: ['🤪', '💥', '🌀', '🧠', '⚡️'], count: 40, durationMs: 12000 });\n every(() => wave({ kind: 'rain', glyphs: ['🤪', '💥', '🌀', '🧠', '⚡️', '🍕', '📀'], count: 30, durationMs: 9000 }), 9500);\n every(() => spawnFallingLetters(layer), 12000);\n later(() => spawnFallingLetters(layer), 7000);\n }\n\n // Sound — long effect, loop the track; fully stopped on cleanup.\n {\n const audio = new Audio(`${fxAssetsUrl}/rick.mp3`);\n audio.volume = 0.8;\n audio.loop = true;\n cleanups.push(() => {\n audio.pause();\n audio.src = '';\n });\n audio.play().catch(() => {\n const chip = document.createElement('button');\n chip.className = 'rk-fx-sound';\n chip.type = 'button';\n chip.textContent = '🔊 klikni pre zvuk';\n chip.addEventListener('click', () => {\n audio.play().catch(() => undefined);\n chip.remove();\n });\n layer.appendChild(chip);\n cleanups.push(() => chip.remove());\n });\n }\n\n installKillWord(cleanups);\n\n return () => {\n for (const fn of cleanups) fn();\n };\n}\n\n/** Kill word: typing \"hovno\" anywhere ends the effect for the whole room.\n * While chaos runs, bare kill letters are swallowed so they can't trigger\n * global shortcuts (H would hide the layer mid-panic); typing into real\n * text fields keeps working untouched. */\nfunction installKillWord(cleanups: Array<() => void>): void {\n let buffer = '';\n const inTextField = (event: KeyboardEvent) =>\n event\n .composedPath()\n .some(\n (node) =>\n node instanceof HTMLElement &&\n (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA' || node.isContentEditable),\n );\n const KILL_LETTERS = new Set(['h', 'o', 'v', 'n']);\n const onKey = (event: KeyboardEvent) => {\n if (event.key.length !== 1 || event.metaKey || event.ctrlKey || event.altKey) return;\n const key = event.key.toLowerCase();\n buffer = (buffer + key).slice(-8);\n if (KILL_LETTERS.has(key) && !inTextField(event)) event.stopPropagation();\n if (buffer.includes('hovno')) {\n buffer = '';\n broadcast?.('stop');\n cancelEffects();\n }\n };\n document.addEventListener('keydown', onKey, true);\n cleanups.push(() => document.removeEventListener('keydown', onKey, true));\n}\n\n/** Shared scaffolding for the /ondro-caliber page wreckers: timers, style\n * injection, particle waves, frozen scroll + a transform-origin pinned to\n * the viewport center the reviewer was looking at, text decay and the kill\n * word. Each effect only writes its own choreography. */\ninterface BigFxCtx {\n layer: HTMLElement;\n reduced: boolean;\n addStyle(css: string): void;\n later(fn: () => void, ms: number): void;\n every(fn: () => void, ms: number): void;\n wave(spec: ParticleSpec): void;\n decayText(): void;\n cleanups: Array<() => void>;\n}\nfunction bigEffect(build: (ctx: BigFxCtx) => void) {\n return function start({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const cleanups: Array<() => void> = [];\n const timers: number[] = [];\n const intervals: number[] = [];\n const later = (fn: () => void, ms: number) => timers.push(window.setTimeout(fn, ms));\n const every = (fn: () => void, ms: number) => intervals.push(window.setInterval(fn, ms));\n cleanups.push(() => {\n timers.forEach((t) => window.clearTimeout(t));\n intervals.forEach((t) => window.clearInterval(t));\n });\n const addStyle = (css: string) => {\n const style = document.createElement('style');\n style.setAttribute('data-rk-fx', '');\n style.textContent = css;\n document.head.appendChild(style);\n cleanups.push(() => style.remove());\n };\n const wave = (spec: ParticleSpec) => {\n const sub = document.createElement('div');\n sub.className = 'rk-fx-layer';\n layer.appendChild(sub);\n spawnParticles(sub, spec, reduced, spec.durationMs);\n timers.push(window.setTimeout(() => sub.remove(), spec.durationMs + 1600));\n cleanups.push(() => sub.remove());\n };\n if (!reduced) {\n // Freeze scrolling (the base zoom would grow scrollbars) — restored exactly.\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n const htmlOverflow = document.documentElement.style.overflow;\n document.documentElement.style.overflow = 'hidden';\n cleanups.push(() => {\n document.documentElement.style.overflow = htmlOverflow;\n if (document.documentElement.getAttribute('style') === '') document.documentElement.removeAttribute('style');\n window.scrollTo(scrollX, scrollY);\n });\n const originY = scrollY + window.innerHeight / 2;\n addStyle(`${CHAOS_SEL} { transform-origin: 50vw ${originY}px; }`);\n }\n build({\n layer,\n reduced,\n addStyle,\n later,\n every,\n wave,\n decayText: () => startTextDecay(cleanups, every),\n cleanups,\n });\n installKillWord(cleanups);\n return () => {\n for (const fn of cleanups) fn();\n };\n };\n}\n\n/**\n * Typography decay — glitch-swaps characters IN TEXT NODES ONLY. Element\n * structure is never touched (the innerText-wipes-children lesson); every\n * node's original string is snapshotted and restored verbatim on cleanup, so\n * outerHTML of affected elements ends byte-identical.\n */\nfunction startTextDecay(\n cleanups: Array<() => void>,\n every: (fn: () => void, ms: number) => void,\n): void {\n const GLYPHS = '▓▒░#@%&$?!ר∆§';\n const originals = new Map<Text, string>();\n const nodes: Text[] = [];\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);\n let node: Node | null;\n while ((node = walker.nextNode()) && nodes.length < 120) {\n const text = node as Text;\n const value = text.nodeValue ?? '';\n if (value.trim().length < 4) continue;\n const parent = text.parentElement;\n if (!parent || parent.closest('[data-review-kit-host], script, style, [data-rk-edited]')) continue;\n nodes.push(text);\n }\n every(() => {\n for (let i = 0; i < 22; i++) {\n const text = nodes[(Math.random() * nodes.length) | 0];\n if (!text || !text.isConnected) continue;\n if (!originals.has(text)) originals.set(text, text.nodeValue ?? '');\n const original = originals.get(text) ?? '';\n if (Math.random() < 0.3) {\n text.nodeValue = original; // shimmer back to sanity sometimes\n continue;\n }\n const chars = [...original];\n const swaps = 1 + ((Math.random() * 3) | 0);\n for (let k = 0; k < swaps; k++) {\n const idx = (Math.random() * chars.length) | 0;\n if (chars[idx] !== ' ') chars[idx] = GLYPHS[(Math.random() * GLYPHS.length) | 0];\n }\n text.nodeValue = chars.join('');\n }\n }, 260);\n cleanups.push(() => {\n for (const [text, value] of originals) {\n if (text.isConnected && text.nodeValue !== value) text.nodeValue = value;\n }\n originals.clear();\n });\n}\n\n/** Letters visibly falling out of headings — rendered as OVERLAY clones in\n * the shadow layer; the real DOM is never touched. */\nfunction spawnFallingLetters(layer: HTMLElement): void {\n const sub = document.createElement('div');\n sub.className = 'rk-fx-layer';\n layer.appendChild(sub);\n const headings = [...document.querySelectorAll('h1, h2, h3')].filter((el) => {\n const r = el.getBoundingClientRect();\n return r.width > 0 && r.top < window.innerHeight && r.bottom > 0 && !el.closest('[data-review-kit-host]');\n });\n let spawned = 0;\n for (const heading of headings.slice(0, 3)) {\n const textNode = [...heading.childNodes].find((n) => n.nodeType === 3 && (n.nodeValue ?? '').trim().length > 3);\n const source = textNode ?? heading.firstChild;\n if (!source || source.nodeType !== 3) continue;\n const value = source.nodeValue ?? '';\n const range = document.createRange();\n for (let i = 0; i < value.length && spawned < 26; i++) {\n if (value[i] === ' ' || Math.random() < 0.55) continue;\n range.setStart(source, i);\n range.setEnd(source, i + 1);\n const rect = range.getBoundingClientRect();\n if (rect.width === 0) continue;\n const span = document.createElement('span');\n span.className = 'rk-fx-letter';\n span.textContent = value[i];\n span.style.left = `${rect.left}px`;\n span.style.top = `${rect.top}px`;\n span.style.fontSize = `${rect.height}px`;\n span.style.animationDelay = `${(Math.random() * 900) | 0}ms`;\n span.style.setProperty('--fx-drift', `${((Math.random() * 120) | 0) - 60}px`);\n sub.appendChild(span);\n spawned++;\n }\n }\n window.setTimeout(() => sub.remove(), 4600);\n}\n\n/** Sliding glitch strips over the page — backdrop-filter hue/saturation\n * shifts that MOVE (no blinking, no inversion → no strobe risk). */\nfunction spawnGlitchBands(layer: HTMLElement, cleanups: Array<() => void>): void {\n for (let i = 0; i < 3; i++) {\n const band = document.createElement('div');\n band.className = 'rk-fx-band';\n band.style.height = `${34 + i * 16}px`;\n band.style.animationDuration = `${2.8 + i * 0.7}s`;\n band.style.animationDelay = `${i * 0.9}s`;\n layer.appendChild(band);\n cleanups.push(() => band.remove());\n }\n}\n\n/* --------------- the /ondro-caliber page wreckers ---------------- */\n\n/** /lava — the page overheats, softens and slowly runs down the screen. */\nconst startLava = bigEffect(({ layer, reduced, addStyle, later, every, wave, decayText, cleanups }) => {\n if (reduced) {\n addStyle(`@keyframes rk-lava-soft { 0%,100% { filter: none; } 50% { filter: sepia(0.35) hue-rotate(-20deg) saturate(1.3); } }\n${CHAOS_SEL} { animation: rk-lava-soft 9s ease-in-out infinite; }`);\n wave({ kind: 'rain', glyphs: ['🫠', '🔥'], count: 8, durationMs: 9000 });\n every(() => wave({ kind: 'rain', glyphs: ['🫠', '💧'], count: 6, durationMs: 9000 }), 14000);\n return;\n }\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('data-rk-fx', '');\n svg.setAttribute('width', '0');\n svg.setAttribute('height', '0');\n svg.style.position = 'absolute';\n svg.innerHTML = `<defs><filter id=\"rk-lava-warp\" x=\"-10%\" y=\"-10%\" width=\"120%\" height=\"130%\">\n <feTurbulence type=\"fractalNoise\" baseFrequency=\"0.008 0.003\" numOctaves=\"2\" result=\"n\" seed=\"4\">\n <animate attributeName=\"baseFrequency\" dur=\"7s\" values=\"0.008 0.003;0.014 0.006;0.008 0.003\" repeatCount=\"indefinite\"/>\n </feTurbulence>\n <feDisplacementMap in=\"SourceGraphic\" in2=\"n\" scale=\"10\" xChannelSelector=\"R\" yChannelSelector=\"G\">\n <animate attributeName=\"scale\" dur=\"6s\" values=\"4;24;4\" repeatCount=\"indefinite\"/>\n </feDisplacementMap>\n </filter></defs>`;\n document.body.appendChild(svg);\n cleanups.push(() => svg.remove());\n\n // Phase 1: the heat arrives — shimmer, warm hue, first sag.\n addStyle(`@keyframes rk-lava1 {\n 0% { filter: none; transform: scale(1.22); }\n 35% { filter: sepia(0.4) hue-rotate(-24deg) saturate(1.8) blur(0.8px); transform: scale(1.235) skewY(0.5deg) translateY(6px); }\n 70% { filter: sepia(0.6) hue-rotate(-38deg) saturate(2.2) contrast(1.1) blur(1.6px); transform: scale(1.22) scaleY(1.03) translateY(14px) skewX(-0.6deg); }\n 100% { filter: none; transform: scale(1.22); }\n}\n${CHAOS_SEL} { animation: rk-lava1 7s ease-in-out infinite; }`);\n // Phase 2 (10s): properly molten — displacement warp + heavy vertical sag.\n later(() => {\n addStyle(`@keyframes rk-lava2 {\n 0% { filter: url(#rk-lava-warp) sepia(0.5) hue-rotate(-30deg) saturate(2); transform: scale(1.22) translateY(10px); }\n 40% { filter: url(#rk-lava-warp) sepia(0.8) hue-rotate(-48deg) saturate(2.8) contrast(1.18) blur(2.4px); transform: scale(1.2) scaleY(1.1) translateY(46px) skewX(1deg); }\n 70% { filter: url(#rk-lava-warp) sepia(0.7) hue-rotate(-40deg) saturate(2.4) blur(1.2px); transform: scale(1.23) scaleY(1.06) translateY(28px) skewY(-0.8deg); }\n 100% { filter: url(#rk-lava-warp) sepia(0.5) hue-rotate(-30deg) saturate(2); transform: scale(1.22) translateY(10px); }\n}\n${CHAOS_SEL} { animation: rk-lava2 6.5s ease-in-out infinite; }\n@keyframes rk-lava-text { 0%,100% { letter-spacing: normal; } 50% { letter-spacing: 0.1em; word-spacing: 0.25em; text-shadow: 0 6px 6px rgba(255,80,0,0.5); } }\nh1, h2, h3, p, a, li, button { animation: rk-lava-text 5s ease-in-out infinite; }`);\n decayText();\n }, 10000);\n // Molten streaks running down the screen the whole time.\n const drips = document.createElement('div');\n drips.className = 'rk-fx-layer';\n layer.appendChild(drips);\n cleanups.push(() => drips.remove());\n every(() => {\n const d = document.createElement('div');\n d.className = 'rk-fx-drip';\n d.style.left = `${(Math.random() * 96 + 2).toFixed(1)}vw`;\n d.style.animationDuration = `${(3.5 + Math.random() * 3).toFixed(2)}s`;\n d.style.background = `linear-gradient(180deg, transparent, hsl(${(Math.random() * 30 + 8) | 0}, 95%, 55%))`;\n drips.appendChild(d);\n window.setTimeout(() => d.remove(), 7000);\n }, 700);\n wave({ kind: 'rain', glyphs: ['🔥', '🫠', '🌡️', '💧'], count: 30, durationMs: 10000 });\n every(() => wave({ kind: 'rain', glyphs: ['🔥', '🫠', '💧'], count: 22, durationMs: 9000 }), 9500);\n});\n\n/** /sklo — the page shatters into pieces like glass, drifts apart and\n * reassembles, over and over. Real elements fly; layout never changes. */\nconst startSklo = bigEffect(({ layer, reduced, addStyle, every, wave, decayText, cleanups }) => {\n if (reduced) {\n addStyle(`@keyframes rk-sklo-soft { 0%,100% { filter: none; } 50% { filter: saturate(0.7) brightness(1.06); } }\n${CHAOS_SEL} { animation: rk-sklo-soft 8s ease-in-out infinite; }`);\n wave({ kind: 'burst', glyphs: ['✧', '❖', '💠'], count: 10, durationMs: 8000 });\n return;\n }\n addStyle(`@keyframes rk-sklo-base {\n 0%,10% { transform: scale(1.12); filter: none; }\n 16% { transform: scale(1.125) rotate(0.4deg); filter: brightness(1.12) contrast(1.06); }\n 50% { transform: scale(1.1) rotate(-0.5deg); filter: saturate(0.65) brightness(1.05) blur(0.5px); }\n 72% { transform: scale(1.12); filter: none; }\n 100% { transform: scale(1.12); filter: none; }\n}\n${CHAOS_SEL} { animation: rk-sklo-base 11s ease-in-out infinite; }\n@keyframes rk-sklo-fly {\n 0%, 12% { transform: translate(0, 0) rotate(0); opacity: 1; }\n 30% { transform: translate(var(--rk-gx), var(--rk-gy)) rotate(var(--rk-gr)); opacity: 0.92; }\n 52% { transform: translate(calc(var(--rk-gx) * 1.18), calc(var(--rk-gy) * 1.18)) rotate(calc(var(--rk-gr) * 1.25)); opacity: 0.85; }\n 74% { transform: translate(0, 0) rotate(0); opacity: 1; }\n 100% { transform: translate(0, 0) rotate(0); opacity: 1; }\n}\n[data-rk-shard] { animation: rk-sklo-fly 11s cubic-bezier(0.55, 0, 0.3, 1) infinite; }`);\n // Pick visible content blocks and hand each its own trajectory. The\n // trajectories live in a generated stylesheet keyed by the shard index —\n // never in inline styles: Chrome resurrects a removed \\`style\\` attribute\n // as \\`style=\"\"\\` once el.style was touched, which would break the\n // byte-exact restore guarantee.\n const shards = [...document.querySelectorAll<HTMLElement>('h1, h2, h3, h4, p, li, img, button, a')]\n .filter((el) => {\n if (el.closest('[data-review-kit-host]')) return false;\n const r = el.getBoundingClientRect();\n return r.width > 8 && r.height > 8 && r.bottom > -200 && r.top < window.innerHeight + 200;\n })\n .slice(0, 90);\n const rules: string[] = [];\n shards.forEach((el, i) => {\n const angle = (i * 137.5 * Math.PI) / 180;\n const dist = 18 + ((i * 29) % 46);\n rules.push(\n `[data-rk-shard=\"${i}\"] { --rk-gx: ${(Math.cos(angle) * dist).toFixed(1)}vw; --rk-gy: ${(Math.sin(angle) * dist).toFixed(1)}vh; --rk-gr: ${((i * 97) % 640) - 320}deg; }`,\n );\n el.setAttribute('data-rk-shard', String(i));\n });\n addStyle(rules.join('\\n'));\n cleanups.push(() => {\n for (const el of shards) el.removeAttribute('data-rk-shard');\n });\n // Crack lines flare up right as the pieces let go (opacity ease, no strobe).\n const cracks = document.createElement('div');\n cracks.className = 'rk-fx-cracks';\n cracks.innerHTML = Array.from({ length: 9 }, (_, i) => {\n const angle = i * 40 + (i % 3) * 7;\n return `<span style=\"transform: rotate(${angle}deg); animation-delay: ${(i * 0.05).toFixed(2)}s\"></span>`;\n }).join('');\n layer.appendChild(cracks);\n cleanups.push(() => cracks.remove());\n decayText();\n every(() => wave({ kind: 'burst', glyphs: ['✧', '❖', '💠', '🧊'], count: 26, durationMs: 5000 }), 11000);\n wave({ kind: 'burst', glyphs: ['✧', '❖', '💠'], count: 26, durationMs: 5000 });\n});\n\n/** /vir — the whole page gets pulled into a spinning vortex at the center. */\nconst startVir = bigEffect(({ layer, reduced, addStyle, later, wave, decayText, cleanups }) => {\n if (reduced) {\n addStyle(`@keyframes rk-vir-soft { 0%,100% { filter: none; } 50% { filter: hue-rotate(50deg); } }\n${CHAOS_SEL} { animation: rk-vir-soft 9s ease-in-out infinite; }`);\n wave({ kind: 'burst', glyphs: ['🌀'], count: 8, durationMs: 8000 });\n return;\n }\n // Phase 1: the pull starts — slow breathing rotation.\n addStyle(`@keyframes rk-vir1 {\n 0% { transform: scale(1.25) rotate(0deg); filter: none; }\n 30% { transform: scale(1.31) rotate(4deg); filter: hue-rotate(50deg) saturate(1.3) blur(0.5px); }\n 60% { transform: scale(1.28) rotate(-3.4deg); filter: hue-rotate(140deg) saturate(0.8) blur(1px); }\n 100% { transform: scale(1.25) rotate(0deg); filter: none; }\n}\n${CHAOS_SEL} { animation: rk-vir1 6.5s ease-in-out infinite; }`);\n // Phase 2 (12s): the vortex bites — deeper angles, stronger suction.\n later(() => {\n addStyle(`@keyframes rk-vir2 {\n 0% { transform: scale(1.25) rotate(0deg); filter: hue-rotate(0deg) saturate(1.4); }\n 25% { transform: scale(1.42) rotate(9deg); filter: hue-rotate(90deg) saturate(1.9) blur(1.6px); }\n 50% { transform: scale(1.55) rotate(-7deg); filter: hue-rotate(200deg) saturate(0.6) contrast(1.15) blur(2.6px); }\n 75% { transform: scale(1.38) rotate(10deg); filter: hue-rotate(300deg) saturate(1.8) blur(1.2px); }\n 100% { transform: scale(1.25) rotate(0deg); filter: hue-rotate(360deg) saturate(1.4); }\n}\n${CHAOS_SEL} { animation: rk-vir2 5.5s ease-in-out infinite; }\n@keyframes rk-vir-text { 0%,100% { letter-spacing: normal; } 50% { letter-spacing: 0.16em; text-shadow: 3px 0 rgba(0,180,255,0.5), -3px 0 rgba(255,60,160,0.5); } }\nh1, h2, h3, p, a, li, button { animation: rk-vir-text 4.5s ease-in-out infinite; }`);\n decayText();\n }, 12000);\n // Debris spiralling into the center, continuously.\n const GLYPHS = ['🌀', '✨', '🍃', '📄', '☄️'];\n const bits: Array<{ el: HTMLSpanElement; r: number; a: number; v: number }> = [];\n const cx = () => window.innerWidth / 2;\n const cy = () => window.innerHeight / 2;\n const maxR = () => Math.hypot(window.innerWidth, window.innerHeight) / 2 + 60;\n for (let i = 0; i < 36; i++) {\n const el = document.createElement('span');\n el.className = 'rk-fx-particle';\n el.textContent = GLYPHS[i % GLYPHS.length];\n el.style.fontSize = `${13 + ((i * 11) % 16)}px`;\n layer.appendChild(el);\n bits.push({ el, r: maxR() * ((i + 1) / 36), a: i * 0.7, v: 0.6 + (i % 5) * 0.16 });\n }\n let raf = 0;\n const tick = () => {\n raf = requestAnimationFrame(tick);\n for (const bit of bits) {\n bit.a += 0.014 * bit.v * (1 + 140 / Math.max(bit.r, 40));\n bit.r -= 0.55 * bit.v;\n if (bit.r < 16) bit.r = maxR();\n bit.el.style.transform = `translate3d(${cx() + Math.cos(bit.a) * bit.r}px, ${cy() + Math.sin(bit.a) * bit.r}px, 0) rotate(${bit.a}rad)`;\n bit.el.style.opacity = `${Math.min(1, bit.r / 120)}`;\n }\n };\n raf = requestAnimationFrame(tick);\n cleanups.push(() => {\n cancelAnimationFrame(raf);\n bits.forEach((bit) => bit.el.remove());\n });\n});\n\n/** /crt — the site becomes a worn-out CRT television with a bad signal:\n * green phosphor, scanlines, vignette, a rolling band and signal tears. */\nconst startCrt = bigEffect(({ layer, reduced, addStyle, every, wave, decayText, cleanups }) => {\n if (reduced) {\n addStyle(`${CHAOS_SEL} { filter: sepia(0.7) hue-rotate(55deg) saturate(1.6) contrast(1.05); transition: filter 2s ease; }`);\n return;\n }\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('data-rk-fx', '');\n svg.setAttribute('width', '0');\n svg.setAttribute('height', '0');\n svg.style.position = 'absolute';\n svg.innerHTML = `<defs><filter id=\"rk-crt-tear\" x=\"-10%\" y=\"-10%\" width=\"120%\" height=\"120%\">\n <feTurbulence type=\"turbulence\" baseFrequency=\"0.002 0.09\" numOctaves=\"1\" result=\"n\" seed=\"11\">\n <animate attributeName=\"seed\" dur=\"3s\" values=\"11;37;11\" repeatCount=\"indefinite\"/>\n </feTurbulence>\n <feDisplacementMap in=\"SourceGraphic\" in2=\"n\" scale=\"0\" xChannelSelector=\"R\" yChannelSelector=\"G\">\n <animate attributeName=\"scale\" dur=\"8s\" values=\"0;0;26;4;0;0\" keyTimes=\"0;0.55;0.62;0.7;0.78;1\" repeatCount=\"indefinite\"/>\n </feDisplacementMap>\n </filter></defs>`;\n document.body.appendChild(svg);\n cleanups.push(() => svg.remove());\n addStyle(`@keyframes rk-crt-hold {\n 0%, 60% { transform: scale(1.16) translate(0, 0); }\n 64% { transform: scale(1.16) translate(-3px, 14px) skewX(-0.8deg); }\n 68% { transform: scale(1.16) translate(2px, -8px); }\n 74%, 100% { transform: scale(1.16) translate(0, 0); }\n}\n${CHAOS_SEL} {\n filter: url(#rk-crt-tear) sepia(1) hue-rotate(55deg) saturate(2.6) contrast(1.22) brightness(0.92);\n animation: rk-crt-hold 8s linear infinite;\n}\n@keyframes rk-crt-text { 0%,100% { text-shadow: 1px 0 rgba(0,255,120,0.5); } 50% { text-shadow: -2px 0 rgba(0,255,120,0.7), 2px 0 rgba(0,120,60,0.5); letter-spacing: 0.06em; } }\nh1, h2, h3, p, a, li, button { animation: rk-crt-text 5s ease-in-out infinite; }`);\n const overlay = document.createElement('div');\n overlay.className = 'rk-fx-crt';\n overlay.innerHTML = '<div class=\"rk-fx-crt-scan\"></div><div class=\"rk-fx-crt-roll\"></div><div class=\"rk-fx-crt-vignette\"></div><div class=\"rk-fx-crt-osd\">KANÁL 69 · SLABÝ SIGNÁL</div>';\n layer.appendChild(overlay);\n cleanups.push(() => overlay.remove());\n decayText();\n every(() => wave({ kind: 'rain', glyphs: ['📺', '📡', '𝍍'], count: 10, durationMs: 7000 }), 16000);\n});\n\n/** /kokot — a rude alert banner marquees across the screen. Visual only. */\nfunction startBanner({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const banner = document.createElement('div');\n banner.className = 'rk-fx-banner';\n banner.textContent = '🚨 KOKOT ALERT 🚨 KOKOT ALERT 🚨 KOKOT ALERT 🚨';\n if (reduced) banner.classList.add('rk-fx-banner-still');\n layer.appendChild(banner);\n return () => banner.remove();\n}\n\n/** /vrtule — every image on the page gently takes off. Injected style only. */\nfunction startVrtule({ reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const style = document.createElement('style');\n style.setAttribute('data-rk-fx', 'vrtule');\n style.textContent = reduced\n ? `@keyframes rk-vrtula { 0%,100% { transform: rotate(0); } 50% { transform: rotate(3deg); } }\nimg { animation: rk-vrtula 4s ease-in-out infinite; }`\n : `@keyframes rk-vrtula { from { transform: rotate(0) scale(1); } 50% { transform: rotate(180deg) scale(0.9); } to { transform: rotate(360deg) scale(1); } }\nimg { animation: rk-vrtula 3.6s ease-in-out infinite; }`;\n document.head.appendChild(style);\n return () => style.remove();\n}\n\n/** Shared cursor-chase engine: critters follow every live peer cursor and the\n * local pointer. Powers /muchy and /pes; visual overlay only. */\nfunction makeChase(options: {\n glyphs: string[];\n count: number;\n sizePx: (i: number) => number;\n orbit: (seed: number) => number;\n lag: number;\n wobbleT?: number;\n flip?: boolean;\n}) {\n return function startChase({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const critters: Array<{ el: HTMLSpanElement; x: number; y: number; seed: number }> = [];\n const count = reduced ? Math.min(4, options.count) : options.count;\n for (let i = 0; i < count; i++) {\n const el = document.createElement('span');\n el.className = 'rk-fx-particle';\n el.textContent = options.glyphs[i % options.glyphs.length];\n el.style.fontSize = `${options.sizePx(i)}px`;\n layer.appendChild(el);\n critters.push({ el, x: window.innerWidth / 2, y: window.innerHeight / 2, seed: i * 137 });\n }\n const wobble = options.wobbleT ?? 400;\n let raf = 0;\n const tick = (t: number) => {\n raf = requestAnimationFrame(tick);\n // Targets: every visible peer cursor chip + the local pointer.\n const root = layer.getRootNode() as ShadowRoot | Document;\n const chips = [...root.querySelectorAll('.rk-peer-cursor')]\n .filter((c) => (c as HTMLElement).style.opacity !== '0')\n .map((c) => {\n const m = /translate3d\\(([-\\d.]+)px, ([-\\d.]+)px/.exec((c as HTMLElement).style.transform);\n return m ? { x: parseFloat(m[1]), y: parseFloat(m[2]) } : null;\n })\n .filter((p): p is { x: number; y: number } => p !== null);\n chips.push({ x: lastPointerFallback.x, y: lastPointerFallback.y });\n for (const critter of critters) {\n const target = chips[critter.seed % chips.length];\n const orbit = reduced ? 14 : options.orbit(critter.seed);\n const wx = target.x + Math.cos(t / wobble + critter.seed) * orbit;\n const wy = target.y + Math.sin(t / (wobble * 0.82) + critter.seed) * orbit;\n const prevX = critter.x;\n critter.x += (wx - critter.x) * options.lag;\n critter.y += (wy - critter.y) * options.lag;\n const face = options.flip && critter.x < prevX ? ' scaleX(-1)' : '';\n critter.el.style.transform = `translate3d(${critter.x}px, ${critter.y}px, 0)${face}`;\n }\n };\n raf = requestAnimationFrame(tick);\n const onMove = (event: PointerEvent) => {\n lastPointerFallback.x = event.clientX;\n lastPointerFallback.y = event.clientY;\n };\n document.addEventListener('pointermove', onMove, { passive: true });\n return () => {\n cancelAnimationFrame(raf);\n document.removeEventListener('pointermove', onMove);\n for (const critter of critters) critter.el.remove();\n };\n };\n}\nconst lastPointerFallback = { x: 300, y: 300 };\n\n/** One data-rk-fx <style> tag with automatic removal — shared by the small\n * page-filter effects below. */\nfunction styleEffect(css: string): () => void {\n const style = document.createElement('style');\n style.setAttribute('data-rk-fx', '');\n style.textContent = css;\n document.head.appendChild(style);\n return () => style.remove();\n}\n\nconst PAGE_SEL = 'body > :not([data-review-kit-host]):not(script):not(style)';\n\n/** /disko — slow hue sweep + sparkles. One full color cycle per 4 s. */\nfunction startDisko({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const remove = styleEffect(\n reduced\n ? `@keyframes rk-disko { 0%,100% { filter: none; } 50% { filter: hue-rotate(60deg) saturate(1.2); } }\n${PAGE_SEL} { animation: rk-disko 8s ease-in-out infinite; }`\n : `@keyframes rk-disko { from { filter: hue-rotate(0deg) saturate(1.35); } to { filter: hue-rotate(360deg) saturate(1.35); } }\n${PAGE_SEL} { animation: rk-disko 4s linear infinite; }`,\n );\n spawnParticles(layer, { kind: 'rain', glyphs: ['✨', '🪩', '💃', '🕺'], count: 26, durationMs: 15000 }, reduced, 15000);\n return remove;\n}\n\n/** /zrkadlo — the whole page slowly flips into mirror world and back. */\nfunction startZrkadlo({ reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n if (reduced) {\n return styleEffect(`${PAGE_SEL} { filter: saturate(0.8); transition: filter 2s ease; }`);\n }\n return styleEffect(`@keyframes rk-zrkadlo {\n 0%, 100% { transform: perspective(1400px) rotateY(0); }\n 35%, 65% { transform: perspective(1400px) rotateY(180deg); }\n}\n${PAGE_SEL} { animation: rk-zrkadlo 12s ease-in-out both; transform-origin: 50% 50%; }`);\n}\n\n/** /pohreb — the page slowly drains of color while wilted roses fall. */\nfunction startPohreb({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const remove = styleEffect(`@keyframes rk-pohreb { from { filter: none; } to { filter: grayscale(1) brightness(0.82) sepia(0.15); } }\n${PAGE_SEL} { animation: rk-pohreb 5s ease-out both; }`);\n spawnParticles(layer, { kind: 'rain', glyphs: ['🥀', '⚰️', '🕯️', '🖤'], count: reduced ? 8 : 22, durationMs: 14000 }, reduced, 14000);\n return remove;\n}\n\n/** /laser — party beams sweep the page from the corners. Overlay only. */\nfunction startLaser({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const beams: HTMLElement[] = [];\n const count = reduced ? 2 : 5;\n const hues = [330, 190, 120, 45, 265];\n for (let i = 0; i < count; i++) {\n const beam = document.createElement('div');\n beam.className = 'rk-fx-laser';\n beam.style.background = `linear-gradient(90deg, transparent, hsla(${hues[i % hues.length]}, 100%, 60%, 0.55), transparent)`;\n beam.style.left = `${(i % 2) * 100}%`;\n beam.style.animationDuration = `${3.4 + i * 0.6}s`;\n beam.style.animationDelay = `${i * 0.45}s`;\n if (i % 2) beam.style.animationDirection = 'reverse';\n layer.appendChild(beam);\n beams.push(beam);\n }\n return () => beams.forEach((b) => b.remove());\n}\n\n/** /kura — a chicken struts along the bottom edge, leaving eggs. Some hatch. */\nfunction startKura({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const hen = document.createElement('span');\n hen.className = 'rk-fx-kura';\n hen.textContent = '🐔';\n layer.appendChild(hen);\n const props: HTMLElement[] = [hen];\n const timers: number[] = [];\n const walkMs = reduced ? 16000 : 11000;\n hen.style.animationDuration = `${walkMs}ms`;\n if (!reduced) {\n for (let i = 1; i <= 5; i++) {\n timers.push(\n window.setTimeout(() => {\n const egg = document.createElement('span');\n egg.className = 'rk-fx-egg';\n egg.textContent = '🥚';\n egg.style.left = `${(i / 6) * 100}%`;\n layer.appendChild(egg);\n props.push(egg);\n timers.push(\n window.setTimeout(() => {\n egg.textContent = '🐣';\n }, 2600 + i * 400),\n );\n }, (walkMs * i) / 6),\n );\n }\n }\n return () => {\n timers.forEach((t) => window.clearTimeout(t));\n props.forEach((p) => p.remove());\n };\n}\n\n/** /spam — a storm of fake-important toasts. Pure overlay, self-cleaning. */\nfunction startSpam({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const MESSAGES = [\n '⚠️ Kritická chyba: stránka je príliš pekná',\n '🔥 69 ľudí práve pozerá tento button',\n '💾 Ukladám tvoje hriechy…',\n '📈 Konverzia stúpla o 420 %',\n '🧠 AI navrhuje: prerob to celé',\n '🍪 Táto stránka žerie koláčiky',\n '📞 Volá ti klient. Zdvihni.',\n '💸 Faktúra po splatnosti (odjakživa)',\n '🛸 Zistená mimozemská aktivita v pätičke',\n '✅ Nič sa nepodarilo úspešne',\n ];\n const toasts: HTMLElement[] = [];\n const timers: number[] = [];\n const total = reduced ? 4 : MESSAGES.length;\n for (let i = 0; i < total; i++) {\n timers.push(\n window.setTimeout(() => {\n const toast = document.createElement('div');\n toast.className = 'rk-fx-toast';\n toast.textContent = MESSAGES[i % MESSAGES.length];\n toast.style.top = `${14 + (i % 5) * 58}px`;\n layer.appendChild(toast);\n toasts.push(toast);\n timers.push(window.setTimeout(() => toast.remove(), 5200));\n }, i * (reduced ? 1800 : 950)),\n );\n }\n return () => {\n timers.forEach((t) => window.clearTimeout(t));\n toasts.forEach((t) => t.remove());\n };\n}\n\nexport const EFFECTS: Record<EffectName, EffectSpec> = {\n ondro: { kind: 'custom', durationMs: ONDRO_MS, start: startOndro },\n lava: { kind: 'custom', durationMs: BIG_MS, start: startLava },\n sklo: { kind: 'custom', durationMs: BIG_MS, start: startSklo },\n vir: { kind: 'custom', durationMs: BIG_MS, start: startVir },\n crt: { kind: 'custom', durationMs: BIG_MS, start: startCrt },\n hovno: { kind: 'rain', glyphs: ['💩'], count: 44, durationMs: 4200 },\n konfety: { kind: 'burst', glyphs: ['🎉', '🎊', '✨'], count: 56, durationMs: 3600 },\n srdiecka: { kind: 'rain', glyphs: ['❤️', '💚', '💛'], count: 40, durationMs: 4200 },\n sneh: { kind: 'rain', glyphs: ['❄️', '🌨️'], count: 48, durationMs: 5200 },\n zemetrasenie: { kind: 'rain', glyphs: ['🪨', '🧱'], count: 18, durationMs: 2400, shake: true },\n '69': { kind: 'burst', glyphs: ['🍆', '🍑', '💦'], count: 69, durationMs: NICE_MS },\n kokot: { kind: 'custom', durationMs: 14500, start: startBanner },\n vrtule: { kind: 'custom', durationMs: NICE_MS, start: startVrtule },\n muchy: {\n kind: 'custom',\n durationMs: NICE_MS,\n start: makeChase({ glyphs: ['🪰'], count: 14, sizePx: (i) => 12 + (i % 3) * 4, orbit: (s) => 26 + (s % 20), lag: 0.12, wobbleT: 400 }),\n },\n pes: {\n kind: 'custom',\n durationMs: 12000,\n start: makeChase({ glyphs: ['🐕', '🐩', '🦮'], count: 3, sizePx: (i) => 26 + (i % 2) * 6, orbit: (s) => 46 + (s % 30), lag: 0.055, wobbleT: 900, flip: true }),\n },\n pivo: { kind: 'rain', glyphs: ['🍺', '🍻', '🍾'], count: 42, durationMs: 8000 },\n nikotin: { kind: 'rain', glyphs: ['🚬', '💨', '😮‍💨'], count: 20, durationMs: 13000 },\n matrix: { kind: 'rain', glyphs: [...'アカサタナ0169ハマヤラヲ'], count: 64, durationMs: 12000, className: 'rk-fx-matrix' },\n disko: { kind: 'custom', durationMs: 15000, start: startDisko },\n zrkadlo: { kind: 'custom', durationMs: 12000, start: startZrkadlo },\n pohreb: { kind: 'custom', durationMs: 14000, start: startPohreb },\n laser: { kind: 'custom', durationMs: 12000, start: startLaser },\n kura: { kind: 'custom', durationMs: 11500, start: startKura },\n spam: { kind: 'custom', durationMs: 11000, start: startSpam },\n};\n\nexport function effectNames(): string[] {\n return Object.keys(EFFECTS);\n}\n\n/**\n * Run an effect inside the shadow root (`layerHost` = .rk-root). Returns\n * false for unknown names (caller treats the text as a comment). The name\n * 'stop' is the room-wide kill switch and just cancels everything.\n */\nexport function runEffect(name: string, layerHost: HTMLElement | null): boolean {\n if (name === 'stop') {\n cancelEffects();\n return true;\n }\n const spec: EffectSpec | undefined = (EFFECTS as Record<string, EffectSpec | undefined>)[name];\n if (!spec || !layerHost) return spec !== undefined;\n const reduced = reducedMotion();\n const duration = reduced && spec.kind !== 'custom' ? Math.min(2000, spec.durationMs) : spec.durationMs;\n\n const layer = document.createElement('div');\n layer.className = 'rk-fx-layer';\n layerHost.appendChild(layer);\n\n let customCleanup: (() => void) | null = null;\n let shakeCleanup: (() => void) | null = null;\n if (spec.kind === 'custom') {\n customCleanup = spec.start({ layer, reduced });\n } else {\n spawnParticles(layer, spec, reduced, duration);\n if (spec.shake && !reduced) shakeCleanup = runShake();\n }\n\n let timer = 0;\n const cancel = () => {\n window.clearTimeout(timer);\n customCleanup?.();\n shakeCleanup?.();\n layer.remove();\n active.delete(cancel);\n };\n timer = window.setTimeout(cancel, duration + 1200);\n active.add(cancel);\n return true;\n}\n","/**\n * Lazy façade over `effects.ts`. The effect implementations are a separate\n * chunk that downloads the first time someone runs a `/` command (locally or\n * from a peer); until then only the name list is in memory. Cancel and the\n * broadcaster hook degrade gracefully while the chunk is not loaded — with\n * nothing loaded, nothing can be running.\n */\n\nimport { isEffectCommand } from './effectCatalog';\n\ninterface EffectsModule {\n runEffect(name: string, layerHost: HTMLElement | null): boolean;\n cancelEffects(): boolean;\n setEffectBroadcaster(fn: ((name: string) => void) | null): void;\n setFxAssetsUrl(url: string | null): void;\n}\n\nlet loaded: EffectsModule | null = null;\nlet loading: Promise<EffectsModule> | null = null;\nlet broadcaster: ((name: string) => void) | null = null;\nlet assetsUrl: string | null = null;\n/** Effects queued on the in-flight import; a cancel that arrives meanwhile must still win. */\nlet queued = 0;\n\nfunction load(): Promise<EffectsModule> {\n if (loaded) return Promise.resolve(loaded);\n if (!loading) {\n loading = import('./effects')\n .then((mod) => {\n loaded = mod;\n mod.setEffectBroadcaster(broadcaster);\n mod.setFxAssetsUrl(assetsUrl);\n return mod;\n })\n .catch((error: unknown) => {\n loading = null; // a failed download (offline, CSP) is retried on the next command\n queued = 0;\n throw error;\n });\n }\n return loading;\n}\n\n/** Cancel now if the chunk is in, otherwise right after the queued effects start. */\nfunction cancelWhenReady(): boolean {\n if (loaded) return loaded.cancelEffects();\n if (loading && queued > 0) {\n // Registered after the pending runEffect callbacks, so it runs after\n // they start the effect and cancels it before the first frame.\n loading.then((mod) => mod.cancelEffects()).catch(() => undefined);\n return true;\n }\n return false;\n}\n\n/** Broadcast hook, injected by the sync layer; forwarded once the chunk exists. */\nexport function setEffectBroadcaster(fn: ((name: string) => void) | null): void {\n broadcaster = fn;\n loaded?.setEffectBroadcaster(fn);\n}\n\n/** Base URL for effect sounds (`ReviewKitConfig.fxAssetsUrl`); forwarded once loaded. */\nexport function setEffectAssetsUrl(url: string | null | undefined): void {\n assetsUrl = url ?? null;\n loaded?.setFxAssetsUrl(assetsUrl);\n}\n\n/** Cancel everything running or queued behind the chunk download. */\nexport function cancelEffects(): boolean {\n return cancelWhenReady();\n}\n\n/**\n * Run an effect by name. Returns synchronously whether the name is a known\n * command (callers treat unknown text as a plain comment); the effect itself\n * starts once the chunk is in. Load failures are swallowed — effects are\n * best-effort fun and must never break the review layer.\n */\nexport function runEffect(name: string, layerHost: HTMLElement | null): boolean {\n if (!isEffectCommand(name)) return false;\n if (name === 'stop') {\n cancelWhenReady();\n return true;\n }\n queued += 1;\n void load()\n .then((mod) => {\n queued = Math.max(0, queued - 1);\n mod.runEffect(name, layerHost);\n })\n .catch(() => {\n /* chunk failed to load (offline, CSP) — ignore; next command retries */\n });\n return true;\n}\n","/** Export / import helpers for review sessions. */\n\nimport type { ReviewSession } from '../schema';\nimport { parseSessionJson } from '../schema';\nimport type { ParseResult } from '../schema';\nimport { HOST_ATTR } from './target';\n\nfunction pad(n: number): string {\n return String(n).padStart(2, '0');\n}\n\nexport function exportFilename(session: ReviewSession, now: Date = new Date()): string {\n let host = 'site';\n try {\n host = new URL(session.site.origin).hostname;\n } catch {\n /* keep fallback */\n }\n const site = host.replace(/[^a-z0-9.-]/gi, '').replace(/\\.+$/, '') || 'site';\n const stamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}`;\n return `review-${site}-${stamp}.json`;\n}\n\nexport function sessionToJson(session: ReviewSession): string {\n return JSON.stringify(session, null, 2);\n}\n\nexport function downloadSession(session: ReviewSession): void {\n const blob = new Blob([sessionToJson(session)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n // Tagged as plugin UI so pick mode's capture-phase click swallowing\n // can never cancel the programmatic download click.\n a.setAttribute(HOST_ATTR, '');\n a.href = url;\n a.download = exportFilename(session);\n document.body.appendChild(a);\n a.click();\n a.remove();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\nexport async function copySessionToClipboard(session: ReviewSession): Promise<boolean> {\n try {\n await navigator.clipboard.writeText(sessionToJson(session));\n return true;\n } catch {\n return false;\n }\n}\n\nexport function importSessionFile(file: File): Promise<ParseResult> {\n return new Promise((resolve) => {\n const reader = new FileReader();\n reader.onload = () => {\n resolve(parseSessionJson(typeof reader.result === 'string' ? reader.result : ''));\n };\n reader.onerror = () => resolve({ ok: false, error: 'Could not read the file.' });\n reader.readAsText(file);\n });\n}\n","/**\n * Keyboard shortcut registry — the single source of truth. The key handler\n * in App, the cheat sheet and the toolbar tooltips are all derived from\n * this list; a shortcut that isn't here doesn't exist, and every row here\n * is live. Modifier display follows the platform (⌘ on mac, Ctrl elsewhere).\n */\n\nimport type { Dispatch } from 'react';\nimport { cancelEffects } from './effectsLazy';\nimport { copySessionToClipboard, downloadSession } from './exportSession';\nimport { lastPointer } from './pointer';\nimport { captureTarget } from './target';\nimport { revertElementPreview } from './preview';\nimport { findImage, pickElementAt, pointAnchor, resolveTarget } from './target';\nimport { rkId } from './id';\nimport type { ReviewTarget } from '../schema';\nimport type { Action, EditorKind, State, ToolKind } from './store';\nimport { choosePreview, toast } from './store';\n\nexport const IS_MAC =\n typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform);\n\n/** True when the event originates in any text-entry context (shadow or host). */\nexport function isTypingContext(event: KeyboardEvent): boolean {\n const path = event.composedPath();\n for (const node of path) {\n if (node instanceof HTMLElement) {\n const tag = node.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || node.isContentEditable) return true;\n }\n }\n return false;\n}\n\nexport interface ShortcutCtx {\n state: State;\n dispatch: Dispatch<Action>;\n event: KeyboardEvent;\n}\n\nexport interface ShortcutDef {\n id: string;\n group: 'Tools' | 'View' | 'Items' | 'Session';\n /** Short name — full-strength text everywhere the shortcut is listed. */\n title: string;\n /** Secondary detail line, visually muted under the title. */\n description: string;\n /** KeyboardEvent.key, lowercase. */\n key: string;\n altKeys?: string[];\n mod?: 'primary' | 'primary-shift';\n allowWhileTyping?: boolean;\n /** Return false to leave the event untouched (no preventDefault). */\n run: (ctx: ShortcutCtx) => void | false;\n}\n\nexport function matchShortcut(def: ShortcutDef, event: KeyboardEvent, mac: boolean): boolean {\n const key = event.key.toLowerCase();\n if (key !== def.key && !(def.altKeys ?? []).includes(key)) return false;\n const primary = mac ? event.metaKey : event.ctrlKey;\n const otherPrimary = mac ? event.ctrlKey : event.metaKey;\n if (def.mod === 'primary') return primary && !otherPrimary && !event.altKey && !event.shiftKey;\n if (def.mod === 'primary-shift') return primary && !otherPrimary && !event.altKey && event.shiftKey;\n return !event.metaKey && !event.ctrlKey && !event.altKey && (def.key === '?' || !event.shiftKey);\n}\n\nconst KEY_LABELS: Record<string, string> = {\n escape: 'Esc',\n backspace: '⌫',\n arrowup: '↑',\n arrowdown: '↓',\n};\n\nexport function displayKeys(def: ShortcutDef, mac: boolean): string[] {\n const parts: string[] = [];\n if (def.mod === 'primary' || def.mod === 'primary-shift') parts.push(mac ? '⌘' : 'Ctrl');\n if (def.mod === 'primary-shift') parts.push('⇧');\n parts.push(KEY_LABELS[def.key] ?? def.key.toUpperCase());\n return parts;\n}\n\n/** \"(T)\" / \"(⌘E)\" suffix for tooltips, derived from the same registry row. */\nexport function keyHint(id: string): string {\n const def = SHORTCUTS.find((entry) => entry.id === id);\n return def ? ` (${displayKeys(def, IS_MAC).join('')})` : '';\n}\n\n/** The registry row's short name — tooltips reuse it so naming stays single-source. */\nexport function shortcutTitle(id: string): string {\n return SHORTCUTS.find((entry) => entry.id === id)?.title ?? '';\n}\n\n/* ------------------------------------------------------------------ */\n/* Actions shared by tool shortcuts and the pick layer */\n/* ------------------------------------------------------------------ */\n\n/** Open an editor for an element right away (used by armed-tool clicks). */\nexport function openEditorFor(\n dispatch: Dispatch<Action>,\n kind: EditorKind,\n element: HTMLElement,\n target: ReviewTarget,\n): void {\n revertElementPreview(element);\n dispatch({ type: 'OPEN_EDITOR', editor: { kind, element, target } });\n}\n\n/** Tool key: apply to the current selection immediately, else arm the tool. */\nfunction armOrApply(ctx: ShortcutCtx, tool: Exclude<ToolKind, 'select'>): void {\n const { state, dispatch } = ctx;\n const selection = state.selection;\n if (selection) {\n if (tool === 'image' && !findImage(selection.element)) {\n toast(dispatch, 'That element has no image — press T to rewrite its text instead.', 'info');\n return;\n }\n openEditorFor(dispatch, tool, selection.element, selection.target);\n return;\n }\n dispatch({ type: 'SET_TOOL', tool });\n}\n\nfunction jumpItem(ctx: ShortcutCtx, delta: number): void {\n const { state, dispatch } = ctx;\n const items = state.session?.items.filter((item) => item.route === state.route) ?? [];\n if (items.length === 0) {\n toast(dispatch, 'No feedback items on this page yet.', 'info');\n return;\n }\n const index = items.findIndex((item) => item.id === state.activeItemId);\n const next =\n index === -1\n ? delta > 0\n ? items[0]\n : items[items.length - 1]\n : items[(index + delta + items.length) % items.length];\n dispatch({ type: 'SET_ACTIVE_ITEM', id: next.id });\n resolveTarget(next.target)?.element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n}\n\n/* ------------------------------------------------------------------ */\n/* The registry */\n/* ------------------------------------------------------------------ */\n\nexport const SHORTCUTS: ShortcutDef[] = [\n /* Tools */\n {\n id: 'tool-select',\n group: 'Tools',\n key: 'v',\n title: 'Select tool',\n description: 'Click an element to pick it',\n run: ({ dispatch }) => {\n dispatch({ type: 'SET_TOOL', tool: 'select' });\n },\n },\n {\n id: 'tool-copy',\n group: 'Tools',\n key: 't',\n title: 'Rewrite tool',\n description: 'Click text and start typing',\n run: (ctx) => armOrApply(ctx, 'copy'),\n },\n {\n id: 'tool-comment',\n group: 'Tools',\n key: 'c',\n title: 'Comment tool',\n description: 'Click an element to comment on it',\n run: (ctx) => armOrApply(ctx, 'comment'),\n },\n {\n id: 'tool-image',\n group: 'Tools',\n key: 'i',\n title: 'Image tool',\n description: 'Click a picture to replace it',\n run: (ctx) => armOrApply(ctx, 'image'),\n },\n {\n id: 'quick-comment',\n group: 'Tools',\n key: '/',\n title: 'Quick comment',\n description: 'Comment at the cursor',\n run: ({ dispatch }) => {\n const x = lastPointer.has ? lastPointer.x : window.innerWidth / 2;\n const y = lastPointer.has ? lastPointer.y : window.innerHeight / 2;\n const el = pickElementAt(x, y);\n if (!el) return false;\n const target = captureTarget(el);\n target.anchor = pointAnchor(el, x, y);\n dispatch({ type: 'OPEN_QUICK', quick: { id: rkId(), x, y, element: el, target } });\n },\n },\n {\n id: 'escape',\n group: 'Tools',\n key: 'escape',\n allowWhileTyping: true,\n title: 'Step back',\n description: 'Close card, drop tool, leave pick mode',\n run: ({ state, dispatch, event }) => {\n // The inline copy editor handles Esc on the host element itself.\n if (state.editor?.kind === 'copy' && isTypingContext(event)) return false;\n if (cancelEffects()) return;\n if (state.quick) dispatch({ type: 'CLOSE_QUICK' });\n else if (state.cheatsheetOpen) dispatch({ type: 'SET_CHEATSHEET', open: false });\n else if (state.confirm) dispatch({ type: 'SET_CONFIRM', confirm: null });\n else if (state.editor) dispatch({ type: 'CLOSE_EDITOR' });\n else if (state.selection) dispatch({ type: 'SELECT', selection: null });\n else if (state.mode === 'pick' && state.tool !== 'select') dispatch({ type: 'SET_TOOL', tool: 'select' });\n else if (state.mode === 'pick') dispatch({ type: 'SET_MODE', mode: 'idle' });\n else if (state.panelOpen) dispatch({ type: 'SET_PANEL', open: false });\n else return false;\n },\n },\n\n /* View */\n {\n id: 'view-toggle',\n group: 'View',\n key: 'p',\n title: 'Original ⇄ Edited',\n description: 'Toggle the page view',\n run: ({ state, dispatch }) => {\n if (state.editor) return false;\n choosePreview(dispatch, !state.preview);\n },\n },\n {\n id: 'panel',\n group: 'View',\n key: 'b',\n title: 'Feedback panel',\n description: 'Open or close it',\n run: ({ state, dispatch }) => {\n dispatch({ type: 'SET_PANEL', open: !state.panelOpen });\n },\n },\n {\n id: 'hide-layer',\n group: 'View',\n key: 'h',\n title: 'Hide / show layer',\n description: 'The whole review layer, for a clean page',\n run: ({ state, dispatch }) => {\n dispatch({ type: 'SET_HIDDEN', on: !state.hidden });\n },\n },\n {\n id: 'cheatsheet',\n group: 'View',\n key: '?',\n title: 'Shortcuts',\n description: 'Show this overview',\n run: ({ state, dispatch }) => {\n dispatch({ type: 'SET_CHEATSHEET', open: !state.cheatsheetOpen });\n },\n },\n\n /* Items */\n {\n id: 'item-next',\n group: 'Items',\n key: 'j',\n title: 'Next item',\n description: 'Jump to the next item',\n run: (ctx) => jumpItem(ctx, 1),\n },\n {\n id: 'item-prev',\n group: 'Items',\n key: 'k',\n title: 'Previous item',\n description: 'Jump to the previous item',\n run: (ctx) => jumpItem(ctx, -1),\n },\n {\n id: 'item-resolve',\n group: 'Items',\n key: 'd',\n title: 'Accept item',\n description: 'Mark it accepted, or reopen it',\n run: ({ state, dispatch }) => {\n const item = state.session?.items.find((entry) => entry.id === state.activeItemId);\n if (!item) {\n toast(dispatch, 'No item selected — use J / K to move between items.', 'info');\n return;\n }\n const status = item.status === 'accepted' ? 'open' : 'accepted';\n dispatch({ type: 'SET_ITEM_STATUS', id: item.id, status });\n toast(dispatch, status === 'accepted' ? 'Marked accepted' : 'Reopened', 'success');\n },\n },\n {\n id: 'item-delete',\n group: 'Items',\n key: 'backspace',\n altKeys: ['delete'],\n title: 'Delete item',\n description: 'Asks for confirmation first',\n run: ({ state, dispatch }) => {\n const item = state.session?.items.find((entry) => entry.id === state.activeItemId);\n if (!item) {\n toast(dispatch, 'No item selected — use J / K to move between items.', 'info');\n return;\n }\n dispatch({\n type: 'SET_CONFIRM',\n confirm: {\n title: 'Delete this item?',\n message:\n state.syncStatus !== 'disabled'\n ? 'The item will be deleted for everyone in this room. This cannot be undone.'\n : 'The feedback item will be removed. This cannot be undone.',\n confirmLabel: 'Delete',\n danger: true,\n onConfirm: () => {\n dispatch({ type: 'DELETE_ITEM', id: item.id });\n toast(dispatch, 'Item deleted', 'info');\n },\n },\n });\n },\n },\n\n /* Session */\n {\n id: 'undo',\n group: 'Session',\n key: 'z',\n mod: 'primary',\n title: 'Undo',\n description: 'Take back the last change',\n run: ({ state, dispatch }) => {\n if (state.undoStack.length === 0) return false;\n dispatch({ type: 'UNDO' });\n toast(dispatch, 'Undone', 'info');\n },\n },\n {\n id: 'export',\n group: 'Session',\n key: 'e',\n mod: 'primary',\n title: 'Export session',\n description: 'Download the feedback as JSON',\n run: ({ state, dispatch }) => {\n if (!state.session || state.session.items.length === 0) {\n toast(dispatch, 'Nothing to export yet.', 'info');\n return;\n }\n downloadSession(state.session);\n toast(dispatch, 'Session exported', 'success');\n },\n },\n {\n id: 'copy-session',\n group: 'Session',\n key: 'e',\n mod: 'primary-shift',\n title: 'Copy session',\n description: 'Session JSON to the clipboard',\n run: ({ state, dispatch }) => {\n const session = state.session;\n if (!session || session.items.length === 0) {\n toast(dispatch, 'Nothing to copy yet.', 'info');\n return;\n }\n void copySessionToClipboard(session).then((ok) =>\n toast(dispatch, ok ? 'Session JSON copied' : 'Clipboard unavailable', ok ? 'success' : 'error'),\n );\n },\n },\n];\n","/**\n * Automatic realtime push of review items to Emblema — no manual step.\n *\n * Watches the session and dispatches changed OPEN items to a locally running\n * Emblema app via the existing v1 intake contract (buildDispatch/sendToEmblema\n * inside sendToEmblema), debounced 500 ms. Silent-fail by design: an\n * unreachable Emblema never blocks or toasts the reviewer — the panel header\n * shows a small status hint and the next item change retries. The session\n * menu's \"Resend all to Emblema\" stays as the manual fallback.\n *\n * Contract limits (v1 is upsert-only, field-frozen): deletions and status\n * flips away from `open` cannot be expressed on this wire — the CLI sync\n * agent's room bridge (`reviewkit-emblema serve`) carries those end to end.\n */\n\nimport { useEffect, useRef } from 'react';\nimport type { Dispatch } from 'react';\nimport type { ReviewItem } from '../schema';\nimport { sendToEmblema } from '../integrations/emblema';\nimport type { Action, ReviewKitConfig, State } from './store';\n\nexport const AUTO_PUSH_DEBOUNCE_MS = 500;\n\nexport function useEmblemaAutoPush(\n state: State,\n dispatch: Dispatch<Action>,\n config: ReviewKitConfig,\n): void {\n const emblema = config.emblema;\n const sessionRef = useRef(state.session);\n sessionRef.current = state.session;\n /** id -> the exact item object last delivered (reference equality = unchanged). */\n const lastSent = useRef(new Map<string, ReviewItem>());\n const inFlight = useRef(false);\n const alive = useRef(true);\n useEffect(() => {\n alive.current = true;\n return () => {\n alive.current = false;\n };\n }, []);\n\n // Fresh closure per render; timers always call the latest via the ref.\n const flushRef = useRef<() => void>(() => {});\n flushRef.current = () => {\n if (!alive.current || !emblema) return;\n const session = sessionRef.current;\n if (!session) return;\n if (inFlight.current) {\n // A push is on the wire — try again after it lands.\n window.setTimeout(() => flushRef.current(), AUTO_PUSH_DEBOUNCE_MS);\n return;\n }\n const changed = session.items.filter(\n (item) => item.status === 'open' && lastSent.current.get(item.id) !== item,\n );\n if (changed.length === 0) return;\n inFlight.current = true;\n dispatch({ type: 'EMBLEMA_PUSH_STATUS', status: 'sending' });\n void sendToEmblema(session, changed, emblema).then((result) => {\n inFlight.current = false;\n if (result.ok) {\n for (const item of changed) lastSent.current.set(item.id, item);\n if (alive.current) dispatch({ type: 'EMBLEMA_PUSH_STATUS', status: 'ok' });\n } else if (alive.current) {\n // 'rejected' = Emblema answered but refused the batch (e.g. an intake\n // older than this contract revision); distinct from unreachable.\n dispatch({ type: 'EMBLEMA_PUSH_STATUS', status: result.reason === 'rejected' ? 'rejected' : 'offline' });\n }\n });\n };\n\n const items = state.session?.items;\n useEffect(() => {\n if (!emblema || !items) return;\n // Forget deleted ids so a later re-add with the same id pushes again.\n for (const id of [...lastSent.current.keys()]) {\n if (!items.some((item) => item.id === id)) lastSent.current.delete(id);\n }\n const dirty = items.some(\n (item) => item.status === 'open' && lastSent.current.get(item.id) !== item,\n );\n if (!dirty) return;\n const timer = window.setTimeout(() => flushRef.current(), AUTO_PUSH_DEBOUNCE_MS);\n return () => window.clearTimeout(timer);\n }, [items, emblema]);\n}\n","/**\n * rkSync — standalone realtime transport for ReviewKit. Protocol v1\n * (see ../PROTOCOL.md). Framework-agnostic: no React, no imports from\n * ReviewKit/src, no dependencies. Uses the platform WebSocket.\n *\n * Offline-first: every public method is safe to call at any time. If the\n * server is unreachable nothing throws, nothing is logged (unless\n * `debug: true`), item mutations queue (bounded) and flush after reconnect.\n */\n\nexport const RK_SYNC_PROTOCOL_VERSION = 1;\n\n/* ------------------------------------------------------------------ */\n/* Types (structural mirror of schema/review-session.schema.json) */\n/* ------------------------------------------------------------------ */\n\n/** A review item as defined by ReviewKit's JSON schema — opaque to transport. */\nexport interface SyncReviewItem {\n id: string;\n createdAt: string;\n type: string;\n status: string;\n route: string;\n target: unknown;\n priority: string;\n note?: string;\n payload?: unknown;\n [extra: string]: unknown;\n}\n\nexport interface SyncUser {\n /** Stable per-browser reviewer id (persist it yourself, e.g. localStorage). */\n id: string;\n name: string;\n /** CSS color used for this reviewer's cursor/badge. */\n color: string;\n}\n\n/** Cursor payload: normalized document fallback (x,y in 0..1) plus an\n * optional element anchor (selector + fractional offset inside its box). */\nexport interface SyncCursor {\n x: number;\n y: number;\n sel?: string;\n ox?: number;\n oy?: number;\n}\n\nexport interface SyncPeer extends SyncUser {\n cursor: SyncCursor | null;\n selecting: string | null;\n typingItemId: string | null;\n}\n\nexport type SyncStatus = 'connecting' | 'online' | 'offline';\n\nexport interface RkSyncHandlers {\n /** Connection state changes. Starts as 'offline' until start(). */\n onStatus?(status: SyncStatus): void;\n /**\n * Full server state after (re)connect. Replace remote-derived state with\n * `items`; local-only items created while offline are re-sent automatically\n * from the queue after this fires.\n */\n onSnapshot?(items: SyncReviewItem[], peers: SyncPeer[], deletedIds?: string[]): void;\n onPeerJoin?(peer: SyncUser): void;\n onPeerLeave?(peerId: string): void;\n onPeerCursor?(peerId: string, cursor: SyncCursor): void;\n onPeerSelecting?(peerId: string, selector: string | null): void;\n onPeerTyping?(peerId: string, itemId: string | null, active: boolean): void;\n /** Ephemeral visual effect from a peer — never persisted anywhere. */\n onPeerEffect?(peerId: string, name: string): void;\n /**\n * Item mutations, broadcast to everyone INCLUDING the original author\n * (your own echoes arrive too — apply idempotently, keyed by id).\n */\n onItemAdd?(item: SyncReviewItem, authorId: string): void;\n onItemUpdate?(id: string, patch: Record<string, unknown>, authorId: string): void;\n onItemStatus?(id: string, status: string, authorId: string): void;\n onItemDelete?(id: string, authorId: string): void;\n}\n\nexport interface RkSyncOptions {\n /** Shared-secret token; connections without it are rejected by the server. */\n token: string;\n user: SyncUser;\n handlers?: RkSyncHandlers;\n /** Default: wss://<current host>/rk-sync (ws:// on http pages). */\n url?: string;\n /** Default: current origin + pathname. */\n room?: { origin: string; route: string };\n /** Log transport events via console.debug. Default false: fully silent. */\n debug?: boolean;\n}\n\nexport interface RkSync {\n readonly status: SyncStatus;\n start(): void;\n /** Clean sign-off: sends bye, closes, stops reconnecting. */\n stop(): void;\n /** Ephemeral presence — dropped when offline (never queued). */\n sendCursor(cursor: SyncCursor): void;\n sendSelecting(selector: string | null): void;\n sendTyping(itemId: string | null, active: boolean): void;\n /** Ephemeral visual effect for the whole room — broadcast only, no storage. */\n sendEffect(name: string): void;\n /** Item mutations — queued while offline (bounded), flushed after snapshot. */\n addItem(item: SyncReviewItem): void;\n updateItem(id: string, patch: Record<string, unknown>): void;\n setStatus(id: string, status: string): void;\n deleteItem(id: string): void;\n}\n\n/* ------------------------------------------------------------------ */\n/* Implementation */\n/* ------------------------------------------------------------------ */\n\nconst BACKOFF_BASE_MS = 1000;\nconst BACKOFF_MAX_MS = 30_000;\nconst PING_INTERVAL_MS = 20_000;\nconst PONG_TIMEOUT_MS = 10_000;\nconst MAX_QUEUE = 300;\nconst CURSOR_MIN_INTERVAL_MS = 66; // ≤ ~15 cursor msgs/s\n\nexport function createRkSync(options: RkSyncOptions): RkSync {\n const handlers = options.handlers ?? {};\n const debug = options.debug === true;\n\n const log = (...args: unknown[]): void => {\n if (debug) {\n try {\n console.debug('[rkSync]', ...args);\n } catch {\n /* ignore */\n }\n }\n };\n\n const defaultUrl = (): string | null => {\n try {\n if (typeof location === 'undefined') return null;\n const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';\n return `${proto}//${location.host}/rk-sync`;\n } catch {\n return null;\n }\n };\n\n const defaultRoom = (): { origin: string; route: string } => {\n try {\n if (typeof location !== 'undefined') {\n return { origin: location.origin, route: location.pathname };\n }\n } catch {\n /* ignore */\n }\n return { origin: 'unknown', route: '/' };\n };\n\n const url = options.url ?? defaultUrl();\n const room = options.room ?? defaultRoom();\n\n let ws: WebSocket | null = null;\n let status: SyncStatus = 'offline';\n let stopped = true;\n let synced = false; // welcome received on the current connection\n let attempts = 0;\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let pingTimer: ReturnType<typeof setInterval> | null = null;\n let pongTimer: ReturnType<typeof setTimeout> | null = null;\n let lastCursorSent = 0;\n const queue: Record<string, unknown>[] = [];\n\n const safely = (fn: (() => void) | undefined): void => {\n try {\n fn?.();\n } catch (err) {\n log('handler threw', err);\n }\n };\n\n const setStatusValue = (next: SyncStatus): void => {\n if (status === next) return;\n status = next;\n safely(() => handlers.onStatus?.(next));\n };\n\n const rawSend = (msg: Record<string, unknown>): boolean => {\n if (!ws || ws.readyState !== 1 /* OPEN */) return false;\n try {\n ws.send(JSON.stringify(msg));\n return true;\n } catch {\n return false;\n }\n };\n\n /** Item mutation: send now, or queue for the next connection. */\n const sendOrQueue = (msg: Record<string, unknown>): void => {\n if (synced && rawSend(msg)) return;\n if (queue.length >= MAX_QUEUE) queue.shift();\n queue.push(msg);\n log('queued', msg.t, `(${queue.length} pending)`);\n };\n\n /** Ephemeral message: best effort, never queued. */\n const sendEphemeral = (msg: Record<string, unknown>): void => {\n if (synced) rawSend(msg);\n };\n\n const clearTimers = (): void => {\n if (reconnectTimer) clearTimeout(reconnectTimer);\n if (pingTimer) clearInterval(pingTimer);\n if (pongTimer) clearTimeout(pongTimer);\n reconnectTimer = pingTimer = pongTimer = null;\n };\n\n const scheduleReconnect = (): void => {\n if (stopped || reconnectTimer) return;\n const backoff = Math.min(BACKOFF_MAX_MS, BACKOFF_BASE_MS * 2 ** attempts);\n const delay = backoff * (0.7 + Math.random() * 0.6); // ±30% jitter\n attempts += 1;\n log(`reconnect in ${Math.round(delay)}ms (attempt ${attempts})`);\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect();\n }, delay);\n };\n\n const startPinging = (): void => {\n pingTimer = setInterval(() => {\n if (!rawSend({ t: 'ping' })) return;\n if (pongTimer) return; // one outstanding pong check at a time\n pongTimer = setTimeout(() => {\n pongTimer = null;\n log('pong timeout — recycling connection');\n try {\n ws?.close();\n } catch {\n /* ignore */\n }\n }, PONG_TIMEOUT_MS);\n }, PING_INTERVAL_MS);\n };\n\n const handleMessage = (data: unknown): void => {\n let msg: Record<string, unknown>;\n try {\n const parsed: unknown = JSON.parse(String(data));\n if (typeof parsed !== 'object' || parsed === null) return;\n msg = parsed as Record<string, unknown>;\n } catch {\n return;\n }\n\n switch (msg.t) {\n case 'welcome': {\n synced = true;\n attempts = 0;\n setStatusValue('online');\n const items = Array.isArray(msg.items) ? (msg.items as SyncReviewItem[]) : [];\n const peers = Array.isArray(msg.peers) ? (msg.peers as SyncPeer[]) : [];\n const deleted = Array.isArray(msg.deleted) ? (msg.deleted as unknown[]).filter((x): x is string => typeof x === 'string') : [];\n log(`welcome: ${items.length} items, ${peers.length} peers, ${deleted.length} tombstones, flushing ${queue.length}`);\n safely(() => handlers.onSnapshot?.(items, peers, deleted));\n while (queue.length > 0) {\n const queued = queue[0];\n if (!rawSend(queued)) break;\n queue.shift();\n }\n break;\n }\n case 'pong':\n if (pongTimer) {\n clearTimeout(pongTimer);\n pongTimer = null;\n }\n break;\n case 'error':\n log('server error:', msg.code, msg.message);\n break;\n case 'presence:join': {\n const peer = msg.peer as SyncUser | undefined;\n if (peer && typeof peer.id === 'string') safely(() => handlers.onPeerJoin?.(peer));\n break;\n }\n case 'presence:leave':\n if (typeof msg.peerId === 'string') {\n const peerId = msg.peerId;\n safely(() => handlers.onPeerLeave?.(peerId));\n }\n break;\n case 'cursor':\n if (typeof msg.peerId === 'string' && typeof msg.x === 'number' && typeof msg.y === 'number') {\n const { peerId, x, y } = msg as { peerId: string; x: number; y: number };\n const cursor: SyncCursor = { x, y };\n if (typeof msg.sel === 'string') cursor.sel = msg.sel;\n if (typeof msg.ox === 'number') cursor.ox = msg.ox;\n if (typeof msg.oy === 'number') cursor.oy = msg.oy;\n safely(() => handlers.onPeerCursor?.(peerId, cursor));\n }\n break;\n case 'fx':\n if (typeof msg.peerId === 'string' && typeof msg.name === 'string') {\n const { peerId, name } = msg as { peerId: string; name: string };\n safely(() => handlers.onPeerEffect?.(peerId, name));\n }\n break;\n case 'selecting':\n if (typeof msg.peerId === 'string') {\n const peerId = msg.peerId;\n const selector = typeof msg.selector === 'string' ? msg.selector : null;\n safely(() => handlers.onPeerSelecting?.(peerId, selector));\n }\n break;\n case 'typing':\n if (typeof msg.peerId === 'string') {\n const peerId = msg.peerId;\n const itemId = typeof msg.itemId === 'string' ? msg.itemId : null;\n const active = msg.active === true;\n safely(() => handlers.onPeerTyping?.(peerId, itemId, active));\n }\n break;\n case 'item:add': {\n const item = msg.item as SyncReviewItem | undefined;\n const authorId = typeof msg.authorId === 'string' ? msg.authorId : '';\n if (item && typeof item.id === 'string') safely(() => handlers.onItemAdd?.(item, authorId));\n break;\n }\n case 'item:update':\n if (typeof msg.id === 'string' && typeof msg.patch === 'object' && msg.patch !== null) {\n const { id } = msg as { id: string };\n const patch = msg.patch as Record<string, unknown>;\n const authorId = typeof msg.authorId === 'string' ? msg.authorId : '';\n safely(() => handlers.onItemUpdate?.(id, patch, authorId));\n }\n break;\n case 'item:status':\n if (typeof msg.id === 'string' && typeof msg.status === 'string') {\n const { id, status: itemStatus } = msg as { id: string; status: string };\n const authorId = typeof msg.authorId === 'string' ? msg.authorId : '';\n safely(() => handlers.onItemStatus?.(id, itemStatus, authorId));\n }\n break;\n case 'item:delete':\n if (typeof msg.id === 'string') {\n const { id } = msg as { id: string };\n const authorId = typeof msg.authorId === 'string' ? msg.authorId : '';\n safely(() => handlers.onItemDelete?.(id, authorId));\n }\n break;\n default:\n break; // unknown types ignored (forward compatibility)\n }\n };\n\n const connect = (): void => {\n if (stopped || !url) return;\n setStatusValue('connecting');\n let socket: WebSocket;\n try {\n socket = new WebSocket(url);\n } catch (err) {\n log('WebSocket constructor failed', err);\n setStatusValue('offline');\n scheduleReconnect();\n return;\n }\n ws = socket;\n\n socket.onopen = () => {\n if (socket !== ws) return;\n log('open — sending hello');\n rawSend({\n t: 'hello',\n v: RK_SYNC_PROTOCOL_VERSION,\n token: options.token,\n room,\n user: { id: options.user.id, name: options.user.name, color: options.user.color },\n });\n startPinging();\n };\n socket.onmessage = (event: MessageEvent) => {\n if (socket === ws) handleMessage(event.data);\n };\n socket.onerror = () => {\n /* swallowed — close handler drives reconnect */\n };\n socket.onclose = (event: CloseEvent) => {\n if (socket !== ws) return;\n ws = null;\n synced = false;\n if (pingTimer) clearInterval(pingTimer);\n if (pongTimer) clearTimeout(pongTimer);\n pingTimer = pongTimer = null;\n setStatusValue('offline');\n log(`closed (${event.code})`);\n // Auth/protocol/origin rejections are permanent for this config — don't hammer.\n if (event.code === 4003 || event.code === 1002 || event.code === 4000 || event.code === 4005) {\n log('permanent close code — reconnect disabled');\n stopped = true;\n return;\n }\n scheduleReconnect();\n };\n };\n\n return {\n get status() {\n return status;\n },\n start() {\n if (!stopped) return;\n stopped = false;\n attempts = 0;\n connect();\n },\n stop() {\n stopped = true;\n clearTimers();\n const socket = ws;\n ws = null;\n synced = false;\n if (socket) {\n try {\n if (socket.readyState === 1) socket.send(JSON.stringify({ t: 'bye' }));\n socket.close(1000);\n } catch {\n /* ignore */\n }\n }\n setStatusValue('offline');\n },\n sendCursor(cursor) {\n const now = Date.now();\n if (now - lastCursorSent < CURSOR_MIN_INTERVAL_MS) return;\n lastCursorSent = now;\n sendEphemeral({ t: 'cursor', ...cursor });\n },\n sendSelecting(selector) {\n sendEphemeral({ t: 'selecting', selector });\n },\n sendTyping(itemId, active) {\n sendEphemeral({ t: 'typing', itemId, active });\n },\n sendEffect(name) {\n sendEphemeral({ t: 'fx', name });\n },\n addItem(item) {\n sendOrQueue({ t: 'item:add', item });\n },\n updateItem(id, patch) {\n sendOrQueue({ t: 'item:update', id, patch });\n },\n setStatus(id, status) {\n sendOrQueue({ t: 'item:status', id, status });\n },\n deleteItem(id) {\n sendOrQueue({ t: 'item:delete', id });\n },\n };\n}\n","/** Stable per-browser reviewer identity, shared by sync and item authorship. */\n\nimport { rkId } from './id';\n\nconst REVIEWER_ID_KEY = 'review-kit:reviewer-id';\n\n/** Reviewer colors — mid-tone steps of the design palette, readable on both schemes. */\nexport const PEER_COLORS = ['#4c58e6', '#0f8a5f', '#b97502', '#dc3d43', '#7c3aed', '#0e7490', '#be185d', '#4d7c0f'];\n\nexport function reviewerId(): string {\n try {\n const stored = window.localStorage.getItem(REVIEWER_ID_KEY);\n if (stored) return stored;\n const fresh = rkId();\n window.localStorage.setItem(REVIEWER_ID_KEY, fresh);\n return fresh;\n } catch {\n return rkId();\n }\n}\n\nexport function colorForReviewer(id: string): string {\n let hash = 0;\n for (let i = 0; i < id.length; i++) hash = (hash * 31 + id.charCodeAt(i)) >>> 0;\n return PEER_COLORS[hash % PEER_COLORS.length];\n}\n\n/** Author stamp stored on every created item (additive schema field). */\nexport function currentAuthor(name: string | undefined): { id: string; name: string; color: string } {\n const id = reviewerId();\n return { id, name: name?.trim() || 'Reviewer', color: colorForReviewer(id) };\n}\n","/**\n * Realtime bridge: wires the store to the rkSync transport (realtime/client).\n *\n * Local → remote: the hook returns a wrapped dispatch. After every action it\n * diffs the previous vs. next item list by id and emits add / update (full\n * item as a LWW patch) / delete — one uniform mirror that also covers undo,\n * clear and import. Remote-originated actions (REMOTE_*, SYNC_*) are never\n * mirrored, so no loops.\n *\n * Remote → local: transport handlers dispatch idempotent REMOTE_* actions\n * keyed by item id; our own server echoes reduce to no-ops (deep-equal\n * guard in the reducer), so nothing flickers and nothing duplicates.\n *\n * Offline-first: without BOTH syncToken and syncUrl nothing here runs and no\n * socket is ever opened (there is no default server); with them, rkSync\n * queues mutations while offline and this bridge re-adds never-synced local\n * items after each snapshot.\n */\n\nimport { useEffect, useMemo, useRef } from 'react';\nimport type { Dispatch } from 'react';\nimport { createRkSync } from '../../realtime/client/rkSync';\nimport type { RkSync, SyncCursor, SyncPeer, SyncReviewItem } from '../../realtime/client/rkSync';\nimport { runEffect, setEffectBroadcaster } from './effectsLazy';\nimport { layerRoot } from './pointer';\nimport { buildSelector, isPluginElement } from './target';\nimport type { ItemStatus, ReviewItem } from '../schema';\nimport { ITEM_STATUSES } from '../schema';\nimport type { Action, PeerCursor, PeerState, ReviewKitConfig, State } from './store';\nimport { toast } from './store';\nimport { colorForReviewer, PEER_COLORS, reviewerId } from './identity';\n\nfunction toPeerState(peer: SyncPeer): PeerState {\n return {\n id: peer.id,\n name: typeof peer.name === 'string' ? peer.name : '',\n color: typeof peer.color === 'string' ? peer.color : PEER_COLORS[0],\n cursor: (peer.cursor as PeerCursor | null) ?? null,\n selecting: peer.selecting ?? null,\n typingItemId: peer.typingItemId ?? null,\n typingActive: peer.typingItemId !== null && peer.typingItemId !== undefined,\n };\n}\n\n/** Module-level bridge so the `/` composer can fire room effects. */\nlet activeSyncRef: RkSync | null = null;\nexport function sendEffectToRoom(name: string): void {\n activeSyncRef?.sendEffect(name);\n}\n\nconst MIRRORED_EXCLUDED = new Set(['SYNC_SNAPSHOT', 'REMOTE_ADD', 'REMOTE_PATCH', 'REMOTE_STATUS', 'REMOTE_DELETE', 'INIT_SESSION']);\n\n/**\n * Items on the wire are opaque JSON from other clients — never trust their\n * shape. Anything without a string id is dropped; `target` is coerced to an\n * object so downstream dereferences (`item.target.textSnippet`,\n * `item.target.anchor`, …) can degrade to \"orphaned\" instead of crashing the\n * whole layer (a single malformed item used to throw on every render).\n */\nfunction sanitizeRemoteItem(raw: SyncReviewItem): ReviewItem | null {\n if (typeof raw !== 'object' || raw === null) return null;\n if (typeof raw.id !== 'string' || raw.id === '') return null;\n const target =\n typeof raw.target === 'object' && raw.target !== null && !Array.isArray(raw.target) ? raw.target : {};\n return { ...raw, target } as unknown as ReviewItem;\n}\n\nexport function useRealtimeSync(\n state: State,\n rawDispatch: Dispatch<Action>,\n config: ReviewKitConfig,\n reducer: (state: State, action: Action) => State,\n): Dispatch<Action> {\n const syncRef = useRef<RkSync | null>(null);\n const stateRef = useRef(state);\n stateRef.current = state;\n const myIdRef = useRef<string>('');\n\n const enabled =\n typeof config.syncToken === 'string' &&\n config.syncToken !== '' &&\n typeof config.syncUrl === 'string' &&\n config.syncUrl !== '';\n const author = state.session?.author ?? '';\n const hasSession = state.session !== null;\n\n // Transport lifecycle — starts once the session exists, restarts on rename.\n useEffect(() => {\n if (!enabled || !hasSession) return;\n const id = reviewerId();\n myIdRef.current = id;\n const dispatch = rawDispatch;\n\n const sync = createRkSync({\n token: config.syncToken as string,\n url: config.syncUrl as string,\n user: { id, name: author || 'Reviewer', color: colorForReviewer(id) },\n handlers: {\n onStatus: (status) => dispatch({ type: 'SYNC_STATUS', status }),\n onSnapshot: (items, peers, deletedIds = []) => {\n const safeItems = items.map(sanitizeRemoteItem).filter((item): item is ReviewItem => item !== null);\n dispatch({ type: 'SYNC_SNAPSHOT', items: safeItems });\n // Ids the room has deleted for good: purge local copies (deletion\n // done while we were away must reach us too)…\n const deleted = new Set(deletedIds);\n for (const id of deletedIds) dispatch({ type: 'REMOTE_DELETE', id });\n dispatch({ type: 'PEERS_SET', peers: peers.filter((peer) => peer.id !== id).map(toPeerState) });\n // …and share persisted local items the room has never seen —\n // except tombstoned ones, which must NEVER be uploaded back.\n const serverIds = new Set(items.map((item) => item.id));\n for (const item of stateRef.current.session?.items ?? []) {\n if (!serverIds.has(item.id) && !deleted.has(item.id)) sync.addItem(item as SyncReviewItem);\n }\n },\n onPeerJoin: (peer) =>\n dispatch({\n type: 'PEER_JOIN',\n peer: toPeerState({ ...peer, cursor: null, selecting: null, typingItemId: null }),\n }),\n onPeerLeave: (peerId) => dispatch({ type: 'PEER_LEAVE', peerId }),\n onPeerCursor: (peerId, cursor) => dispatch({ type: 'PEER_CURSOR', peerId, cursor: cursor as PeerCursor }),\n onPeerEffect: (_peerId, name) => {\n runEffect(name, layerRoot);\n },\n onPeerSelecting: (peerId, selector) => dispatch({ type: 'PEER_SELECTING', peerId, selector }),\n onPeerTyping: (peerId, itemId, active) => dispatch({ type: 'PEER_TYPING', peerId, itemId, active }),\n onItemAdd: (item, authorId) => {\n const safeItem = sanitizeRemoteItem(item);\n if (!safeItem) return;\n const isNew = !stateRef.current.session?.items.some((existing) => existing.id === item.id);\n dispatch({ type: 'REMOTE_ADD', item: safeItem });\n if (authorId !== id && isNew) {\n const peer = stateRef.current.peers.find((entry) => entry.id === authorId);\n toast(dispatch, `${peer?.name || 'Someone'} added a ${typeof item.type === 'string' ? item.type : 'change'}`, 'info');\n }\n },\n onItemUpdate: (itemId, patch) => {\n // A shallow LWW patch may carry `target` too — never let a peer\n // replace a valid target with a non-object.\n const safePatch = { ...patch };\n if ('target' in safePatch && (typeof safePatch.target !== 'object' || safePatch.target === null || Array.isArray(safePatch.target))) {\n delete safePatch.target;\n }\n dispatch({ type: 'REMOTE_PATCH', id: itemId, patch: safePatch });\n },\n onItemStatus: (itemId, status) => {\n if ((ITEM_STATUSES as readonly string[]).includes(status)) {\n dispatch({ type: 'REMOTE_STATUS', id: itemId, status: status as ItemStatus });\n }\n },\n onItemDelete: (itemId) => dispatch({ type: 'REMOTE_DELETE', id: itemId }),\n },\n });\n syncRef.current = sync;\n activeSyncRef = sync;\n setEffectBroadcaster((name) => sync.sendEffect(name));\n sync.start();\n return () => {\n syncRef.current = null;\n if (activeSyncRef === sync) activeSyncRef = null;\n setEffectBroadcaster(null);\n sync.stop();\n dispatch({ type: 'SYNC_STATUS', status: 'disabled' });\n dispatch({ type: 'PEERS_SET', peers: [] });\n };\n }, [enabled, hasSession, config.syncToken, config.syncUrl, author, rawDispatch]);\n\n // Wrapped dispatch: apply locally, then mirror the resulting item diff.\n const wrapped = useMemo<Dispatch<Action>>(() => {\n return (action: Action) => {\n const prev = stateRef.current;\n rawDispatch(action);\n const sync = syncRef.current;\n if (!sync || MIRRORED_EXCLUDED.has(action.type)) return;\n if (!prev.session) return;\n const next = reducer(prev, action);\n // Keep the ref current for same-tick follow-up dispatches (the render\n // that would refresh it hasn't happened yet).\n stateRef.current = next;\n if (!next.session || next.session.items === prev.session.items) return;\n\n const prevById = new Map(prev.session.items.map((item) => [item.id, item]));\n const nextById = new Map(next.session.items.map((item) => [item.id, item]));\n for (const [id, item] of nextById) {\n const before = prevById.get(id);\n if (!before) sync.addItem(item as SyncReviewItem);\n else if (before !== item) sync.updateItem(id, item as unknown as Record<string, unknown>);\n }\n for (const id of prevById.keys()) {\n if (!nextById.has(id)) sync.deleteItem(id);\n }\n };\n }, [rawDispatch, reducer]);\n\n // Ephemeral presence: element-anchored cursor (transport throttles),\n // selection, typing. The anchor (selector + fractional offset in the\n // element's box) lets receivers place the cursor on the same piece of\n // CONTENT regardless of their viewport width, zoom, DPR or scroll; the\n // normalized document fraction is only a degraded fallback.\n useEffect(() => {\n if (!enabled) return;\n let lastEl: Element | null = null;\n let lastSel: string | null = null;\n const onPointerMove = (event: PointerEvent) => {\n const doc = document.documentElement;\n const cursor: SyncCursor = {\n x: (event.clientX + window.scrollX) / Math.max(1, doc.scrollWidth),\n y: (event.clientY + window.scrollY) / Math.max(1, doc.scrollHeight),\n };\n const el = document.elementFromPoint(event.clientX, event.clientY);\n if (el instanceof HTMLElement && !isPluginElement(el) && el !== document.body && el !== doc) {\n if (el !== lastEl) {\n lastEl = el;\n lastSel = buildSelector(el);\n }\n const rect = el.getBoundingClientRect();\n if (lastSel && rect.width > 0 && rect.height > 0) {\n cursor.sel = lastSel;\n cursor.ox = (event.clientX - rect.left) / rect.width;\n cursor.oy = (event.clientY - rect.top) / rect.height;\n }\n }\n syncRef.current?.sendCursor(cursor);\n };\n document.addEventListener('pointermove', onPointerMove, { passive: true });\n return () => document.removeEventListener('pointermove', onPointerMove);\n }, [enabled]);\n\n const selectingSelector = state.editor?.target.selector ?? state.selection?.target.selector ?? null;\n useEffect(() => {\n if (!enabled) return;\n syncRef.current?.sendSelecting(selectingSelector);\n }, [enabled, selectingSelector]);\n\n const editorOpen = state.editor !== null;\n useEffect(() => {\n if (!enabled) return;\n syncRef.current?.sendTyping(null, editorOpen);\n }, [enabled, editorOpen]);\n\n return enabled ? wrapped : rawDispatch;\n}\n","/**\n * Shared free-drag position logic for floating chrome (toolbar, badge):\n * one persistence format, one viewport clamp, one edge-snap — so every\n * draggable behaves identically (localStorage, resize clamp, reset).\n */\n\nexport interface Pos {\n x: number;\n y: number;\n}\n\nconst MARGIN = 8;\nconst SNAP = 14;\n\nexport function readStoredPos(key: string): Pos | null {\n try {\n const raw = window.localStorage.getItem(key);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n typeof (parsed as Pos).x === 'number' &&\n typeof (parsed as Pos).y === 'number'\n ) {\n return parsed as Pos;\n }\n } catch {\n /* ignore */\n }\n return null;\n}\n\nexport function storePos(key: string, pos: Pos | null): void {\n try {\n if (pos === null) window.localStorage.removeItem(key);\n else window.localStorage.setItem(key, JSON.stringify(pos));\n } catch {\n /* ignore */\n }\n}\n\n/** Keep the element fully inside the viewport. */\nexport function clampPos(x: number, y: number, width: number, height: number): Pos {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n return {\n x: Math.min(Math.max(x, MARGIN), Math.max(MARGIN, vw - width - MARGIN)),\n y: Math.min(Math.max(y, MARGIN), Math.max(MARGIN, vh - height - MARGIN)),\n };\n}\n\n/** Clamp + magnet-snap to the edges and the horizontal center (drag release). */\nexport function snapClampPos(x: number, y: number, width: number, height: number): Pos {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const centerX = (vw - width) / 2;\n if (Math.abs(x - centerX) < SNAP) x = centerX;\n if (x < MARGIN + SNAP) x = MARGIN;\n if (x > vw - width - MARGIN - SNAP) x = vw - width - MARGIN;\n if (y < 16 + SNAP) y = 16;\n if (y > vh - height - 16 - SNAP) y = vh - height - 16;\n return clampPos(x, y, width, height);\n}\n","/**\n * Floating badge pill. Freely draggable with the SAME shared logic as the\n * toolbar (dragPosition.ts): position persists in localStorage, clamps back\n * into the viewport on resize, edge-snaps on release, double-click resets to\n * the default corner. The panel opens on click (a <6px move is a click).\n */\n\nimport { useLayoutEffect, useRef, useState } from 'react';\nimport type { PointerEvent as ReactPointerEvent } from 'react';\nimport { clampPos, readStoredPos, snapClampPos, storePos } from '../dragPosition';\nimport type { Pos } from '../dragPosition';\nimport type { BadgeCorner } from '../store';\nimport { useConfig, useDispatch, useStore } from '../store';\n\nconst POS_KEY = 'review-kit:badge-pos';\nconst DRAG_THRESHOLD = 6;\n\n/** Default resting spot: ~50px off the corner on desktop; tighter on small\n * screens, and lifted above the bottom-centered toolbar so they never\n * overlap on a phone. A stored (dragged) position always wins over this. */\nfunction defaultPos(corner: BadgeCorner, width: number, height: number): Pos {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const small = vw < 480;\n const edgeX = small ? 12 : 50;\n const edgeBottom = small ? 72 : 50;\n return {\n x: corner.includes('left') ? edgeX : vw - width - edgeX,\n y: corner.includes('top') ? 16 : vh - height - edgeBottom,\n };\n}\n\n/** Which half the badge sits in decides the panel's side. */\nfunction cornerFor(pos: Pos, width: number, height: number): BadgeCorner {\n const horizontal = pos.x + width / 2 < window.innerWidth / 2 ? 'left' : 'right';\n const vertical = pos.y + height / 2 < window.innerHeight / 2 ? 'top' : 'bottom';\n return `${vertical}-${horizontal}` as BadgeCorner;\n}\n\nexport function Badge() {\n const { session, mode, panelOpen } = useStore();\n const dispatch = useDispatch();\n const config = useConfig();\n const ref = useRef<HTMLButtonElement | null>(null);\n // Click opens the panel only after a short beat — a second click within it\n // is a double-click and resets the position instead. Without the delay the\n // first click would unmount the badge and the reset would be unreachable.\n const clickTimer = useRef<number | null>(null);\n const lastClickAt = useRef(0);\n const [pos, setPos] = useState<Pos | null>(() => readStoredPos(POS_KEY));\n const [dragging, setDragging] = useState(false);\n const drag = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n baseX: number;\n baseY: number;\n moved: boolean;\n lastDx: number;\n lastDy: number;\n } | null>(null);\n\n const openCount = session?.items.filter((item) => item.status === 'open').length ?? 0;\n\n const applyPos = (next: Pos | null, persist: boolean) => {\n setPos(next);\n if (persist) storePos(POS_KEY, next);\n const el = ref.current;\n if (el) {\n const effective = next ?? defaultPos(config.position ?? 'bottom-right', el.offsetWidth, el.offsetHeight);\n dispatch({ type: 'SET_CORNER', corner: cornerFor(effective, el.offsetWidth, el.offsetHeight) });\n }\n };\n\n // Park: stored position (clamped) or the configured default corner.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || dragging) return;\n const park = () => {\n const stored = readStoredPos(POS_KEY);\n const target = stored\n ? clampPos(stored.x, stored.y, el.offsetWidth, el.offsetHeight)\n : defaultPos(config.position ?? 'bottom-right', el.offsetWidth, el.offsetHeight);\n el.style.left = '0px';\n el.style.top = '0px';\n el.style.translate = `${target.x}px ${target.y}px`;\n dispatch({ type: 'SET_CORNER', corner: cornerFor(target, el.offsetWidth, el.offsetHeight) });\n };\n park();\n window.addEventListener('resize', park);\n return () => window.removeEventListener('resize', park);\n }, [pos, dragging, panelOpen, config.position, dispatch]);\n\n const onPointerDown = (event: ReactPointerEvent<HTMLButtonElement>) => {\n const el = ref.current;\n if (!el || event.button !== 0) return;\n const rect = el.getBoundingClientRect();\n const state = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n baseX: rect.left,\n baseY: rect.top,\n moved: false,\n lastDx: 0,\n lastDy: 0,\n };\n drag.current = state;\n const killDrag = (dragEvent: Event) => dragEvent.preventDefault();\n const onMove = (move: PointerEvent) => {\n const node = ref.current;\n if (!node || move.pointerId !== state.pointerId) return;\n const dx = move.clientX - state.startX;\n const dy = move.clientY - state.startY;\n if (!state.moved) {\n if (Math.hypot(dx, dy) < DRAG_THRESHOLD) return;\n state.moved = true;\n setDragging(true);\n try {\n node.setPointerCapture(state.pointerId);\n } catch {\n /* ignore */\n }\n }\n move.preventDefault();\n state.lastDx = dx;\n state.lastDy = dy;\n node.style.left = '0px';\n node.style.top = '0px';\n node.style.translate = `${state.baseX + dx}px ${state.baseY + dy}px`;\n };\n const onUp = (up: PointerEvent) => {\n if (up.pointerId !== state.pointerId) return;\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', onUp);\n window.removeEventListener('pointercancel', onUp);\n window.removeEventListener('dragstart', killDrag, true);\n drag.current = null;\n const node = ref.current;\n if (!node) return;\n if (!state.moved) {\n const now = Date.now();\n if (now - lastClickAt.current < 300) {\n if (clickTimer.current !== null) window.clearTimeout(clickTimer.current);\n clickTimer.current = null;\n lastClickAt.current = 0;\n applyPos(null, true);\n return;\n }\n lastClickAt.current = now;\n clickTimer.current = window.setTimeout(() => {\n clickTimer.current = null;\n dispatch({ type: 'SET_PANEL', open: !panelOpen });\n }, 280);\n return;\n }\n setDragging(false);\n const snapped = snapClampPos(\n state.baseX + state.lastDx,\n state.baseY + state.lastDy,\n node.offsetWidth,\n node.offsetHeight,\n );\n node.style.translate = `${snapped.x}px ${snapped.y}px`;\n applyPos(snapped, true);\n };\n window.addEventListener('pointermove', onMove, { passive: false });\n window.addEventListener('pointerup', onUp);\n window.addEventListener('pointercancel', onUp);\n window.addEventListener('dragstart', killDrag, true);\n };\n\n // The open panel owns the badge's corner (its footer sits right under it) —\n // hide the badge; the panel has its own close button and Esc.\n if (panelOpen) return null;\n\n const classes = ['rk-badge', dragging ? 'rk-dragging' : '', mode === 'pick' ? 'rk-picking' : '']\n .filter(Boolean)\n .join(' ');\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={classes}\n aria-label={`Review kit — ${openCount} open item${openCount === 1 ? '' : 's'}. Click to open the panel, drag to move, double-click to reset position.`}\n aria-expanded={panelOpen}\n onPointerDown={onPointerDown}\n >\n <span className=\"rk-badge-dot\" />\n Review\n {openCount > 0 && <span className=\"rk-badge-count\">{openCount}</span>}\n </button>\n );\n}\n","/** Inline SVG icon set — 16px grid, 1.5 stroke, round caps, optically aligned. */\n\nimport type { ReactNode, SVGProps } from 'react';\n\ntype IconProps = SVGProps<SVGSVGElement> & { size?: number };\n\nfunction Base({ size = 16, children, ...rest }: IconProps & { children: ReactNode }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n {...rest}\n >\n {children}\n </svg>\n );\n}\n\nexport function IconText(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M3.5 4.5V3h9v1.5\" />\n <path d=\"M8 3v10\" />\n <path d=\"M6 13h4\" />\n </Base>\n );\n}\n\nexport function IconImage(props: IconProps) {\n return (\n <Base {...props}>\n <rect x=\"2.25\" y=\"3.25\" width=\"11.5\" height=\"9.5\" rx=\"1.5\" />\n <circle cx=\"5.75\" cy=\"6.5\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <path d=\"M2.5 11l3.2-3.2a1 1 0 0 1 1.4 0L10 10.7l1.4-1.4a1 1 0 0 1 1.4 0l.95.95\" />\n </Base>\n );\n}\n\nexport function IconComment(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M13.5 7.6c0 2.7-2.46 4.6-5.5 4.6-.6 0-1.18-.07-1.72-.2L3.5 13.5l.55-2.2C3.06 10.45 2.5 9.1 2.5 7.6 2.5 4.9 4.96 3 8 3s5.5 1.9 5.5 4.6Z\" />\n </Base>\n );\n}\n\nexport function IconTrash(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M2.75 4.25h10.5\" />\n <path d=\"M5.5 4.25V3.4c0-.63.51-1.15 1.15-1.15h2.7c.64 0 1.15.52 1.15 1.15v.85\" />\n <path d=\"M4.25 4.5l.55 8.05c.04.62.56 1.1 1.18 1.1h4.04c.62 0 1.14-.48 1.18-1.1l.55-8.05\" />\n <path d=\"M6.6 7v3.8M9.4 7v3.8\" />\n </Base>\n );\n}\n\nexport function IconMove(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M8 2.5v11\" />\n <path d=\"M5.25 5.25 8 2.5l2.75 2.75\" />\n <path d=\"M5.25 10.75 8 13.5l2.75-2.75\" />\n </Base>\n );\n}\n\nexport function IconStyle(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M11.2 2.6a1.6 1.6 0 0 1 2.26 2.26L7.1 11.2l-3.1.85.84-3.1 6.36-6.35Z\" />\n <path d=\"M9.6 4.2l2.2 2.2\" />\n </Base>\n );\n}\n\nexport function IconClose(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M4 4l8 8M12 4l-8 8\" />\n </Base>\n );\n}\n\nexport function IconChevronRight(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M6 3.5 10.5 8 6 12.5\" />\n </Base>\n );\n}\n\nexport function IconSearch(props: IconProps) {\n return (\n <Base {...props}>\n <circle cx=\"7\" cy=\"7\" r=\"4.25\" />\n <path d=\"M10.3 10.3 13.5 13.5\" />\n </Base>\n );\n}\n\nexport function IconDownload(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M8 2.5v7.5\" />\n <path d=\"M5.25 7.5 8 10.25 10.75 7.5\" />\n <path d=\"M3 11.5v1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1\" />\n </Base>\n );\n}\n\nexport function IconUpload(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M8 10V2.75\" />\n <path d=\"M5.25 5.25 8 2.5l2.75 2.75\" />\n <path d=\"M3 11.5v1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1\" />\n </Base>\n );\n}\n\nexport function IconCopyClipboard(props: IconProps) {\n return (\n <Base {...props}>\n <rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <path d=\"M10.5 5.5v-2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2\" />\n </Base>\n );\n}\n\nexport function IconUndo(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M3 6.5h6.5a3.5 3.5 0 0 1 0 7H6\" />\n <path d=\"M5.5 4 3 6.5 5.5 9\" />\n </Base>\n );\n}\n\nexport function IconCheck(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M3 8.5 6.5 12 13 4.5\" />\n </Base>\n );\n}\n\nexport function IconWarning(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M8 2.75 14.5 13.5h-13L8 2.75Z\" />\n <path d=\"M8 7v3\" />\n <circle cx=\"8\" cy=\"11.9\" r=\"0.55\" fill=\"currentColor\" stroke=\"none\" />\n </Base>\n );\n}\n\nexport function IconTarget(props: IconProps) {\n return (\n <Base {...props}>\n <circle cx=\"8\" cy=\"8\" r=\"5.5\" />\n <circle cx=\"8\" cy=\"8\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <path d=\"M8 1.5v2M8 12.5v2M1.5 8h2M12.5 8h2\" />\n </Base>\n );\n}\n\nexport function IconKeyboard(props: IconProps) {\n return (\n <Base {...props}>\n <rect x=\"2\" y=\"4.5\" width=\"12\" height=\"7.5\" rx=\"1.5\" />\n <path d=\"M4.5 7h.01M7 7h.01M9.5 7h.01M12 7h.01M5 9.5h6\" />\n </Base>\n );\n}\n\nexport function IconGear(props: IconProps) {\n return (\n <Base {...props}>\n <circle cx=\"8\" cy=\"8\" r=\"2.1\" />\n <path d=\"M8 1.8v2M8 12.2v2M1.8 8h2M12.2 8h2M3.6 3.6l1.4 1.4M11 11l1.4 1.4M12.4 3.6 11 5M5 11l-1.4 1.4\" />\n </Base>\n );\n}\n\nexport function IconFilter(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M2.5 4h11M4.5 8h7M6.5 12h3\" />\n </Base>\n );\n}\n\nexport function IconLink(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M6.5 9.5 9.5 6.5\" />\n <path d=\"M7.25 4.9 8.4 3.75a2.4 2.4 0 0 1 3.4 0 2.4 2.4 0 0 1 0 3.4L10.65 8.3\" />\n <path d=\"M8.75 11.1 7.6 12.25a2.4 2.4 0 0 1-3.4 0 2.4 2.4 0 0 1 0-3.4L5.35 7.7\" />\n </Base>\n );\n}\n\nexport function IconUnlink(props: IconProps) {\n return (\n <Base {...props}>\n <path d=\"M6.5 4.5v-2M9.5 13.5v-2M4.5 6.5h-2M13.5 9.5h-2\" />\n <path d=\"M6 10 3.5 12.5M10 6l2.5-2.5\" />\n </Base>\n );\n}\n\nexport function iconForType(type: string, size = 14): ReactNode {\n switch (type) {\n case 'copy':\n return <IconText size={size} />;\n case 'image':\n return <IconImage size={size} />;\n case 'comment':\n return <IconComment size={size} />;\n case 'delete':\n return <IconTrash size={size} />;\n case 'move':\n return <IconMove size={size} />;\n case 'style':\n return <IconStyle size={size} />;\n default:\n return <IconTarget size={size} />;\n }\n}\n","/** Keyboard shortcut cheatsheet dialog — rendered from the shortcut registry. */\n\nimport { displayKeys, IS_MAC, SHORTCUTS } from '../shortcuts';\nimport { useDispatch, useStore } from '../store';\nimport { IconClose, IconKeyboard } from './icons';\n\nconst GROUPS: Array<'Tools' | 'View' | 'Items' | 'Session'> = ['Tools', 'View', 'Items', 'Session'];\n\nexport function CheatSheet() {\n const { cheatsheetOpen } = useStore();\n const dispatch = useDispatch();\n if (!cheatsheetOpen) return null;\n\n const close = () => dispatch({ type: 'SET_CHEATSHEET', open: false });\n\n return (\n <>\n <div className=\"rk-backdrop\" onClick={close} />\n <div className=\"rk-modal rk-cheatsheet\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Keyboard shortcuts\">\n <div className=\"rk-cheat-head\">\n <span className=\"rk-cheat-head-icon\">\n <IconKeyboard size={15} />\n </span>\n <span className=\"rk-cheat-title\">Keyboard shortcuts</span>\n <span style={{ flex: 1 }} />\n <button type=\"button\" className=\"rk-icon-btn\" aria-label=\"Close\" onClick={close} autoFocus>\n <IconClose size={13} />\n </button>\n </div>\n <div className=\"rk-cheat-grid\">\n {GROUPS.map((group) => (\n <section key={group} className=\"rk-cheat-group\">\n <h3 className=\"rk-cheat-group-title\">{group}</h3>\n {SHORTCUTS.filter((def) => def.group === group).map((def) => (\n <div key={def.id} className=\"rk-shortcut-row\">\n <span className=\"rk-shortcut-text\">\n <span className=\"rk-shortcut-title\">{def.title}</span>\n <span className=\"rk-shortcut-desc\">{def.description}</span>\n </span>\n <span className=\"rk-keys\">\n {displayKeys(def, IS_MAC).map((key) => (\n <span key={key} className=\"rk-kbd\">\n {key}\n </span>\n ))}\n </span>\n </div>\n ))}\n </section>\n ))}\n </div>\n <div className=\"rk-egg\">Psst — the “/” box knows a few tricks it won’t tell you about.</div>\n </div>\n </>\n );\n}\n","/**\n * \"Connect to Emblema\" — pairing-key management (contract v2).\n * Talks to the local sync agent (`reviewkit-emblema serve`) over its\n * localhost management API; the key itself is generated and stored by the\n * agent in the project's .reviewkit/emblema-sync.json.\n */\n\nimport { useEffect, useState } from 'react';\nimport {\n fetchSyncKey,\n fetchSyncState,\n generateSyncKey,\n revokeSyncKey,\n} from '../../integrations/emblema';\nimport type { EmblemaSyncState } from '../../integrations/emblema';\nimport { toast, useDispatch, useStore } from '../store';\nimport { IconClose } from './icons';\n\n/** The key is a secret: only ever render it shortened (emk_…last4). */\nfunction shortKey(key: string): string {\n return `${key.slice(0, 4)}…${key.slice(-4)}`;\n}\n\nfunction ago(iso: string | null): string {\n if (!iso) return 'never';\n const s = Math.max(0, (Date.now() - Date.parse(iso)) / 1000);\n if (s < 45) return 'just now';\n if (s < 3600) return `${Math.round(s / 60)} min ago`;\n if (s < 86400) return `${Math.round(s / 3600)} h ago`;\n return new Date(iso).toLocaleString();\n}\n\nexport function EmblemaConnect() {\n const { emblemaConnectOpen } = useStore();\n const dispatch = useDispatch();\n const [state, setState] = useState<EmblemaSyncState | null | 'loading'>('loading');\n const [key, setKey] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n\n const refresh = () => {\n setState('loading');\n void fetchSyncState().then(setState);\n };\n useEffect(() => {\n if (emblemaConnectOpen) {\n setKey(null);\n refresh();\n }\n }, [emblemaConnectOpen]);\n\n if (!emblemaConnectOpen) return null;\n const close = () => dispatch({ type: 'SET_EMBLEMA_CONNECT', open: false });\n\n const copy = async (value: string) => {\n try {\n await navigator.clipboard.writeText(value);\n toast(dispatch, 'Pairing key copied — paste it into Emblema', 'success');\n } catch {\n toast(dispatch, 'Copy failed — select the key manually', 'error');\n }\n };\n\n const generate = (label: string) => {\n setBusy(true);\n void generateSyncKey()\n .then(async (fresh) => {\n if (fresh) {\n setKey(fresh);\n await copy(fresh);\n toast(dispatch, `${label} — the previous key no longer works`, 'info');\n } else {\n toast(dispatch, 'The local sync agent did not answer.', 'error');\n }\n refresh();\n })\n .finally(() => setBusy(false));\n };\n\n return (\n <>\n <div className=\"rk-backdrop\" onClick={close} />\n <div className=\"rk-modal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Connect to Emblema\">\n <div className=\"rk-modal-body\">\n <div className=\"rk-modal-title\" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n Connect to Emblema\n <span style={{ flex: 1 }} />\n <button type=\"button\" className=\"rk-icon-btn\" aria-label=\"Close\" onClick={close} autoFocus>\n <IconClose size={13} />\n </button>\n </div>\n\n {state === 'loading' && <div className=\"rk-modal-text\">Looking for the local sync agent…</div>}\n\n {state === null && (\n <div className=\"rk-modal-text\">\n The local sync agent isn&apos;t running. In the project repo run:\n <code className=\"rk-connect-cmd\">npx @satanwagen/reviewkit-cli init --origin {window.location.origin}</code>\n <code className=\"rk-connect-cmd\">npx @satanwagen/reviewkit-cli serve</code>\n then reopen this dialog.\n </div>\n )}\n\n {state !== null && state !== 'loading' && (\n <>\n <div className=\"rk-modal-text\">\n Project <strong>{state.name}</strong> <span className=\"rk-connect-id\">({state.id})</span>\n <br />\n Status:{' '}\n {state.revoked ? (\n <span className=\"rk-connect-bad\">revoked — generate a new key to reconnect</span>\n ) : (\n <>paired key active</>\n )}\n <br />\n Last confirmed by Emblema: <strong>{ago(state.lastAck)}</strong> · {state.findings} finding\n {state.findings === 1 ? '' : 's'} tracked\n </div>\n {key && (\n <code\n className=\"rk-connect-key\"\n title=\"The full key was copied to the clipboard — paste it into Emblema. Use Copy key to copy it again.\"\n >\n {shortKey(key)}\n </code>\n )}\n <div className=\"rk-connect-actions\">\n <button\n type=\"button\"\n className=\"rk-btn rk-btn-primary\"\n disabled={busy}\n title=\"Issue a fresh pairing key — any previous key stops working immediately\"\n onClick={() => generate(state.revoked || !state.paired ? 'Key generated' : 'Key rotated')}\n >\n {state.revoked ? 'Generate new key' : 'New key (rotate)'}\n </button>\n <button\n type=\"button\"\n className=\"rk-btn rk-btn-ghost\"\n disabled={busy || state.revoked}\n onClick={() => {\n void fetchSyncKey().then((current) => {\n if (current) {\n setKey(current);\n void copy(current);\n } else toast(dispatch, 'No active key — generate one first.', 'error');\n });\n }}\n >\n Copy key\n </button>\n <span style={{ flex: 1 }} />\n <button\n type=\"button\"\n className=\"rk-btn rk-btn-ghost rk-connect-revoke\"\n disabled={busy || state.revoked}\n title=\"Delete the pairing key — Emblema loses access until a new key is generated\"\n onClick={() => {\n void revokeSyncKey().then((ok) => {\n toast(dispatch, ok ? 'Pairing revoked — Emblema is disconnected' : 'Revoke failed', ok ? 'info' : 'error');\n setKey(null);\n refresh();\n });\n }}\n >\n Delete key (revoke)\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n </>\n );\n}\n","/** First-run coach mark: explains pick mode, captures the reviewer's name. */\n\nimport { useState } from 'react';\nimport { useConfig, useDispatch, useStore } from '../store';\nimport { IconTarget } from './icons';\n\nexport const COACH_KEY = 'review-kit:coach-dismissed';\n\nexport function CoachMark() {\n const { coachOpen, session } = useStore();\n const dispatch = useDispatch();\n const config = useConfig();\n const [name, setName] = useState(session?.author ?? config.defaultAuthor ?? '');\n\n if (!coachOpen) return null;\n\n const done = (startPicking: boolean) => {\n if (name.trim() !== '') dispatch({ type: 'SET_AUTHOR', author: name.trim() });\n dispatch({ type: 'SET_COACH', open: false });\n try {\n window.localStorage.setItem(COACH_KEY, '1');\n } catch {\n /* ignore */\n }\n if (startPicking) dispatch({ type: 'SET_MODE', mode: 'pick' });\n };\n\n return (\n <div className=\"rk-coach\" role=\"dialog\" aria-label=\"Welcome to review mode\">\n <div className=\"rk-coach-accent\" />\n <div className=\"rk-coach-body\">\n <div className=\"rk-modal-title\" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <IconTarget size={16} /> Review mode\n </div>\n <div className=\"rk-modal-text\">\n Click anything on the page to suggest a change — rewrite the copy, swap an image, or\n leave a note. The live site stays untouched; everything you add is collected for the\n team.\n </div>\n <div className=\"rk-coach-keys\" aria-label=\"Key shortcuts\">\n <span><span className=\"rk-kbd\">T</span> rewrite</span>\n <span><span className=\"rk-kbd\">C</span> comment</span>\n <span><span className=\"rk-kbd\">I</span> image</span>\n <span><span className=\"rk-kbd\">V</span> select</span>\n <span><span className=\"rk-kbd\">?</span> all shortcuts</span>\n </div>\n <div>\n <label className=\"rk-label\" htmlFor=\"rk-author\">\n Your name\n </label>\n <input\n id=\"rk-author\"\n className=\"rk-input\"\n placeholder=\"e.g. Marta from marketing\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') done(true);\n }}\n />\n </div>\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8, marginTop: 4 }}>\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={() => done(false)}>\n Not now\n </button>\n <button type=\"button\" className=\"rk-btn rk-btn-primary\" onClick={() => done(true)}>\n Start reviewing\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/** Designed confirm dialog — never window.confirm. */\n\nimport { useEffect, useRef } from 'react';\nimport { useDispatch, useStore } from '../store';\n\nexport function ConfirmHost() {\n const { confirm } = useStore();\n const dispatch = useDispatch();\n const cancelRef = useRef<HTMLButtonElement | null>(null);\n\n useEffect(() => {\n if (confirm) cancelRef.current?.focus();\n }, [confirm]);\n\n if (!confirm) return null;\n\n const close = () => dispatch({ type: 'SET_CONFIRM', confirm: null });\n\n return (\n <>\n <div className=\"rk-backdrop\" onClick={close} />\n <div className=\"rk-modal\" role=\"alertdialog\" aria-modal=\"true\" aria-label={confirm.title}>\n <div className=\"rk-modal-body\">\n <div className=\"rk-modal-title\">{confirm.title}</div>\n <div className=\"rk-modal-text\">{confirm.message}</div>\n </div>\n <div className=\"rk-modal-actions\">\n <button ref={cancelRef} type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={close}>\n Cancel\n </button>\n <button\n type=\"button\"\n className={`rk-btn ${confirm.danger ? 'rk-btn-danger' : 'rk-btn-primary'}`}\n onClick={() => {\n const action = confirm.onConfirm;\n close();\n action();\n }}\n >\n {confirm.confirmLabel}\n </button>\n </div>\n </div>\n </>\n );\n}\n","/** Tiny anchored-positioning helper (flip + shift). No floating-ui. */\n\nexport type Side = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface ComputedPosition {\n x: number;\n y: number;\n side: Side;\n}\n\ninterface Options {\n side?: Side;\n /** Gap between anchor and floating element. */\n offset?: number;\n /** Minimum distance from viewport edges. */\n padding?: number;\n}\n\ninterface Size {\n width: number;\n height: number;\n}\n\nfunction place(anchor: DOMRect, size: Size, side: Side, offset: number): { x: number; y: number } {\n switch (side) {\n case 'top':\n return { x: anchor.left + anchor.width / 2 - size.width / 2, y: anchor.top - size.height - offset };\n case 'bottom':\n return { x: anchor.left + anchor.width / 2 - size.width / 2, y: anchor.bottom + offset };\n case 'left':\n return { x: anchor.left - size.width - offset, y: anchor.top + anchor.height / 2 - size.height / 2 };\n case 'right':\n return { x: anchor.right + offset, y: anchor.top + anchor.height / 2 - size.height / 2 };\n }\n}\n\nfunction fits(pos: { x: number; y: number }, size: Size, vw: number, vh: number, padding: number): boolean {\n return (\n pos.x >= padding &&\n pos.y >= padding &&\n pos.x + size.width <= vw - padding &&\n pos.y + size.height <= vh - padding\n );\n}\n\nconst OPPOSITE: Record<Side, Side> = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' };\n\n/**\n * Position a floating element near an anchor rect, in viewport coordinates.\n * Flips to the opposite side when the preferred side doesn't fit, then shifts\n * to stay inside the viewport.\n */\nexport function computePosition(anchor: DOMRect, size: Size, options: Options = {}): ComputedPosition {\n const side = options.side ?? 'bottom';\n const offset = options.offset ?? 8;\n const padding = options.padding ?? 8;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n const order: Side[] = [side, OPPOSITE[side], 'bottom', 'top', 'right', 'left'];\n let chosen: Side = side;\n let pos = place(anchor, size, side, offset);\n for (const candidate of order) {\n const attempt = place(anchor, size, candidate, offset);\n if (fits(attempt, size, vw, vh, padding)) {\n chosen = candidate;\n pos = attempt;\n break;\n }\n }\n\n return {\n x: Math.min(Math.max(pos.x, padding), Math.max(padding, vw - size.width - padding)),\n y: Math.min(Math.max(pos.y, padding), Math.max(padding, vh - size.height - padding)),\n side: chosen,\n };\n}\n","/** Anchor a floating shadow-DOM element to a host-page element, rAF-tracked. */\n\nimport { useLayoutEffect, useRef, useState } from 'react';\nimport type { CSSProperties, RefObject } from 'react';\nimport type { Side } from './position';\nimport { computePosition } from './position';\n\nexport interface AnchoredPosition {\n x: number;\n y: number;\n side: Side;\n}\n\n/**\n * Continuously positions a floating element next to `anchorEl` (a host-page\n * element), following scroll and resize via a rAF loop. Returns a ref for the\n * floating element and the computed viewport position (null until measured).\n */\nexport function useAnchored<T extends HTMLElement>(\n anchorEl: Element | null,\n side: Side = 'bottom',\n offset = 8,\n): { ref: RefObject<T | null>; pos: AnchoredPosition | null } {\n const ref = useRef<T | null>(null);\n const [pos, setPos] = useState<AnchoredPosition | null>(null);\n\n useLayoutEffect(() => {\n if (!anchorEl) {\n setPos(null);\n return;\n }\n let raf = 0;\n let last = '';\n const update = () => {\n const floating = ref.current;\n if (floating && anchorEl.isConnected) {\n const rect = anchorEl.getBoundingClientRect();\n const next = computePosition(rect, { width: floating.offsetWidth, height: floating.offsetHeight }, { side, offset });\n const key = `${Math.round(next.x)}|${Math.round(next.y)}|${next.side}`;\n if (key !== last) {\n last = key;\n setPos(next);\n }\n }\n raf = requestAnimationFrame(update);\n };\n update();\n return () => cancelAnimationFrame(raf);\n }, [anchorEl, side, offset]);\n\n return { ref, pos };\n}\n\n/** Style helper: place a fixed-position floating element at a computed position. */\nexport function anchoredStyle(pos: AnchoredPosition | null): CSSProperties {\n if (!pos) return { visibility: 'hidden', transform: 'translate3d(-9999px, -9999px, 0)' };\n return { transform: `translate3d(${pos.x}px, ${pos.y}px, 0)`, top: 0, left: 0 };\n}\n","/**\n * Image replacement: pick/drop a file, paste or link an image URL, or describe it.\n *\n * URL loading is fetch-first (embed as a data URL, 2 MB cap). When the fetch\n * fails — typically CORS — the image is kept as an external *link* instead\n * (verified renderable via an <img> probe) and exported as `afterSrc` rather\n * than `afterDataUrl`, so the session always records whether the replacement\n * is embedded or referenced.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { ChangeEvent, DragEvent as ReactDragEvent, KeyboardEvent as ReactKeyboardEvent } from 'react';\nimport type { ImageItem, ItemPriority } from '../../schema';\nimport type { EditorState } from '../store';\nimport { toast, useDispatch, useStore } from '../store';\nimport { rkId } from '../id';\nimport { currentAuthor } from '../identity';\nimport { findImage } from '../target';\nimport { useAnchored, anchoredStyle } from '../useAnchored';\nimport { IconImage, IconLink, IconUpload } from './icons';\n\nconst MAX_BYTES = 2 * 1024 * 1024;\nconst FETCH_TIMEOUT_MS = 12_000;\nconst PROBE_TIMEOUT_MS = 8_000;\n\ntype Replacement =\n | { kind: 'data'; dataUrl: string }\n | { kind: 'url'; url: string };\n\nfunction parseImageUrl(raw: string): URL | null {\n let url: URL;\n try {\n url = new URL(raw.trim());\n } catch {\n return null;\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:' && url.protocol !== 'data:') return null;\n return url;\n}\n\nfunction blobToDataUrl(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result === 'string') resolve(reader.result);\n else reject(new Error('unreadable'));\n };\n reader.onerror = () => reject(new Error('unreadable'));\n reader.readAsDataURL(blob);\n });\n}\n\n/** Can the browser render this URL as an image at all (no CORS needed)? */\nfunction probeImage(url: string): Promise<boolean> {\n return new Promise((resolve) => {\n const img = new Image();\n const timer = window.setTimeout(() => {\n img.src = '';\n resolve(false);\n }, PROBE_TIMEOUT_MS);\n img.onload = () => {\n window.clearTimeout(timer);\n resolve(img.naturalWidth > 0);\n };\n img.onerror = () => {\n window.clearTimeout(timer);\n resolve(false);\n };\n img.src = url;\n });\n}\n\n/** First usable URL from a cross-tab image drag (uri-list, html or plain text). */\nfunction urlFromDataTransfer(dt: DataTransfer): string | null {\n const uriList = dt.getData('text/uri-list');\n const fromList = uriList\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => line !== '' && !line.startsWith('#'));\n if (fromList) return fromList;\n const html = dt.getData('text/html');\n if (html) {\n const src = new DOMParser().parseFromString(html, 'text/html').querySelector('img')?.getAttribute('src');\n if (src) return src;\n }\n const plain = dt.getData('text/plain').trim();\n return plain || null;\n}\n\nexport function ImageEditor({ editor }: { editor: EditorState }) {\n const dispatch = useDispatch();\n const { route, session } = useStore();\n const [replacement, setReplacement] = useState<Replacement | null>(null);\n const [urlValue, setUrlValue] = useState('');\n const [loading, setLoading] = useState(false);\n const [description, setDescription] = useState('');\n const [priority, setPriority] = useState<ItemPriority>('nice');\n const [over, setOver] = useState(false);\n const fileInput = useRef<HTMLInputElement | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n const debounceRef = useRef<number | null>(null);\n const { ref, pos } = useAnchored<HTMLDivElement>(editor.element, 'bottom', 12);\n\n const image = findImage(editor.element);\n const beforeSrc = image?.currentSrc || image?.src || '';\n\n const readFile = (file: File) => {\n if (!file.type.startsWith('image/')) {\n toast(dispatch, 'That file is not an image.', 'error');\n return;\n }\n if (file.size > MAX_BYTES) {\n toast(dispatch, 'Image is over 2 MB — please use a smaller file or paste a link to it.', 'error');\n return;\n }\n void blobToDataUrl(file)\n .then((dataUrl) => setReplacement({ kind: 'data', dataUrl }))\n .catch(() => toast(dispatch, 'Could not read that file.', 'error'));\n };\n\n const loadFromUrl = async (raw: string) => {\n const url = parseImageUrl(raw);\n if (!url) {\n toast(dispatch, 'That doesn’t look like an image link.', 'error');\n return;\n }\n // Mixed content: an http image can neither be fetched nor rendered on an\n // https page — try the https variant instead of failing silently.\n if (window.location.protocol === 'https:' && url.protocol === 'http:') {\n url.protocol = 'https:';\n toast(dispatch, 'http:// images are blocked on a secure page — trying https instead.', 'info');\n }\n\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n const timeout = window.setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n setLoading(true);\n try {\n let embedded = false;\n try {\n const response = await fetch(url.href, { signal: controller.signal, mode: 'cors' });\n if (response.ok) {\n const blob = await response.blob();\n if (blob.type.startsWith('image/')) {\n if (blob.size > MAX_BYTES) {\n setReplacement({ kind: 'url', url: url.href });\n toast(dispatch, 'Image is over 2 MB — kept as a link instead of embedding it.', 'info');\n return;\n }\n setReplacement({ kind: 'data', dataUrl: await blobToDataUrl(blob) });\n embedded = true;\n }\n }\n } catch {\n /* network / CORS / timeout — fall through to the <img> probe */\n }\n if (embedded) return;\n if (controller.signal.aborted && abortRef.current !== controller) return; // superseded\n if (await probeImage(url.href)) {\n setReplacement({ kind: 'url', url: url.href });\n toast(dispatch, 'Couldn’t embed that image (cross-origin) — kept as a link.', 'info');\n } else {\n toast(dispatch, 'Couldn’t load an image from that link.', 'error');\n }\n } finally {\n window.clearTimeout(timeout);\n if (abortRef.current === controller) {\n abortRef.current = null;\n setLoading(false);\n }\n }\n };\n\n // Typing or pasting into the URL field loads after a short pause.\n useEffect(() => {\n if (debounceRef.current !== null) window.clearTimeout(debounceRef.current);\n if (urlValue.trim() === '' || replacement !== null) return;\n debounceRef.current = window.setTimeout(() => {\n if (parseImageUrl(urlValue)) void loadFromUrl(urlValue);\n }, 600);\n return () => {\n if (debounceRef.current !== null) window.clearTimeout(debounceRef.current);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- loadFromUrl is stable per session\n }, [urlValue, replacement]);\n\n // Abort any in-flight load when the editor closes.\n useEffect(() => () => abortRef.current?.abort(), []);\n\n // ⌘/Ctrl+V anywhere while the editor is open: clipboard image or image link.\n useEffect(() => {\n const onPaste = (event: ClipboardEvent) => {\n const data = event.clipboardData;\n if (!data) return;\n const file = Array.from(data.files).find((f) => f.type.startsWith('image/'));\n if (file) {\n event.preventDefault();\n readFile(file);\n return;\n }\n // Plain text paste: treat as an image link unless it targets a text field.\n const inTextField = event\n .composedPath()\n .some((node) => node instanceof HTMLElement && (node.tagName === 'TEXTAREA' || node.tagName === 'INPUT'));\n if (inTextField) return;\n const text = data.getData('text/plain').trim();\n if (text && parseImageUrl(text)) {\n event.preventDefault();\n setUrlValue(text);\n void loadFromUrl(text);\n }\n };\n document.addEventListener('paste', onPaste);\n return () => document.removeEventListener('paste', onPaste);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- handlers are stable per session\n }, []);\n\n const onDrop = (event: ReactDragEvent<HTMLButtonElement>) => {\n event.preventDefault();\n setOver(false);\n const file = event.dataTransfer.files.item(0);\n if (file) {\n readFile(file);\n return;\n }\n // Dragged from another browser tab: a URL, not a file.\n const url = urlFromDataTransfer(event.dataTransfer);\n if (url && parseImageUrl(url)) {\n setUrlValue(url);\n void loadFromUrl(url);\n } else {\n toast(dispatch, 'Drop an image file, or drag an image from another tab.', 'error');\n }\n };\n\n const onPick = (event: ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.item(0);\n if (file) readFile(file);\n event.target.value = '';\n };\n\n const onUrlKeyDown = (event: ReactKeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n void loadFromUrl(urlValue);\n }\n };\n\n const clearReplacement = () => {\n abortRef.current?.abort();\n setReplacement(null);\n setUrlValue('');\n setLoading(false);\n };\n\n const save = () => {\n if (!replacement && description.trim() === '') {\n toast(dispatch, 'Add a replacement image or describe what should be here.', 'error');\n return;\n }\n const item: ImageItem = {\n id: rkId(),\n createdAt: new Date().toISOString(),\n author: currentAuthor(session?.author),\n type: 'image',\n status: 'open',\n route,\n target: editor.target,\n payload: { beforeSrc },\n priority,\n };\n if (replacement?.kind === 'data') item.payload.afterDataUrl = replacement.dataUrl;\n if (replacement?.kind === 'url') item.payload.afterSrc = replacement.url;\n if (description.trim() !== '') item.payload.description = description.trim();\n dispatch({ type: 'ADD_ITEM', item });\n toast(dispatch, 'Image proposal saved', 'success');\n };\n\n const previewSrc = replacement?.kind === 'data' ? replacement.dataUrl : replacement?.url;\n\n return (\n <div ref={ref} className=\"rk-card\" style={anchoredStyle(pos)} role=\"dialog\" aria-label=\"Replace image\">\n <div className=\"rk-card-head\">\n <IconImage size={14} />\n Replace image\n </div>\n <div className=\"rk-card-body\">\n {replacement && previewSrc ? (\n <div className=\"rk-thumbs\">\n <div className=\"rk-thumb-pair\" title=\"Hover to compare with the current image\">\n <figure className=\"rk-thumb\">\n <img src={beforeSrc} alt=\"Current\" />\n <figcaption>Before</figcaption>\n </figure>\n <figure className=\"rk-thumb\">\n <img src={previewSrc} alt=\"Proposed replacement\" />\n <figcaption>{replacement.kind === 'url' ? 'After · linked' : 'After'}</figcaption>\n </figure>\n </div>\n </div>\n ) : (\n <>\n <button\n type=\"button\"\n className={`rk-drop${over ? ' rk-over' : ''}`}\n onClick={() => fileInput.current?.click()}\n onDragOver={(event) => {\n event.preventDefault();\n setOver(true);\n }}\n onDragLeave={() => setOver(false)}\n onDrop={onDrop}\n >\n <IconUpload size={18} />\n <span>\n Drop an image — from your disk or another tab —\n <br />\n or click to browse (max 2 MB)\n </span>\n </button>\n <div className=\"rk-url\">\n {loading ? <span className=\"rk-spinner\" aria-label=\"Loading image\" /> : <IconLink size={13} />}\n <input\n className=\"rk-input\"\n type=\"url\"\n placeholder=\"or paste an image link (https://…)\"\n aria-label=\"Image link\"\n value={urlValue}\n onChange={(event) => setUrlValue(event.target.value)}\n onKeyDown={onUrlKeyDown}\n spellCheck={false}\n />\n </div>\n </>\n )}\n {replacement && (\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={clearReplacement}>\n Remove replacement\n </button>\n )}\n <input ref={fileInput} type=\"file\" accept=\"image/*\" hidden onChange={onPick} />\n <textarea\n className=\"rk-textarea\"\n placeholder=\"Describe what should be here instead…\"\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n rows={2}\n />\n <div className=\"rk-seg\" role=\"group\" aria-label=\"Priority\">\n <button type=\"button\" aria-pressed={priority === 'must'} onClick={() => setPriority('must')}>\n Must\n </button>\n <button type=\"button\" aria-pressed={priority === 'nice'} onClick={() => setPriority('nice')}>\n Nice to have\n </button>\n </div>\n </div>\n <div className=\"rk-card-foot\">\n <span className=\"rk-hint\">\n <span className=\"rk-kbd\">esc</span> cancel\n </span>\n <div className=\"rk-actions\">\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={() => dispatch({ type: 'CLOSE_EDITOR' })}>\n Cancel\n </button>\n <button type=\"button\" className=\"rk-btn rk-btn-primary\" onClick={save}>\n Save\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/** Inline copy rewrite: editable \"After\" field synced live with the element, DOM restored on exit. */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { KeyboardEvent as ReactKeyboardEvent } from 'react';\nimport type { CopyItem, ItemPriority } from '../../schema';\nimport type { EditorState } from '../store';\nimport { toast, useDispatch, useStore } from '../store';\nimport { rkId } from '../id';\nimport { currentAuthor } from '../identity';\nimport { setElementText } from '../preview';\nimport { useAnchored, anchoredStyle } from '../useAnchored';\nimport { IconText } from './icons';\n\nexport function InlineEditor({ editor }: { editor: EditorState }) {\n const dispatch = useDispatch();\n const { route, session } = useStore();\n const [after, setAfter] = useState(() => editor.element.innerText);\n const [priority, setPriority] = useState<ItemPriority>('nice');\n const [note, setNote] = useState('');\n const original = useRef<{ html: string; text: string; styleAttr: string | null } | null>(null);\n const baseline = useRef<{ height: number; width: number; lineHeight: number } | null>(null);\n const [sizeDelta, setSizeDelta] = useState(0);\n const [widthDelta, setWidthDelta] = useState(0);\n const [clipped, setClipped] = useState(false);\n const ringRef = useRef<HTMLDivElement | null>(null);\n const afterRef = useRef<HTMLTextAreaElement | null>(null);\n const { ref, pos } = useAnchored<HTMLDivElement>(editor.element, 'bottom', 12);\n\n const element = editor.element;\n\n // Enter in-place editing; always restore the original DOM on exit. The\n // element stays directly editable too — typing there mirrors into the card.\n useEffect(() => {\n const el = element;\n // Snapshot everything the editor touches — the exit restore must be\n // byte-exact (innerHTML, the style *attribute*, contenteditable).\n original.current = { html: el.innerHTML, text: el.innerText, styleAttr: el.getAttribute('style') };\n const rect = el.getBoundingClientRect();\n const lineHeight = parseFloat(getComputedStyle(el).lineHeight) || 20;\n baseline.current = { height: rect.height, width: rect.width, lineHeight };\n setAfter(el.innerText);\n el.setAttribute('contenteditable', 'plaintext-only');\n if (!el.isContentEditable) el.setAttribute('contenteditable', 'true');\n el.style.outline = 'none';\n el.style.caretColor = '#7c8cf8';\n\n // Only fires for typing in the element itself, never for programmatic\n // innerText writes from the card field — so the two-way sync can't loop.\n const onInput = () => setAfter(el.innerText);\n const onPaste = (event: ClipboardEvent) => {\n // Keep pasted content plain even where plaintext-only is unsupported.\n event.preventDefault();\n const text = event.clipboardData?.getData('text/plain') ?? '';\n document.execCommand('insertText', false, text);\n };\n el.addEventListener('input', onInput);\n el.addEventListener('paste', onPaste);\n\n return () => {\n el.removeEventListener('input', onInput);\n el.removeEventListener('paste', onPaste);\n el.removeAttribute('contenteditable');\n if (original.current) {\n el.innerHTML = original.current.html;\n // Restore the style attribute exactly — resetting properties one by\n // one would leave an empty style=\"\" artifact behind.\n if (original.current.styleAttr === null) el.removeAttribute('style');\n else el.setAttribute('style', original.current.styleAttr);\n }\n };\n }, [element]);\n\n // Focus the card's After field with the caret at the end of the text.\n // Gated on `pos`: until the card is measured it sits at visibility:hidden,\n // where focus() is silently ignored.\n const focusedOnce = useRef(false);\n useEffect(() => {\n const field = afterRef.current;\n if (pos === null || focusedOnce.current || !field) return;\n focusedOnce.current = true;\n field.focus();\n const end = field.value.length;\n field.setSelectionRange(end, end);\n }, [pos]);\n\n // Auto-grow the After field with its content.\n useEffect(() => {\n const field = afterRef.current;\n if (!field) return;\n field.style.height = 'auto';\n field.style.height = `${field.scrollHeight}px`;\n }, [after]);\n\n // Card → page: typing in the field rewrites the element in place. Only\n // text nodes change — icons and nested wrappers keep their place, so the\n // element grows exactly as the real site would with that text.\n const onAfterChange = (value: string) => {\n setAfter(value);\n if (element.innerText !== value) setElementText(element, value);\n };\n\n // rAF: keep the edit ring glued to the element while typing reflows it,\n // and quietly track how the block's size responds to the new text.\n useEffect(() => {\n let raf = 0;\n let lastDelta = 0;\n let lastWidth = 0;\n let lastClipped = false;\n const tick = () => {\n const ring = ringRef.current;\n if (ring && element.isConnected) {\n const rect = element.getBoundingClientRect();\n ring.style.transform = `translate3d(${rect.left - 4}px, ${rect.top - 4}px, 0)`;\n ring.style.width = `${rect.width + 8}px`;\n ring.style.height = `${rect.height + 8}px`;\n const base = baseline.current;\n if (base) {\n const delta = Math.round(rect.height - base.height);\n const dWidth = Math.round(rect.width - base.width);\n const isClipped =\n element.scrollHeight > element.clientHeight + 1 || element.scrollWidth > element.clientWidth + 1;\n if (delta !== lastDelta) {\n lastDelta = delta;\n setSizeDelta(delta);\n }\n if (dWidth !== lastWidth) {\n lastWidth = dWidth;\n setWidthDelta(dWidth);\n }\n if (isClipped !== lastClipped) {\n lastClipped = isClipped;\n setClipped(isClipped);\n }\n }\n }\n raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [element]);\n\n const commit = () => {\n const before = original.current?.text ?? '';\n if (after.trim() === before.trim() && note.trim() === '') {\n dispatch({ type: 'CLOSE_EDITOR' });\n return;\n }\n const item: CopyItem = {\n id: rkId(),\n createdAt: new Date().toISOString(),\n author: currentAuthor(session?.author),\n type: 'copy',\n status: 'open',\n route,\n target: editor.target,\n payload: { before, after },\n priority,\n };\n if (note.trim() !== '') item.note = note.trim();\n dispatch({ type: 'ADD_ITEM', item });\n toast(dispatch, 'Rewrite saved', 'success');\n };\n\n const cancel = () => {\n dispatch({ type: 'CLOSE_EDITOR' });\n };\n\n const onAfterKeyDown = (event: ReactKeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n commit();\n } else if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n cancel();\n }\n };\n\n // Enter commits (Shift+Enter for a new line), Esc cancels — on the host element.\n useEffect(() => {\n const el = element;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n event.stopPropagation();\n commit();\n } else if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n cancel();\n }\n };\n el.addEventListener('keydown', onKeyDown);\n return () => el.removeEventListener('keydown', onKeyDown);\n });\n\n const before = original.current?.text ?? '';\n const delta = after.length - before.length;\n\n return (\n <>\n <div ref={ringRef} className=\"rk-edit-ring\" />\n <div ref={ref} className=\"rk-card\" style={anchoredStyle(pos)} role=\"dialog\" aria-label=\"Rewrite text\">\n <div className=\"rk-card-head\">\n <IconText size={14} />\n Rewrite text\n <span className=\"rk-spacer\" />\n <span className=\"rk-delta\" aria-live=\"polite\">\n {before.length} → {after.length}{' '}\n {delta !== 0 && (\n <span className={delta > 0 ? 'rk-plus' : 'rk-minus'}>\n ({delta > 0 ? '+' : ''}\n {delta})\n </span>\n )}\n </span>\n </div>\n <div className=\"rk-card-body\">\n <div className=\"rk-diff\" aria-label=\"Before and after\">\n <div className=\"rk-diff-row rk-diff-before\">\n <span className=\"rk-diff-tag\">Before</span>\n <span className=\"rk-diff-text\">{before}</span>\n </div>\n <div className=\"rk-diff-row rk-diff-after\">\n <span className=\"rk-diff-tag\">After</span>\n <textarea\n ref={afterRef}\n className=\"rk-textarea rk-diff-input\"\n rows={1}\n aria-label=\"New text\"\n value={after}\n onChange={(event) => onAfterChange(event.target.value)}\n onKeyDown={onAfterKeyDown}\n />\n </div>\n </div>\n {(Math.abs(sizeDelta) > 2 || Math.abs(widthDelta) > 4 || clipped) && (\n <div className=\"rk-size-note\" role=\"status\">\n {Math.abs(sizeDelta) > 2 &&\n (() => {\n const lines = baseline.current ? Math.round(Math.abs(sizeDelta) / baseline.current.lineHeight) : 0;\n const lineNote = lines >= 1 ? ` (~${lines} line${lines === 1 ? '' : 's'})` : '';\n return (\n <span>\n Block {sizeDelta > 0 ? 'grew' : 'shrank'} by {Math.abs(sizeDelta)} px{lineNote} — as it\n would with this text live.\n </span>\n );\n })()}\n {Math.abs(sizeDelta) <= 2 && Math.abs(widthDelta) > 4 && (\n <span>\n Block got {widthDelta > 0 ? 'wider' : 'narrower'} by {Math.abs(widthDelta)} px — as it would\n with this text live.\n </span>\n )}\n {clipped && (\n <span className=\"rk-clip-note\">Text exceeds the visible crop here and will be cut off.</span>\n )}\n </div>\n )}\n <input\n className=\"rk-input\"\n placeholder=\"Note for the developer (optional)\"\n value={note}\n onChange={(event) => setNote(event.target.value)}\n />\n <div className=\"rk-seg\" role=\"group\" aria-label=\"Priority\">\n <button type=\"button\" aria-pressed={priority === 'must'} onClick={() => setPriority('must')}>\n Must\n </button>\n <button type=\"button\" aria-pressed={priority === 'nice'} onClick={() => setPriority('nice')}>\n Nice to have\n </button>\n </div>\n </div>\n <div className=\"rk-card-foot\">\n <span className=\"rk-hint\">\n <span className=\"rk-kbd\">↵</span> save · <span className=\"rk-kbd\">⇧↵</span> newline ·{' '}\n <span className=\"rk-kbd\">esc</span> cancel\n </span>\n <div className=\"rk-actions\">\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={cancel}>\n Cancel\n </button>\n <button type=\"button\" className=\"rk-btn rk-btn-primary\" onClick={commit}>\n Save\n </button>\n </div>\n </div>\n </div>\n </>\n );\n}\n","/** Composer card for comment / delete / move / style items. */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { KeyboardEvent as ReactKeyboardEvent } from 'react';\nimport type { ItemPriority, MovePayload, ReviewItem } from '../../schema';\nimport type { EditorState } from '../store';\nimport { toast, useDispatch, useStore } from '../store';\nimport { rkId } from '../id';\nimport { currentAuthor } from '../identity';\nimport { useAnchored, anchoredStyle } from '../useAnchored';\nimport { iconForType } from './icons';\n\nconst TITLES: Record<string, string> = {\n comment: 'Comment',\n delete: 'Mark for deletion',\n move: 'Move / reorder',\n style: 'Style note',\n};\n\nconst PLACEHOLDERS: Record<string, string> = {\n comment: 'What should change here?',\n delete: 'Why should this go? (optional)',\n move: 'Where should it go instead? e.g. “above the pricing table”',\n style: 'Describe the styling change, e.g. “more contrast, larger on mobile”',\n};\n\ntype Direction = MovePayload['direction'];\n\nexport function NoteComposer({ editor }: { editor: EditorState }) {\n const dispatch = useDispatch();\n const { route, session } = useStore();\n const [text, setText] = useState('');\n const [direction, setDirection] = useState<Direction>(undefined);\n const [priority, setPriority] = useState<ItemPriority>('nice');\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n const { ref, pos } = useAnchored<HTMLDivElement>(editor.element, 'bottom', 12);\n\n const { kind } = editor;\n\n // Focus once the card is MEASURED: until `pos` lands, the anchored card\n // sits at visibility:hidden where focus() is silently ignored — the mount\n // -effect focus never took, so \"click a spot and type\" sent the keystrokes\n // to the page as tool shortcuts (which killed the composer). Same fix as\n // InlineEditor, plus a next-frame re-assert in case the host page steals\n // focus back in its own click handlers.\n const focusedOnce = useRef(false);\n useEffect(() => {\n const field = textareaRef.current;\n if (pos === null || focusedOnce.current || !field) return;\n focusedOnce.current = true;\n field.focus();\n const raf = requestAnimationFrame(() => {\n if ((field.getRootNode() as ShadowRoot | Document).activeElement !== field) field.focus();\n });\n return () => cancelAnimationFrame(raf);\n }, [pos]);\n\n const save = () => {\n const trimmed = text.trim();\n if ((kind === 'comment' || kind === 'style') && trimmed === '') {\n toast(dispatch, 'Write a short note first.', 'error');\n return;\n }\n if (kind === 'move' && trimmed === '' && direction === undefined) {\n toast(dispatch, 'Pick a direction or describe the destination.', 'error');\n return;\n }\n const base = {\n id: rkId(),\n createdAt: new Date().toISOString(),\n author: currentAuthor(session?.author),\n status: 'open' as const,\n route,\n target: editor.target,\n priority,\n };\n let item: ReviewItem;\n switch (kind) {\n case 'comment':\n item = { ...base, type: 'comment', payload: { text: trimmed } };\n break;\n case 'delete':\n item = { ...base, type: 'delete', payload: trimmed === '' ? {} : { reason: trimmed } };\n break;\n case 'move': {\n const payload: MovePayload = {};\n if (direction !== undefined) payload.direction = direction;\n if (trimmed !== '') payload.targetDescription = trimmed;\n item = { ...base, type: 'move', payload };\n break;\n }\n case 'style':\n item = { ...base, type: 'style', payload: { description: trimmed } };\n break;\n default:\n return;\n }\n dispatch({ type: 'ADD_ITEM', item });\n toast(dispatch, `${TITLES[kind] ?? 'Item'} saved`, 'success');\n };\n\n const onKeyDown = (event: ReactKeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n save();\n }\n };\n\n return (\n <div ref={ref} className=\"rk-card\" style={anchoredStyle(pos)} role=\"dialog\" aria-label={TITLES[kind]}>\n <div className=\"rk-card-head\">\n {iconForType(kind)}\n {TITLES[kind]}\n </div>\n <div className=\"rk-card-body\">\n {kind === 'move' && (\n <div className=\"rk-seg\" role=\"group\" aria-label=\"Direction\">\n {(['up', 'down', 'first', 'last'] as const).map((option) => (\n <button\n key={option}\n type=\"button\"\n aria-pressed={direction === option}\n onClick={() => setDirection(direction === option ? undefined : option)}\n >\n {option === 'up' ? 'Up' : option === 'down' ? 'Down' : option === 'first' ? 'First' : 'Last'}\n </button>\n ))}\n </div>\n )}\n <textarea\n ref={textareaRef}\n className=\"rk-textarea\"\n placeholder={PLACEHOLDERS[kind]}\n value={text}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={onKeyDown}\n rows={3}\n />\n <div className=\"rk-seg\" role=\"group\" aria-label=\"Priority\">\n <button type=\"button\" aria-pressed={priority === 'must'} onClick={() => setPriority('must')}>\n Must\n </button>\n <button type=\"button\" aria-pressed={priority === 'nice'} onClick={() => setPriority('nice')}>\n Nice to have\n </button>\n </div>\n </div>\n <div className=\"rk-card-foot\">\n <span className=\"rk-hint\">\n <span className=\"rk-kbd\">⌘↵</span> save · <span className=\"rk-kbd\">esc</span> cancel\n </span>\n <div className=\"rk-actions\">\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={() => dispatch({ type: 'CLOSE_EDITOR' })}>\n Cancel\n </button>\n <button type=\"button\" className=\"rk-btn rk-btn-primary\" onClick={save}>\n Save\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/** Side panel: session list, search/filter, inline edit, export actions. */\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport type { KeyboardEvent as ReactKeyboardEvent, PointerEvent as ReactPointerEvent } from 'react';\nimport type { ItemStatus, ReviewItem } from '../../schema';\nimport {\n isCommentItem,\n isCopyItem,\n isDeleteItem,\n isImageItem,\n isKnownItemType,\n isMoveItem,\n isStyleItem,\n} from '../../schema';\nimport { deactivateReview, isStickyEnabled, rememberFocusItem, setSticky } from '../env';\nimport { fetchSyncState, pingEmblema, sendToEmblema } from '../../integrations/emblema';\nimport type { EmblemaSyncState } from '../../integrations/emblema';\nimport { copySessionToClipboard, downloadSession, importSessionFile } from '../exportSession';\nimport { keyHint } from '../shortcuts';\nimport { revealTarget } from '../reveal';\nimport { isElementVisible, resolveTarget } from '../target';\nimport { choosePreview, itemMatchesFilter, toast, useConfig, useDispatch, useStore } from '../store';\nimport {\n IconClose,\n IconCopyClipboard,\n IconDownload,\n IconFilter,\n IconGear,\n IconKeyboard,\n IconSearch,\n IconTarget,\n IconTrash,\n IconUndo,\n IconUpload,\n iconForType,\n} from './icons';\n\nfunction changeSummary(item: ReviewItem): string {\n if (isCopyItem(item)) return `“${item.payload.after}”`;\n if (isImageItem(item)) {\n if (item.payload.description) return item.payload.description;\n if (item.payload.afterDataUrl) return 'Replacement image attached';\n if (item.payload.afterSrc) return 'Replacement image linked';\n return 'Replace image';\n }\n if (isCommentItem(item)) return item.payload.text;\n if (isDeleteItem(item)) return item.payload.reason ? `Remove — ${item.payload.reason}` : 'Remove this element';\n if (isMoveItem(item)) {\n const parts: string[] = [];\n if (item.payload.direction) parts.push(`Move ${item.payload.direction}`);\n if (item.payload.targetDescription) parts.push(item.payload.targetDescription);\n return parts.join(' — ') || 'Move';\n }\n if (isStyleItem(item)) return item.payload.description;\n return `Unknown change (${item.type})`;\n}\n\nfunction payloadText(item: ReviewItem): string {\n if (isCopyItem(item)) return item.payload.after;\n if (isImageItem(item)) return item.payload.description ?? '';\n if (isCommentItem(item)) return item.payload.text;\n if (isDeleteItem(item)) return item.payload.reason ?? '';\n if (isMoveItem(item)) return item.payload.targetDescription ?? '';\n if (isStyleItem(item)) return item.payload.description;\n return '';\n}\n\nfunction withPayloadText(item: ReviewItem, text: string): ReviewItem {\n if (isCopyItem(item)) return { ...item, payload: { ...item.payload, after: text } };\n if (isImageItem(item)) return { ...item, payload: { ...item.payload, description: text } };\n if (isCommentItem(item)) return { ...item, payload: { ...item.payload, text } };\n if (isDeleteItem(item)) return { ...item, payload: { ...item.payload, reason: text } };\n if (isMoveItem(item)) return { ...item, payload: { ...item.payload, targetDescription: text } };\n if (isStyleItem(item)) return { ...item, payload: { ...item.payload, description: text } };\n return item;\n}\n\nconst TYPE_FILTERS = ['copy', 'image', 'comment', 'delete', 'move', 'style'] as const;\nconst PRIORITY_FILTERS = ['must', 'nice'] as const;\nconst STATUSES: ItemStatus[] = ['open', 'accepted', 'rejected', 'applied'];\nconst PRIORITY_LABELS: Record<string, string> = { must: 'Must', nice: 'Nice to have' };\n\n/** \"5 min ago\" style; the exact timestamp lives in the tooltip. */\nfunction timeAgo(iso: string): string {\n const then = Date.parse(iso);\n if (Number.isNaN(then)) return '';\n const s = Math.max(0, (Date.now() - then) / 1000);\n if (s < 45) return 'just now';\n if (s < 3600) return `${Math.round(s / 60)} min ago`;\n if (s < 86400) return `${Math.round(s / 3600)} h ago`;\n if (s < 7 * 86400) return `${Math.round(s / 86400)} d ago`;\n return new Date(then).toLocaleDateString();\n}\n\n/** Common prefix/suffix split so the changed middle can be highlighted. */\nfunction diffParts(before: string, after: string): { prefix: string; delMid: string; insMid: string; suffix: string } {\n let start = 0;\n while (start < before.length && start < after.length && before[start] === after[start]) start++;\n let endB = before.length;\n let endA = after.length;\n while (endB > start && endA > start && before[endB - 1] === after[endA - 1]) {\n endB--;\n endA--;\n }\n return {\n prefix: before.slice(0, start),\n delMid: before.slice(start, endB),\n insMid: after.slice(start, endA),\n suffix: before.slice(endB),\n };\n}\n\nfunction dataUrlBytes(dataUrl: string): number | null {\n const comma = dataUrl.indexOf(',');\n if (comma === -1) return null;\n const b64 = dataUrl.slice(comma + 1);\n return Math.floor((b64.length * 3) / 4) - (b64.endsWith('==') ? 2 : b64.endsWith('=') ? 1 : 0);\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} kB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/** Persistent before → after view for copy items, with highlighted change. */\nfunction CopyDiff({ before, after }: { before: string; after: string }) {\n const parts = diffParts(before, after);\n const delta = after.length - before.length;\n return (\n <div className=\"rk-diffview\">\n <div className=\"rk-diff-row rk-diff-before\">\n <span className=\"rk-diff-tag\">Before</span>\n <span className=\"rk-diff-text\">\n {parts.prefix}\n {parts.delMid && <mark className=\"rk-del\">{parts.delMid}</mark>}\n {parts.suffix}\n </span>\n </div>\n <div className=\"rk-diff-row rk-diff-after\">\n <span className=\"rk-diff-tag\">After</span>\n <span className=\"rk-diff-text\">\n {parts.prefix}\n {parts.insMid && <mark className=\"rk-ins\">{parts.insMid}</mark>}\n {parts.suffix}\n </span>\n </div>\n <div className=\"rk-diff-len\">\n {before.length} → {after.length} chars{delta !== 0 ? ` (${delta > 0 ? '+' : ''}${delta})` : ''}\n </div>\n </div>\n );\n}\n\n/** Image replacement detail: thumbs, embedded/linked info, download/open. */\nfunction ImageDetail({ beforeSrc, afterSrc, afterDataUrl }: { beforeSrc: string; afterSrc?: string; afterDataUrl?: string }) {\n const replacement = afterDataUrl ?? afterSrc;\n const [dims, setDims] = useState<string>('');\n useEffect(() => {\n if (!replacement) return;\n const img = new Image();\n img.onload = () => setDims(`${img.naturalWidth}×${img.naturalHeight}px`);\n img.src = replacement;\n }, [replacement]);\n if (!replacement) return null;\n const embedded = afterDataUrl !== undefined;\n const bytes = embedded ? dataUrlBytes(afterDataUrl) : null;\n\n const download = async () => {\n try {\n const blob = await (await fetch(replacement)).blob();\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.setAttribute('data-review-kit-host', '');\n a.href = url;\n a.download = `review-image.${(blob.type.split('/')[1] || 'png').split('+')[0]}`;\n document.body.appendChild(a);\n a.click();\n a.remove();\n window.setTimeout(() => URL.revokeObjectURL(url), 1000);\n } catch {\n window.open(replacement, '_blank', 'noopener');\n }\n };\n\n return (\n <div className=\"rk-imgdetail\">\n <div className=\"rk-thumbs\">\n <figure className=\"rk-thumb\">\n {beforeSrc ? <img src={beforeSrc} alt=\"Current\" /> : <div className=\"rk-thumb-missing\">no image</div>}\n <figcaption>Before</figcaption>\n </figure>\n <figure className=\"rk-thumb\">\n <img src={replacement} alt=\"Proposed replacement\" />\n <figcaption>After{embedded ? '' : ' · linked'}</figcaption>\n </figure>\n </div>\n <div className=\"rk-imgdetail-meta\">\n {embedded ? 'Embedded image' : 'Linked image'}\n {dims ? ` · ${dims}` : ''}\n {bytes !== null ? ` · ${formatBytes(bytes)}` : ''}\n </div>\n {!embedded && afterSrc && (\n <a className=\"rk-imgdetail-url\" href={afterSrc} target=\"_blank\" rel=\"noopener noreferrer\" title={afterSrc}>\n {afterSrc}\n </a>\n )}\n <div className=\"rk-imgdetail-actions\">\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={() => void download()}>\n <IconDownload size={12} /> Download\n </button>\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={() => window.open(replacement, '_blank', 'noopener')}>\n Open\n </button>\n </div>\n </div>\n );\n}\n\nexport function Panel() {\n const { session, panelOpen, activeItemId, badgeCorner, undoStack, preview, unapplied, syncStatus, emblemaPush, peers } = useStore();\n const dispatch = useDispatch();\n const config = useConfig();\n const [sticky, setStickyState] = useState(() => isStickyEnabled(config.token));\n const [query, setQuery] = useState('');\n const [typeFilter, setTypeFilter] = useState<Set<string>>(new Set());\n const [prioFilter, setPrioFilter] = useState<Set<string>>(new Set());\n const [statusFilter, setStatusFilter] = useState<Set<string>>(new Set());\n const [filterOpen, setFilterOpen] = useState(false);\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [emblemaAlive, setEmblemaAlive] = useState<boolean | null>(null);\n const [emblemaSending, setEmblemaSending] = useState(false);\n const [emblemaSync, setEmblemaSync] = useState<EmblemaSyncState | null | 'unknown'>('unknown');\n const panelRef = useRef<HTMLDivElement | null>(null);\n const searchRef = useRef<HTMLInputElement | null>(null);\n const importRef = useRef<HTMLInputElement | null>(null);\n const sheetDrag = useRef<{ startY: number } | null>(null);\n\n const items = useMemo(() => session?.items ?? [], [session]);\n\n const { orphanIds, hiddenIds } = useMemo(() => {\n const orphans = new Set<string>();\n const hiddens = new Set<string>();\n for (const item of items) {\n if (item.route !== window.location.pathname) continue;\n const resolved = resolveTarget(item.target);\n if (resolved === null) orphans.add(item.id);\n else if (!isElementVisible(resolved.element)) hiddens.add(item.id);\n }\n return { orphanIds: orphans, hiddenIds: hiddens };\n // Re-check when the panel opens or items change.\n }, [items, panelOpen]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const activeFilter = useMemo(\n () =>\n typeFilter.size + prioFilter.size + statusFilter.size > 0\n ? { types: [...typeFilter], priorities: [...prioFilter], statuses: [...statusFilter] }\n : null,\n [typeFilter, prioFilter, statusFilter],\n );\n\n // Mirror the filters into the store so the pin layer can dim non-matches.\n useEffect(() => {\n dispatch({ type: 'SET_FILTER', filter: activeFilter });\n return () => dispatch({ type: 'SET_FILTER', filter: null });\n }, [activeFilter, dispatch]);\n\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase();\n return items\n .map((item, index) => ({ item, number: index + 1 }))\n .filter(({ item }) => {\n if (!itemMatchesFilter(item, activeFilter)) return false;\n if (q === '') return true;\n const haystack = `${item.target.textSnippet} ${changeSummary(item)} ${item.note ?? ''} ${item.type}`.toLowerCase();\n return haystack.includes(q);\n });\n }, [items, query, activeFilter]);\n\n const typeCounts = useMemo(() => {\n const counts = new Map<string, number>();\n for (const item of items) counts.set(item.type, (counts.get(item.type) ?? 0) + 1);\n return counts;\n }, [items]);\n\n const prioCounts = useMemo(() => {\n const counts = new Map<string, number>();\n for (const item of items) counts.set(item.priority, (counts.get(item.priority) ?? 0) + 1);\n return counts;\n }, [items]);\n\n const statusCounts = useMemo(() => {\n const counts = new Map<string, number>();\n for (const item of items) counts.set(item.status, (counts.get(item.status) ?? 0) + 1);\n return counts;\n }, [items]);\n\n const groups = useMemo(() => {\n const map = new Map<string, typeof filtered>();\n for (const entry of filtered) {\n const list = map.get(entry.item.route) ?? [];\n list.push(entry);\n map.set(entry.item.route, list);\n }\n return Array.from(map.entries());\n }, [filtered]);\n\n // Any outside press closes the small popover menus.\n useEffect(() => {\n if (!filterOpen && !settingsOpen) return;\n const onDown = (event: PointerEvent) => {\n const path = event.composedPath();\n if (path.some((node) => node instanceof HTMLElement && node.classList?.contains('rk-menu-scope'))) return;\n setFilterOpen(false);\n setSettingsOpen(false);\n };\n document.addEventListener('pointerdown', onDown, true);\n return () => document.removeEventListener('pointerdown', onDown, true);\n }, [filterOpen, settingsOpen]);\n\n // Live Emblema pairing status next to \"Connect to Emblema…\" — polls the\n // local sync agent only while the gear menu is open.\n useEffect(() => {\n if (!settingsOpen) return;\n let alive = true;\n const probe = () => {\n void fetchSyncState().then((state) => {\n if (alive) setEmblemaSync(state);\n });\n };\n probe();\n const timer = window.setInterval(probe, 4000);\n return () => {\n alive = false;\n window.clearInterval(timer);\n setEmblemaSync('unknown');\n };\n }, [settingsOpen]);\n\n const emblemaPairState =\n emblemaSync === 'unknown'\n ? 'unknown'\n : emblemaSync === null\n ? 'stale'\n : emblemaSync.revoked\n ? 'revoked'\n : emblemaSync.paired\n ? 'live'\n : 'off';\n const emblemaPairLabel = {\n unknown: '…',\n stale: 'no agent',\n revoked: 'revoked',\n live: 'paired',\n off: 'not paired',\n }[emblemaPairState];\n\n // Scroll the active item's row into view.\n useEffect(() => {\n if (!panelOpen || activeItemId === null) return;\n const row = panelRef.current?.querySelector(`[data-item-id=\"${activeItemId}\"]`);\n row?.scrollIntoView({ block: 'nearest' });\n }, [panelOpen, activeItemId]);\n\n if (!panelOpen || !session) return null;\n\n const side = badgeCorner.includes('left') ? 'rk-left' : 'rk-right';\n\n const moveActive = (delta: number) => {\n if (filtered.length === 0) return;\n const index = filtered.findIndex(({ item }) => item.id === activeItemId);\n const next = index === -1 ? (delta > 0 ? 0 : filtered.length - 1) : Math.min(Math.max(index + delta, 0), filtered.length - 1);\n dispatch({ type: 'SET_ACTIVE_ITEM', id: filtered[next].item.id });\n };\n\n const onKeyDown = (event: ReactKeyboardEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement;\n const inField = target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.tagName === 'SELECT';\n if (event.key === 'ArrowDown' && !inField) {\n event.preventDefault();\n moveActive(1);\n } else if (event.key === 'ArrowUp' && !inField) {\n event.preventDefault();\n moveActive(-1);\n } else if (event.key === 'Tab') {\n // Focus trap.\n const panel = panelRef.current;\n if (!panel) return;\n const focusable = Array.from(\n panel.querySelectorAll<HTMLElement>('button, input, textarea, select, [tabindex]:not([tabindex=\"-1\"])'),\n ).filter((el) => el.offsetParent !== null || el === document.activeElement);\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = panel.getRootNode() instanceof ShadowRoot ? (panel.getRootNode() as ShadowRoot).activeElement : document.activeElement;\n if (event.shiftKey && active === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && active === last) {\n event.preventDefault();\n first.focus();\n }\n }\n };\n\n const jumpTo = (item: ReviewItem) => {\n dispatch({ type: 'SET_ACTIVE_ITEM', id: item.id === activeItemId ? null : item.id });\n if (item.route !== window.location.pathname) {\n // The comment lives on another page: go there (review mode survives via\n // the sticky tab session) and select its pin once the target resolves.\n rememberFocusItem(item.id);\n window.location.assign(item.route);\n return;\n }\n // A hidden target (closed modal/accordion/menu) gets a reveal attempt\n // through the page's own controls before we scroll to it.\n void revealTarget(item.target).then((result) => {\n if (result === 'failed') {\n const resolved = resolveTarget(item.target);\n if (resolved) {\n toast(\n dispatch,\n 'This content couldn’t be opened automatically — please open it by hand to see the pin.',\n 'info',\n );\n }\n return;\n }\n resolveTarget(item.target)?.element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n });\n };\n\n const onExport = () => {\n downloadSession(session);\n toast(dispatch, 'Session exported', 'success');\n };\n\n const onCopy = async () => {\n const ok = await copySessionToClipboard(session);\n toast(dispatch, ok ? 'Session JSON copied' : 'Clipboard unavailable', ok ? 'success' : 'error');\n };\n\n const onImportFile = async (file: File) => {\n const result = await importSessionFile(file);\n if (result.ok) {\n dispatch({ type: 'REPLACE_SESSION', session: result.session });\n toast(dispatch, `Imported ${result.session.items.length} item${result.session.items.length === 1 ? '' : 's'}`, 'success');\n } else {\n toast(dispatch, `Import failed: ${result.error}`, 'error');\n }\n };\n\n const onClear = () => {\n const shared = syncStatus !== 'disabled';\n dispatch({\n type: 'SET_CONFIRM',\n confirm: {\n title: 'Clear this session?',\n message: shared\n ? `All ${items.length} feedback item${items.length === 1 ? '' : 's'} will be deleted for EVERYONE in this room — not just you. This cannot be undone.`\n : `All ${items.length} feedback item${items.length === 1 ? '' : 's'} will be removed. This cannot be undone.`,\n confirmLabel: shared ? 'Delete for everyone' : 'Clear session',\n danger: true,\n onConfirm: () => {\n dispatch({ type: 'CLEAR_ITEMS' });\n toast(dispatch, shared ? 'Session cleared for the whole room' : 'Session cleared', 'info');\n },\n },\n });\n };\n\n const onSheetHandleDown = (event: ReactPointerEvent<HTMLDivElement>) => {\n sheetDrag.current = { startY: event.clientY };\n event.currentTarget.setPointerCapture(event.pointerId);\n };\n const onSheetHandleMove = (event: ReactPointerEvent<HTMLDivElement>) => {\n const drag = sheetDrag.current;\n const panel = panelRef.current;\n if (!drag || !panel) return;\n const dy = Math.max(0, event.clientY - drag.startY);\n panel.style.transform = `translateY(${dy}px)`;\n };\n const onSheetHandleUp = (event: ReactPointerEvent<HTMLDivElement>) => {\n const drag = sheetDrag.current;\n const panel = panelRef.current;\n sheetDrag.current = null;\n if (!drag || !panel) return;\n const dy = Math.max(0, event.clientY - drag.startY);\n panel.style.transform = '';\n if (dy > 110) dispatch({ type: 'SET_PANEL', open: false });\n };\n\n return (\n <div\n ref={panelRef}\n className={`rk-panel ${side}`}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label=\"Review feedback panel\"\n onKeyDown={onKeyDown}\n >\n <div\n className=\"rk-sheet-handle\"\n aria-hidden=\"true\"\n onPointerDown={onSheetHandleDown}\n onPointerMove={onSheetHandleMove}\n onPointerUp={onSheetHandleUp}\n onPointerCancel={onSheetHandleUp}\n />\n <div className=\"rk-panel-head\">\n <div>\n <div className=\"rk-panel-title\">Feedback</div>\n <div className=\"rk-panel-sub\">\n {items.length} item{items.length === 1 ? '' : 's'}\n {session.author ? ` · ${session.author}` : ''}\n {syncStatus !== 'disabled' && (\n <span className={`rk-sync rk-sync-${syncStatus}`}>\n <span className=\"rk-sync-dot\" />\n {syncStatus === 'online'\n ? `live${peers.length > 0 ? ` · ${peers.length} other${peers.length === 1 ? '' : 's'}` : ''}`\n : syncStatus === 'connecting'\n ? 'connecting…'\n : 'local only'}\n </span>\n )}\n {config.emblema && emblemaPush !== 'idle' && (\n <span\n className={`rk-sync rk-epush-${emblemaPush}`}\n title={\n emblemaPush === 'ok'\n ? 'Review items stream to Emblema automatically'\n : emblemaPush === 'sending'\n ? 'Sending items to Emblema…'\n : \"Emblema isn't reachable — items resend on the next change, or use Resend all in the menu\"\n }\n >\n <span className=\"rk-sync-dot\" />\n {emblemaPush === 'ok'\n ? 'emblema'\n : emblemaPush === 'sending'\n ? 'emblema…'\n : emblemaPush === 'rejected'\n ? 'emblema rejected'\n : 'emblema offline'}\n </span>\n )}\n </div>\n </div>\n <span className=\"rk-spacer\" />\n <div className=\"rk-menu-scope rk-menu-anchor\">\n <button\n type=\"button\"\n className=\"rk-icon-btn\"\n aria-label=\"Review session settings\"\n aria-expanded={settingsOpen}\n onClick={() => {\n const willOpen = !settingsOpen;\n setSettingsOpen(willOpen);\n setFilterOpen(false);\n if (willOpen && config.emblema) {\n setEmblemaAlive(null);\n void pingEmblema(config.emblema).then((port) => setEmblemaAlive(port !== null));\n }\n }}\n >\n <IconGear size={15} />\n </button>\n {settingsOpen && (\n <div className=\"rk-menu\" role=\"menu\" aria-label=\"Session settings\">\n {config.token && (\n <button\n type=\"button\"\n role=\"menuitemcheckbox\"\n aria-checked={sticky}\n className=\"rk-menu-item\"\n title=\"Stay in review mode in this tab even when the link parameter is gone (expires after a few hours)\"\n onClick={() => {\n const next = !sticky;\n setSticky(config.token, next);\n setStickyState(next);\n toast(dispatch, next ? 'Review stays on in this tab' : 'Review active only via the link', 'info');\n }}\n >\n <span className={`rk-menu-check${sticky ? ' rk-on' : ''}`} />\n Keep review on in this tab\n </button>\n )}\n {config.emblema && (\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"rk-menu-item\"\n disabled={emblemaSending}\n title=\"Items push to Emblema automatically as you review — this resends every open item on this page in one batch\"\n onClick={() => {\n const emblema = config.emblema;\n if (!emblema || emblemaSending) return;\n const open = items.filter((item) => item.status === 'open');\n if (open.length === 0) {\n toast(dispatch, 'No open items to send.', 'info');\n return;\n }\n setEmblemaSending(true);\n void sendToEmblema(session, open, emblema)\n .then((result) => {\n if (result.ok) {\n toast(dispatch, `${result.sent} item${result.sent === 1 ? '' : 's'} sent — approve in Emblema`, 'success');\n setSettingsOpen(false);\n } else if (result.reason === 'offline') {\n toast(dispatch, \"Emblema isn't running — start the app and try again.\", 'error');\n setEmblemaAlive(false);\n } else {\n toast(dispatch, `Emblema refused the batch${result.detail ? ` (${result.detail})` : ''}.`, 'error');\n }\n })\n .finally(() => setEmblemaSending(false));\n }}\n >\n <span\n className=\"rk-emblema-dot\"\n data-state={emblemaAlive === null ? 'unknown' : emblemaAlive ? 'live' : 'offline'}\n />\n {emblemaSending ? 'Resending…' : 'Resend all to Emblema'}\n </button>\n )}\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"rk-menu-item\"\n title={\n emblemaPairState === 'stale'\n ? 'The local sync agent is not answering — run `npx @satanwagen/reviewkit-cli serve` in the project'\n : 'Pair this project with the Emblema app via a sync key'\n }\n onClick={() => {\n setSettingsOpen(false);\n dispatch({ type: 'SET_EMBLEMA_CONNECT', open: true });\n }}\n >\n <span className=\"rk-emblema-dot\" data-state={emblemaPairState} />\n Connect to Emblema…\n <span className=\"rk-menu-count\">{emblemaPairLabel}</span>\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"rk-menu-item rk-menu-danger\"\n title=\"Turn the review layer off and return to the clean site\"\n onClick={() => deactivateReview()}\n >\n End review\n </button>\n </div>\n )}\n </div>\n <button\n type=\"button\"\n className=\"rk-icon-btn\"\n aria-label=\"Keyboard shortcuts\"\n onClick={() => dispatch({ type: 'SET_CHEATSHEET', open: true })}\n >\n <IconKeyboard size={15} />\n </button>\n <button\n type=\"button\"\n className=\"rk-icon-btn\"\n aria-label=\"Close panel\"\n onClick={() => dispatch({ type: 'SET_PANEL', open: false })}\n >\n <IconClose size={14} />\n </button>\n </div>\n\n <div className=\"rk-view-row\">\n <div className=\"rk-view-info\">\n <div className=\"rk-view-title\">Page view</div>\n </div>\n <div className=\"rk-seg rk-view-toggle\" role=\"group\" aria-label=\"Page view (P to toggle)\">\n <button\n type=\"button\"\n aria-pressed={!preview}\n title={`Show the page as it is in production${keyHint('view-toggle')}`}\n onClick={() => choosePreview(dispatch, false)}\n >\n Original\n </button>\n <button\n type=\"button\"\n aria-pressed={preview}\n title={`Show the page with your changes applied${keyHint('view-toggle')}`}\n onClick={() => choosePreview(dispatch, true)}\n >\n Edited\n </button>\n </div>\n </div>\n\n <div className=\"rk-panel-tools\">\n <button\n type=\"button\"\n className=\"rk-btn rk-btn-primary\"\n title={`Pick an element${keyHint('tool-select')}`}\n onClick={() => {\n dispatch({ type: 'SET_PANEL', open: false });\n dispatch({ type: 'SET_MODE', mode: 'pick' });\n }}\n >\n <IconTarget size={14} /> Pick an element\n </button>\n <div className=\"rk-search-row\">\n <div className=\"rk-search\">\n <IconSearch size={13} />\n <input\n ref={searchRef}\n className=\"rk-input\"\n placeholder=\"Search feedback…\"\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n aria-label=\"Search feedback items\"\n />\n </div>\n <div className=\"rk-menu-scope rk-menu-anchor\">\n <button\n type=\"button\"\n className=\"rk-btn rk-btn-ghost rk-filter-btn\"\n aria-expanded={filterOpen}\n aria-label=\"Filter items\"\n onClick={() => {\n setFilterOpen((open) => !open);\n setSettingsOpen(false);\n }}\n >\n <IconFilter size={13} />\n Filter\n {typeFilter.size + prioFilter.size + statusFilter.size > 0 && <span className=\"rk-badge-count\">{typeFilter.size + prioFilter.size + statusFilter.size}</span>}\n </button>\n {filterOpen && (\n <div className=\"rk-menu\" role=\"menu\" aria-label=\"Filter items\">\n <div className=\"rk-menu-title\">Type</div>\n {TYPE_FILTERS.map((type) => (\n <button\n key={type}\n type=\"button\"\n role=\"menuitemcheckbox\"\n aria-checked={typeFilter.has(type)}\n className=\"rk-menu-item\"\n onClick={() => {\n const next = new Set(typeFilter);\n if (next.has(type)) next.delete(type);\n else next.add(type);\n setTypeFilter(next);\n }}\n >\n <span className={`rk-menu-check${typeFilter.has(type) ? ' rk-on' : ''}`} />\n {iconForType(type, 12)}\n <span className=\"rk-menu-label\">{type}</span>\n <span className=\"rk-menu-count\">{typeCounts.get(type) ?? 0}</span>\n </button>\n ))}\n <div className=\"rk-menu-title\">Priority</div>\n {PRIORITY_FILTERS.map((priority) => (\n <button\n key={priority}\n type=\"button\"\n role=\"menuitemcheckbox\"\n aria-checked={prioFilter.has(priority)}\n className=\"rk-menu-item\"\n onClick={() => {\n const next = new Set(prioFilter);\n if (next.has(priority)) next.delete(priority);\n else next.add(priority);\n setPrioFilter(next);\n }}\n >\n <span className={`rk-menu-check${prioFilter.has(priority) ? ' rk-on' : ''}`} />\n <span className=\"rk-menu-label\">{PRIORITY_LABELS[priority]}</span>\n <span className=\"rk-menu-count\">{prioCounts.get(priority) ?? 0}</span>\n </button>\n ))}\n <div className=\"rk-menu-title\">Status</div>\n {STATUSES.map((status) => (\n <button\n key={status}\n type=\"button\"\n role=\"menuitemcheckbox\"\n aria-checked={statusFilter.has(status)}\n className=\"rk-menu-item\"\n onClick={() => {\n const next = new Set(statusFilter);\n if (next.has(status)) next.delete(status);\n else next.add(status);\n setStatusFilter(next);\n }}\n >\n <span className={`rk-menu-check${statusFilter.has(status) ? ' rk-on' : ''}`} />\n <span className={`rk-status-dot rk-st-${status}`} />\n <span className=\"rk-menu-label\">{status}</span>\n <span className=\"rk-menu-count\">{statusCounts.get(status) ?? 0}</span>\n </button>\n ))}\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"rk-menu-item rk-menu-clear\"\n disabled={typeFilter.size + prioFilter.size + statusFilter.size === 0}\n onClick={() => {\n setTypeFilter(new Set());\n setPrioFilter(new Set());\n setStatusFilter(new Set());\n setFilterOpen(false);\n }}\n >\n Clear filters\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n\n {preview && unapplied > 0 && (\n <div className=\"rk-unplaced\" role=\"status\">\n {unapplied} saved change{unapplied === 1 ? '' : 's'} couldn’t be placed on the current page — the\n page has changed since they were captured.\n </div>\n )}\n\n <div className=\"rk-panel-list\">\n {filtered.length === 0 ? (\n <div className=\"rk-empty\">\n <div className=\"rk-empty-art\">\n <IconTarget size={22} />\n </div>\n <div className=\"rk-empty-title\">{items.length === 0 ? 'Nothing here yet' : 'No matches'}</div>\n <div className=\"rk-empty-text\">\n {items.length === 0\n ? 'Choose “Pick an element”, then click anything on the page. Your suggestions collect here, ready to hand off.'\n : 'Try a different search, or clear the filters.'}\n </div>\n </div>\n ) : (\n groups.map(([route, entries]) => (\n <div key={route}>\n <div className=\"rk-group-title\">{route}</div>\n {entries.map(({ item, number }) => {\n const active = item.id === activeItemId;\n const orphan = orphanIds.has(item.id);\n const hiddenEl = hiddenIds.has(item.id);\n return (\n <div key={item.id}>\n <div\n data-item-id={item.id}\n className={`rk-item${active ? ' rk-active' : ''}${orphan ? ' rk-orphan' : ''}`}\n role=\"button\"\n tabIndex={0}\n onClick={() => jumpTo(item)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n jumpTo(item);\n }\n }}\n >\n <span className=\"rk-item-num\">{number}</span>\n <span className=\"rk-item-icon\">{iconForType(item.type)}</span>\n <span className=\"rk-item-body\">\n <span className=\"rk-item-snippet\">\n {item.target.tagName} · {item.target.textSnippet || item.target.selector}\n </span>\n <span className=\"rk-item-change\">{changeSummary(item)}</span>\n <span className=\"rk-item-meta\">\n <span className=\"rk-author\" title={new Date(item.createdAt).toLocaleString()}>\n <span\n className=\"rk-author-dot\"\n style={{ background: item.author?.color ?? 'var(--rk-fg-faint)' }}\n />\n {item.author?.name ?? 'Unknown'}\n <span className=\"rk-time\"> · {timeAgo(item.createdAt)}</span>\n </span>\n {item.priority === 'must' && <span className=\"rk-badge-mini rk-must\">must</span>}\n {item.status !== 'open' && (\n <span className={`rk-badge-mini rk-${item.status}`}>{item.status}</span>\n )}\n {orphan && <span className=\"rk-badge-mini rk-orphaned\">unanchored</span>}\n {hiddenEl && (\n <span\n className=\"rk-badge-mini rk-hidden-el\"\n title=\"The element exists but isn’t visible on the page right now (closed modal, menu or section)\"\n >\n hidden\n </span>\n )}\n {item.note && <span className=\"rk-badge-mini\">note</span>}\n {peers\n .filter((peer) => peer.typingActive && peer.typingItemId === item.id)\n .map((peer) => (\n <span key={peer.id} className=\"rk-badge-mini\" style={{ color: peer.color }}>\n {peer.name || 'peer'} is writing…\n </span>\n ))}\n </span>\n </span>\n <span className=\"rk-item-actions\">\n <button\n type=\"button\"\n className=\"rk-icon-btn\"\n aria-label={`Delete item ${number}`}\n onClick={(event) => {\n event.stopPropagation();\n dispatch({ type: 'DELETE_ITEM', id: item.id });\n toast(\n dispatch,\n syncStatus !== 'disabled' ? 'Item deleted for the whole room' : 'Item deleted',\n 'info',\n );\n }}\n >\n <IconTrash size={13} />\n </button>\n </span>\n </div>\n {active && (\n <div className=\"rk-item-edit\">\n <div className=\"rk-detail-byline\" title={new Date(item.createdAt).toLocaleString()}>\n <span\n className=\"rk-author-dot\"\n style={{ background: item.author?.color ?? 'var(--rk-fg-faint)' }}\n />\n {item.author?.name ?? 'Unknown'} · {timeAgo(item.createdAt)}\n </div>\n {isCopyItem(item) && <CopyDiff before={item.payload.before} after={item.payload.after} />}\n {isImageItem(item) && (\n <ImageDetail\n beforeSrc={item.payload.beforeSrc}\n afterSrc={item.payload.afterSrc}\n afterDataUrl={item.payload.afterDataUrl}\n />\n )}\n {isKnownItemType(item.type) && item.type !== 'move' && (\n <textarea\n className=\"rk-textarea\"\n rows={2}\n aria-label=\"Proposed change\"\n value={payloadText(item)}\n onChange={(event) =>\n dispatch({ type: 'UPDATE_ITEM', id: item.id, patch: withPayloadText(item, event.target.value) })\n }\n />\n )}\n <input\n className=\"rk-input\"\n placeholder=\"Note (optional)\"\n aria-label=\"Note\"\n value={item.note ?? ''}\n onChange={(event) =>\n dispatch({ type: 'UPDATE_ITEM', id: item.id, patch: { note: event.target.value } })\n }\n />\n <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>\n <div className=\"rk-seg\" role=\"group\" aria-label=\"Priority\">\n <button\n type=\"button\"\n aria-pressed={item.priority === 'must'}\n onClick={() => dispatch({ type: 'UPDATE_ITEM', id: item.id, patch: { priority: 'must' } })}\n >\n Must\n </button>\n <button\n type=\"button\"\n aria-pressed={item.priority === 'nice'}\n onClick={() => dispatch({ type: 'UPDATE_ITEM', id: item.id, patch: { priority: 'nice' } })}\n >\n Nice\n </button>\n </div>\n <div className=\"rk-seg\" role=\"group\" aria-label=\"Status\">\n {STATUSES.map((status) => (\n <button\n key={status}\n type=\"button\"\n aria-pressed={item.status === status}\n onClick={() => dispatch({ type: 'SET_ITEM_STATUS', id: item.id, status })}\n >\n {status}\n </button>\n ))}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n })}\n </div>\n ))\n )}\n </div>\n\n <div className=\"rk-panel-foot\">\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={onExport} disabled={items.length === 0}>\n <IconDownload size={13} /> Export\n </button>\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={() => void onCopy()} disabled={items.length === 0}>\n <IconCopyClipboard size={13} /> Copy\n </button>\n <button type=\"button\" className=\"rk-btn rk-btn-ghost\" onClick={() => importRef.current?.click()}>\n <IconUpload size={13} /> Import\n </button>\n <span className=\"rk-spacer\" />\n {undoStack.length > 0 && (\n <button type=\"button\" className=\"rk-icon-btn\" aria-label=\"Undo last change (⌘Z)\" onClick={() => dispatch({ type: 'UNDO' })}>\n <IconUndo size={14} />\n </button>\n )}\n <button\n type=\"button\"\n className=\"rk-btn rk-btn-ghost\"\n style={{ color: 'var(--rk-danger)' }}\n onClick={onClear}\n disabled={items.length === 0}\n >\n Clear\n </button>\n <button\n type=\"button\"\n className=\"rk-btn rk-btn-ghost\"\n title=\"Turn the review layer off in this tab and return to the clean site (your items stay saved)\"\n onClick={() => deactivateReview()}\n >\n Exit review\n </button>\n <input\n ref={importRef}\n type=\"file\"\n accept=\"application/json,.json\"\n hidden\n onChange={(event) => {\n const file = event.target.files?.item(0);\n if (file) void onImportFile(file);\n event.target.value = '';\n }}\n />\n </div>\n </div>\n );\n}\n","/** Presence: peer avatars (toolbar), live cursors, remote selection rings. */\n\nimport { useEffect, useRef } from 'react';\nimport { useStore } from '../store';\nimport { isPluginElement } from '../target';\n\nfunction initials(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '·';\n if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n}\n\n/** Compact avatar row for the toolbar capsule. */\nexport function PresenceStrip() {\n const { peers, syncStatus } = useStore();\n if (syncStatus === 'disabled' || peers.length === 0) return null;\n return (\n <div className=\"rk-presence\" aria-label={`${peers.length} reviewer${peers.length === 1 ? '' : 's'} online`}>\n {peers.slice(0, 5).map((peer) => (\n <span\n key={peer.id}\n className=\"rk-avatar\"\n style={{ background: peer.color }}\n title={peer.name || 'Reviewer'}\n >\n {initials(peer.name)}\n </span>\n ))}\n {peers.length > 5 && <span className=\"rk-avatar rk-avatar-more\">+{peers.length - 5}</span>}\n </div>\n );\n}\n\n/** Fixed layer with remote cursors + rings around remotely selected elements. */\nexport function PeerCursors() {\n const { peers } = useStore();\n const ringRefs = useRef(new Map<string, HTMLDivElement>());\n const cursorRefs = useRef(new Map<string, HTMLDivElement>());\n const motion = useRef(\n new Map<string, { cx: number; cy: number; lastTx: number; lastSeen: number; hasPos: boolean }>(),\n );\n const peersRef = useRef(peers);\n const seen = useRef(new Map<string, string>());\n // Track cursor-change timestamps so idle cursors can fade out gracefully.\n for (const peer of peers) {\n const sig = peer.cursor ? `${peer.cursor.x},${peer.cursor.y},${peer.cursor.ox},${peer.cursor.oy}` : '';\n if (seen.current.get(peer.id) !== sig) {\n seen.current.set(peer.id, sig);\n const m = motion.current.get(peer.id);\n if (m) m.lastSeen = performance.now();\n }\n }\n peersRef.current = peers;\n\n useEffect(() => {\n const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n let raf = 0;\n let last = performance.now();\n const resolved = new Map<string, { sel: string; el: Element | null; at: number }>();\n\n const tick = () => {\n raf = requestAnimationFrame(tick);\n const now = performance.now();\n const dt = Math.min(64, now - last);\n last = now;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n for (const peer of peersRef.current) {\n // remote selection ring (unchanged behavior)\n const ring = ringRefs.current.get(peer.id);\n if (ring) {\n let rect: DOMRect | null = null;\n if (peer.selecting) {\n try {\n const el = document.querySelector(peer.selecting);\n if (el && !isPluginElement(el)) rect = el.getBoundingClientRect();\n } catch {\n /* stale selector */\n }\n }\n if (rect && rect.width > 0) {\n ring.style.opacity = '1';\n ring.style.transform = `translate3d(${rect.left - 3}px, ${rect.top - 3}px, 0)`;\n ring.style.width = `${rect.width + 6}px`;\n ring.style.height = `${rect.height + 6}px`;\n } else {\n ring.style.opacity = '0';\n }\n }\n\n const chip = cursorRefs.current.get(peer.id);\n if (!chip) continue;\n const cursor = peer.cursor;\n if (!cursor) {\n chip.style.opacity = '0';\n continue;\n }\n\n // Target position: element anchor first (maps to the same CONTENT on\n // any layout), normalized document fraction as the dimmed fallback.\n let tx: number | null = null;\n let ty: number | null = null;\n let approx = false;\n if (cursor.sel) {\n let entry = resolved.get(peer.id);\n if (!entry || entry.sel !== cursor.sel || (entry.el && !entry.el.isConnected) || now - entry.at > 800) {\n let el: Element | null = null;\n try {\n el = document.querySelector(cursor.sel);\n } catch {\n el = null;\n }\n entry = { sel: cursor.sel, el: el && !isPluginElement(el) ? el : null, at: now };\n resolved.set(peer.id, entry);\n }\n if (entry.el) {\n const rect = entry.el.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) {\n tx = rect.left + (cursor.ox ?? 0.5) * rect.width;\n ty = rect.top + (cursor.oy ?? 0.5) * rect.height;\n }\n }\n }\n if (tx === null || ty === null) {\n const doc = document.documentElement;\n tx = cursor.x * Math.max(1, doc.scrollWidth) - window.scrollX;\n ty = cursor.y * Math.max(1, doc.scrollHeight) - window.scrollY;\n approx = true;\n }\n\n // Off-viewport → clamp to the edge as a subtle direction indicator.\n const margin = 14;\n const offscreen = tx < 0 || tx > vw || ty < 0 || ty > vh;\n const px = Math.min(Math.max(tx, margin), vw - margin);\n const py = Math.min(Math.max(ty, margin), vh - margin);\n\n let m = motion.current.get(peer.id);\n if (!m) {\n m = { cx: px, cy: py, lastTx: px, lastSeen: now, hasPos: false };\n motion.current.set(peer.id, m);\n }\n if (!m.hasPos || reduced) {\n m.cx = px;\n m.cy = py;\n m.hasPos = true;\n } else {\n // Critically-damped-ish chase: smooth glide, gentle settle.\n const k = 1 - Math.exp(-dt / 60);\n m.cx += (px - m.cx) * k;\n m.cy += (py - m.cy) * k;\n }\n const velocity = m.cx - m.lastTx;\n m.lastTx = m.cx;\n\n const idleMs = now - m.lastSeen;\n const idleFade = idleMs > 6000 ? 0 : idleMs > 4000 ? 0.4 : 1;\n const baseOpacity = offscreen ? 0.6 : approx ? 0.55 : 1;\n chip.style.opacity = String(Math.min(baseOpacity, idleFade));\n chip.style.transform = `translate3d(${m.cx}px, ${m.cy}px, 0)`;\n chip.classList.toggle('rk-peer-edge', offscreen);\n const svg = chip.querySelector('svg');\n if (svg) {\n const tilt = reduced ? 0 : Math.max(-16, Math.min(16, velocity * 1.6));\n (svg as SVGElement).style.transform = `rotate(${tilt}deg)`;\n }\n }\n };\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, []);\n\n if (peers.length === 0) return null;\n\n return (\n <>\n {peers.map((peer) => (\n <div\n key={`ring-${peer.id}`}\n ref={(el) => {\n if (el) ringRefs.current.set(peer.id, el);\n else ringRefs.current.delete(peer.id);\n }}\n className=\"rk-peer-ring\"\n style={{ borderColor: peer.color, opacity: 0 }}\n />\n ))}\n {peers.map((peer, index) => (\n <div\n key={`cursor-${peer.id}`}\n ref={(el) => {\n if (el) cursorRefs.current.set(peer.id, el);\n else cursorRefs.current.delete(peer.id);\n }}\n className=\"rk-peer-cursor\"\n style={{ opacity: 0 }}\n >\n <svg width=\"14\" height=\"18\" viewBox=\"0 0 14 18\" aria-hidden=\"true\">\n <path d=\"M1 1l12 7.5-5.2 1.2L5 16z\" fill={peer.color} stroke=\"rgba(0,0,0,0.25)\" strokeWidth=\"1\" />\n </svg>\n <span\n className=\"rk-peer-name\"\n style={{ background: peer.color, marginTop: 12 + (index % 3) * 16 }}\n >\n {peer.name || 'Reviewer'}\n {peer.typingActive ? ' · writing…' : ''}\n </span>\n </div>\n ))}\n </>\n );\n}\n","/**\n * `/` quick comment — a tiny composer that opens right at the pointer.\n * Enter saves a normal comment item anchored to the element + fractional\n * offset under the cursor (so it maps to the same content on any layout).\n * Text starting with `/` runs a room-wide visual effect instead of saving;\n * unknown commands simply save as a comment.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { KeyboardEvent as ReactKeyboardEvent } from 'react';\nimport type { CommentItem } from '../../schema';\nimport { isEffectCommand } from '../effectCatalog';\nimport { runEffect } from '../effectsLazy';\nimport { rkId } from '../id';\nimport { currentAuthor } from '../identity';\nimport { layerRoot } from '../pointer';\nimport { sendEffectToRoom } from '../sync';\nimport { toast, useDispatch, useStore } from '../store';\nimport { IconComment } from './icons';\n\nexport function QuickComment() {\n const { quick } = useStore();\n if (!quick) return null;\n // Keyed per opening: every `/` starts a FRESH composer (state can't leak\n // or race between openings — the old one fully unmounts).\n return <QuickComposerCard key={quick.id} quick={quick} />;\n}\n\nfunction QuickComposerCard({ quick }: { quick: NonNullable<ReturnType<typeof useStore>['quick']> }) {\n const { route, session } = useStore();\n const dispatch = useDispatch();\n const [text, setText] = useState('');\n const fieldRef = useRef<HTMLTextAreaElement | null>(null);\n\n useEffect(() => {\n const field = fieldRef.current;\n if (!field) return;\n field.focus();\n // Re-assert on the next frame — the host page's own handlers for the\n // triggering event can steal focus back after we set it.\n const raf = requestAnimationFrame(() => {\n if ((field.getRootNode() as ShadowRoot | Document).activeElement !== field) field.focus();\n });\n return () => cancelAnimationFrame(raf);\n }, []);\n\n const close = () => dispatch({ type: 'CLOSE_QUICK' });\n\n const save = () => {\n // Read the field directly — a fast type-then-Enter can outrun the\n // controlled-state round trip and leave `text` one keystroke behind.\n const trimmed = (fieldRef.current?.value ?? text).trim();\n if (trimmed === '') {\n close();\n return;\n }\n const command = /^\\/(\\S+)$/.exec(trimmed);\n if (command && isEffectCommand(command[1])) {\n // An effect must never leave the composer stuck open or throw upward.\n try {\n runEffect(command[1], layerRoot);\n sendEffectToRoom(command[1]);\n } catch {\n /* effects are best-effort fun */\n }\n close();\n return;\n }\n const item: CommentItem = {\n id: rkId(),\n createdAt: new Date().toISOString(),\n author: currentAuthor(session?.author),\n type: 'comment',\n status: 'open',\n route,\n target: quick.target,\n payload: { text: trimmed },\n priority: 'nice',\n };\n dispatch({ type: 'ADD_ITEM', item });\n toast(dispatch, 'Comment saved', 'success');\n close();\n };\n\n const onKeyDown = (event: ReactKeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n save();\n } else if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n close();\n }\n };\n\n const x = Math.min(Math.max(quick.x, 8), window.innerWidth - 288);\n const y = Math.min(Math.max(quick.y + 12, 8), window.innerHeight - 108);\n\n return (\n <div className=\"rk-quick\" style={{ transform: `translate3d(${x}px, ${y}px, 0)` }} role=\"dialog\" aria-label=\"Quick comment\">\n <div className=\"rk-quick-head\">\n <IconComment size={12} />\n <span>Comment here</span>\n <span className=\"rk-hint\">\n <span className=\"rk-kbd\">↵</span> save · <span className=\"rk-kbd\">esc</span> cancel\n </span>\n </div>\n <textarea\n ref={fieldRef}\n className=\"rk-textarea\"\n rows={2}\n placeholder=\"Say it…\"\n value={text}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={onKeyDown}\n />\n </div>\n );\n}\n","/** Pick mode: rAF-tracked hover outline + label chip, click-to-select. */\n\nimport { useEffect, useRef, useState } from 'react';\nimport { openEditorFor } from '../shortcuts';\nimport { captureTarget, describeElement, findImage, isPluginElement, pickElementAt, pointAnchor } from '../target';\nimport { toast, useDispatch, useStore } from '../store';\n\n/** Applies a viewport rect to a fixed-position ring element. */\nfunction applyRect(el: HTMLElement | null, rect: DOMRect | null, pad = 3): void {\n if (!el) return;\n if (!rect) {\n el.style.opacity = '0';\n return;\n }\n el.style.opacity = '1';\n el.style.transform = `translate3d(${rect.left - pad}px, ${rect.top - pad}px, 0)`;\n el.style.width = `${rect.width + pad * 2}px`;\n el.style.height = `${rect.height + pad * 2}px`;\n}\n\nexport function PickLayer() {\n const { mode, selection, tool } = useStore();\n const dispatch = useDispatch();\n const [hovered, setHovered] = useState<HTMLElement | null>(null);\n const outlineRef = useRef<HTMLDivElement | null>(null);\n const labelRef = useRef<HTMLDivElement | null>(null);\n const selectRef = useRef<HTMLDivElement | null>(null);\n const hoveredRef = useRef<HTMLElement | null>(null);\n hoveredRef.current = hovered;\n\n const picking = mode === 'pick';\n\n // Track pointer + intercept clicks while picking.\n useEffect(() => {\n if (!picking) {\n setHovered(null);\n return;\n }\n const onMove = (event: MouseEvent) => {\n if (isPluginElement(event.target)) {\n setHovered(null);\n return;\n }\n // Same resolution as the click below — the highlight always shows\n // exactly what a click would pick.\n setHovered(pickElementAt(event.clientX, event.clientY));\n };\n const onClick = (event: MouseEvent) => {\n if (isPluginElement(event.target)) return;\n event.preventDefault();\n event.stopPropagation();\n const el = pickElementAt(event.clientX, event.clientY);\n if (!el) return;\n // Pin lands where the user clicked, even inside a large target.\n const target = captureTarget(el);\n target.anchor = pointAnchor(el, event.clientX, event.clientY);\n // Armed tool: the click applies it right away, no toolbar detour.\n if (tool === 'image') {\n if (!findImage(el)) {\n toast(dispatch, 'That element has no image — click a picture, or press T to rewrite text.', 'info');\n return;\n }\n openEditorFor(dispatch, 'image', el, target);\n } else if (tool === 'copy' || tool === 'comment') {\n openEditorFor(dispatch, tool, el, target);\n } else {\n dispatch({ type: 'SELECT', selection: { element: el, target } });\n }\n };\n const swallow = (event: Event) => {\n if (!isPluginElement(event.target)) event.preventDefault();\n };\n document.addEventListener('mousemove', onMove, true);\n document.addEventListener('click', onClick, true);\n document.addEventListener('mousedown', swallow, true);\n return () => {\n document.removeEventListener('mousemove', onMove, true);\n document.removeEventListener('click', onClick, true);\n document.removeEventListener('mousedown', swallow, true);\n };\n }, [picking, tool, dispatch]);\n\n // Page cursor mirrors the armed tool.\n useEffect(() => {\n if (!picking) return;\n const body = document.body;\n const prev = body.style.cursor;\n body.style.cursor = tool === 'copy' ? 'text' : 'crosshair';\n return () => {\n body.style.cursor = prev;\n if (body.getAttribute('style') === '') body.removeAttribute('style');\n };\n }, [picking, tool]);\n\n // rAF loop: keep hover outline, label and selection ring glued to their elements.\n useEffect(() => {\n let raf = 0;\n const tick = () => {\n const hoverEl = hoveredRef.current;\n const hoverRect = hoverEl && hoverEl.isConnected ? hoverEl.getBoundingClientRect() : null;\n applyRect(outlineRef.current, picking ? hoverRect : null);\n const label = labelRef.current;\n if (label) {\n if (picking && hoverRect) {\n label.style.opacity = '1';\n const above = hoverRect.top > 34;\n const x = Math.min(Math.max(hoverRect.left, 8), window.innerWidth - label.offsetWidth - 8);\n const y = above ? hoverRect.top - 30 : Math.min(hoverRect.bottom + 8, window.innerHeight - 34);\n label.style.transform = `translate3d(${x}px, ${y}px, 0)`;\n } else {\n label.style.opacity = '0';\n }\n }\n const selected = selection?.element ?? null;\n const selectedRect = selected && selected.isConnected ? selected.getBoundingClientRect() : null;\n applyRect(selectRef.current, selectedRect);\n raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [picking, selection]);\n\n return (\n <>\n {picking && (\n <>\n <div ref={outlineRef} className=\"rk-outline\" style={{ opacity: 0 }} />\n <div ref={labelRef} className=\"rk-outline-label\" style={{ opacity: 0 }}>\n {hovered ? (\n <>\n <span className=\"rk-tag\">{hovered.tagName.toLowerCase()}</span>\n <span>{describeElement(hovered).replace(/^[a-z0-9]+ · /, '')}</span>\n </>\n ) : (\n <span>Pick an element</span>\n )}\n </div>\n </>\n )}\n {selection && <div ref={selectRef} className=\"rk-select-ring\" style={{ opacity: 0 }} />}\n </>\n );\n}\n","/** Numbered pins anchored to reviewed elements; clustering, orphan tray. */\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport type { ReviewItem } from '../../schema';\nimport { isElementVisible, resolveTarget } from '../target';\nimport { itemMatchesFilter, useDispatch, useStore } from '../store';\nimport { IconUnlink } from './icons';\n\n/** Tooltip wording per status (Emblema spellings in parentheses). */\nconst STATUS_LABELS: Record<string, string> = {\n open: 'open',\n accepted: 'accepted',\n rejected: 'rejected (dismissed)',\n applied: 'applied (fixed)',\n};\n\ninterface Cluster {\n key: string;\n ids: string[];\n numbers: number[];\n}\n\nconst CLUSTER_RADIUS = 26;\nconst RERESOLVE_MS = 800;\n\nexport function Pins() {\n const { session, route, activeItemId, editor, mode, filter } = useStore();\n const dispatch = useDispatch();\n const [clusters, setClusters] = useState<Cluster[]>([]);\n const [orphanCount, setOrphanCount] = useState(0);\n const wrapRefs = useRef(new Map<string, HTMLDivElement>());\n const visibleCache = useRef(new Map<string, boolean>());\n const highlightRef = useRef<HTMLDivElement | null>(null);\n const hoveredItems = useRef<string[] | null>(null);\n const elementCache = useRef(new Map<string, Element | null>());\n const lastResolve = useRef(0);\n const [newestId, setNewestId] = useState<string | null>(null);\n const prevCount = useRef(0);\n\n const items = useMemo(() => {\n const all = session?.items ?? [];\n return all\n .map((item, index) => ({ item, number: index + 1 }))\n .filter(({ item }) => item.route === route);\n }, [session, route]);\n\n // Fresh per render on purpose: REMOTE_STATUS patches must restyle pins the\n // moment they arrive, without waiting for a recluster.\n const byId = new Map<string, ReviewItem>(items.map(({ item }) => [item.id, item]));\n\n // Pulse the newest pin briefly after a capture.\n useEffect(() => {\n const count = session?.items.length ?? 0;\n if (count > prevCount.current && session && count > 0) {\n const id = session.items[count - 1].id;\n setNewestId(id);\n const timer = window.setTimeout(() => setNewestId(null), 3000);\n prevCount.current = count;\n return () => window.clearTimeout(timer);\n }\n prevCount.current = count;\n }, [session]);\n\n // rAF loop: resolve targets (throttled), position pins, recluster on change.\n useEffect(() => {\n let raf = 0;\n let lastSignature = '';\n const tick = (time: number) => {\n raf = requestAnimationFrame(tick);\n const cache = elementCache.current;\n const shouldResolve = time - lastResolve.current > RERESOLVE_MS;\n if (shouldResolve) lastResolve.current = time;\n\n const points: { id: string; number: number; x: number; y: number }[] = [];\n let orphans = 0;\n for (const { item, number } of items) {\n let el = cache.get(item.id);\n if (el === undefined || (el !== null && !el.isConnected) || (el === null && shouldResolve)) {\n el = resolveTarget(item.target)?.element ?? null;\n cache.set(item.id, el);\n // Real visibility (display/visibility/closed containers), refreshed\n // on the throttled resolve tick — not every frame.\n visibleCache.current.set(\n item.id,\n el !== null && isElementVisible(el),\n );\n } else if (shouldResolve) {\n visibleCache.current.set(item.id, el !== null && isElementVisible(el));\n }\n if (!el || !el.isConnected || visibleCache.current.get(item.id) === false) {\n orphans++;\n continue;\n }\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) {\n orphans++;\n continue;\n }\n // Cursor-placed comments carry a fractional anchor inside the box.\n const anchor = item.target.anchor;\n const px = anchor ? rect.left + anchor.ox * rect.width : rect.right - 4;\n const py = anchor ? rect.top + anchor.oy * rect.height : rect.top + 4;\n points.push({ id: item.id, number, x: px, y: py });\n }\n\n // Greedy clustering by proximity.\n const groups: { x: number; y: number; entries: typeof points }[] = [];\n for (const point of points) {\n const group = groups.find((g) => Math.hypot(g.x - point.x, g.y - point.y) < CLUSTER_RADIUS);\n if (group) group.entries.push(point);\n else groups.push({ x: point.x, y: point.y, entries: [point] });\n }\n const next: Cluster[] = groups.map((group) => ({\n key: group.entries.map((entry) => entry.id).join(','),\n ids: group.entries.map((entry) => entry.id),\n numbers: group.entries.map((entry) => entry.number),\n }));\n const signature = `${next.map((cluster) => cluster.key).join('|')}#${orphans}`;\n if (signature !== lastSignature) {\n lastSignature = signature;\n setClusters(next);\n setOrphanCount(orphans);\n }\n // Position rendered pins directly (no per-frame React work).\n for (const group of groups) {\n const key = group.entries.map((entry) => entry.id).join(',');\n const el = wrapRefs.current.get(key);\n if (el) el.style.transform = `translate3d(${group.x}px, ${group.y}px, 0)`;\n }\n // Highlight ring for the hovered pin's element(s).\n const ring = highlightRef.current;\n if (ring) {\n const ids = hoveredItems.current;\n const el = ids && ids.length > 0 ? (cache.get(ids[0]) ?? null) : null;\n if (el && el.isConnected) {\n const rect = el.getBoundingClientRect();\n ring.style.opacity = '1';\n ring.style.transform = `translate3d(${rect.left - 3}px, ${rect.top - 3}px, 0)`;\n ring.style.width = `${rect.width + 6}px`;\n ring.style.height = `${rect.height + 6}px`;\n } else {\n ring.style.opacity = '0';\n }\n }\n };\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [items]);\n\n if (!session || items.length === 0 || editor !== null) {\n return null;\n }\n // While picking, pins stay visible but click-through, so they never block\n // element selection underneath.\n const picking = mode === 'pick';\n\n const openPanelAt = (id: string) => {\n dispatch({ type: 'SET_ACTIVE_ITEM', id });\n dispatch({ type: 'SET_PANEL', open: true });\n };\n\n return (\n <>\n <div ref={highlightRef} className=\"rk-hl-ring\" style={{ opacity: 0 }} />\n {clusters.map((cluster) => {\n const isCluster = cluster.ids.length > 1;\n const isActive = activeItemId !== null && cluster.ids.includes(activeItemId);\n const isNew = newestId !== null && cluster.ids.includes(newestId);\n const members = cluster.ids.map((id) => byId.get(id)).filter((item): item is ReviewItem => item !== undefined);\n // Uniform status colors the pin; a mixed cluster stays neutral.\n const statuses = new Set(members.map((item) => item.status));\n const status = statuses.size === 1 ? members[0]?.status : undefined;\n // Panel filters: a pin with no matching member dims out of the way.\n const dimmed = filter !== null && members.length > 0 && !members.some((item) => itemMatchesFilter(item, filter));\n const statusHint = isCluster\n ? status\n ? ` · all ${STATUS_LABELS[status] ?? status}`\n : ''\n : ` · ${STATUS_LABELS[members[0]?.status ?? 'open'] ?? members[0]?.status}`;\n return (\n <div\n key={cluster.key}\n ref={(el) => {\n if (el) wrapRefs.current.set(cluster.key, el);\n else wrapRefs.current.delete(cluster.key);\n }}\n className={`rk-pin-wrap${picking ? ' rk-pin-ghost' : ''}`}\n >\n <button\n type=\"button\"\n className={`rk-pin${isCluster ? ' rk-cluster' : ''}${isActive ? ' rk-active' : ''}${isNew ? ' rk-new' : ''}${status ? ` rk-st-${status}` : ''}${dimmed ? ' rk-dim' : ''}`}\n style={{ pointerEvents: 'auto' }}\n title={\n isCluster\n ? `${cluster.ids.length} feedback items here${statusHint}`\n : `Feedback item ${cluster.numbers[0]}${statusHint}`\n }\n aria-label={\n isCluster\n ? `${cluster.ids.length} feedback items here${statusHint}`\n : `Feedback item ${cluster.numbers[0]}${statusHint}`\n }\n onMouseEnter={() => {\n hoveredItems.current = cluster.ids;\n }}\n onMouseLeave={() => {\n hoveredItems.current = null;\n }}\n onClick={() => openPanelAt(cluster.ids[0])}\n >\n {isCluster ? `+${cluster.ids.length}` : cluster.numbers[0]}\n </button>\n </div>\n );\n })}\n {orphanCount > 0 && (\n <button\n type=\"button\"\n className=\"rk-tray\"\n style={{ bottom: 16, left: '50%', transform: 'translateX(-50%)' }}\n onClick={() => dispatch({ type: 'SET_PANEL', open: true })}\n >\n <IconUnlink size={13} />\n {orphanCount} unanchored item{orphanCount === 1 ? '' : 's'}\n </button>\n )}\n </>\n );\n}\n","/**\n * Floating action toolbar. Docked bottom-center (~50px up) by default,\n * freely draggable\n * (mouse/touch, whole surface — a >6px move is a drag, less is a click),\n * with magnetic snapping to edges and the horizontal center. The position\n * persists in localStorage across reloads and pages; double-click the grip\n * resets it, arrow keys on the focused grip nudge it. Dragging moves the\n * element purely via the `translate` property — no layout work per move.\n */\n\nimport { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { clampPos, readStoredPos, snapClampPos, storePos } from '../dragPosition';\nimport type { Pos } from '../dragPosition';\nimport type { KeyboardEvent as ReactKeyboardEvent, MouseEvent as ReactMouseEvent, PointerEvent as ReactPointerEvent } from 'react';\nimport type { EditorKind } from '../store';\nimport { useDispatch, useStore } from '../store';\nimport type { ToolKind } from '../store';\nimport { revertElementPreview } from '../preview';\nimport { keyHint, shortcutTitle } from '../shortcuts';\nimport { findImage } from '../target';\nimport { PresenceStrip } from './Presence';\nimport {\n IconClose,\n IconComment,\n IconImage,\n IconMove,\n IconStyle,\n IconTarget,\n IconText,\n IconTrash,\n} from './icons';\n\nconst TOOLS: Array<{ tool: ToolKind; hintId: string; label: string; icon: (size: number) => React.ReactNode }> = [\n { tool: 'select', hintId: 'tool-select', label: 'Select', icon: (n) => <IconTarget size={n} /> },\n { tool: 'copy', hintId: 'tool-copy', label: 'Rewrite text', icon: (n) => <IconText size={n} /> },\n { tool: 'comment', hintId: 'tool-comment', label: 'Comment', icon: (n) => <IconComment size={n} /> },\n { tool: 'image', hintId: 'tool-image', label: 'Replace image', icon: (n) => <IconImage size={n} /> },\n];\n\nconst POS_KEY = 'review-kit:toolbar-pos';\nconst DRAG_THRESHOLD = 6;\n\nexport function Toolbar() {\n const { selection, editor, peers, syncStatus, mode, tool } = useStore();\n const hasPeers = syncStatus !== 'disabled' && peers.length > 0;\n const dispatch = useDispatch();\n const ref = useRef<HTMLDivElement | null>(null);\n const [pos, setPos] = useState<Pos | null>(() => readStoredPos(POS_KEY));\n const drag = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n baseX: number;\n baseY: number;\n moved: boolean;\n lastDx: number;\n lastDy: number;\n } | null>(null);\n const [dragging, setDragging] = useState(false);\n const justDragged = useRef(false);\n\n // The toolbar (with all tools) is visible for the WHOLE review session;\n // it only steps aside while an editor card owns the screen.\n const visible = editor === null || selection !== null;\n\n const applyPos = (next: Pos | null, persist: boolean) => {\n // Back to the CSS default: the manually-set inline bottom (React never\n // tracked it) must go, or \\`bottom: auto\\` would beat the stylesheet.\n if (next === null && ref.current) ref.current.style.bottom = '';\n setPos(next);\n if (persist) storePos(POS_KEY, next);\n };\n\n // Keep a custom position on-screen when the viewport or content changes.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || pos === null) return;\n // Clamp only — snapping here would fight keyboard nudges near an edge.\n const clamped = clampPos(pos.x, pos.y, el.offsetWidth, el.offsetHeight);\n if (clamped.x !== pos.x || clamped.y !== pos.y) applyPos(clamped, true);\n }, [pos, selection, hasPeers, visible]);\n\n useEffect(() => {\n const onResize = () => {\n const el = ref.current;\n const current = readStoredPos(POS_KEY);\n if (!el || !current) return;\n const clamped = clampPos(current.x, current.y, el.offsetWidth, el.offsetHeight);\n if (clamped.x !== current.x || clamped.y !== current.y) applyPos(clamped, true);\n };\n window.addEventListener('resize', onResize);\n return () => window.removeEventListener('resize', onResize);\n }, []);\n\n if (!visible) return null;\n\n // Window-level move/up listeners (attached on pointerdown): pointer capture\n // would reroute the eventual click to the toolbar and break its buttons,\n // and without it fast pointers escape the element before the threshold.\n const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>) => {\n const el = ref.current;\n if (!el || event.button !== 0) return;\n const rect = el.getBoundingClientRect();\n const state = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n baseX: rect.left,\n baseY: rect.top,\n moved: false,\n lastDx: 0,\n lastDy: 0,\n };\n drag.current = state;\n\n const onMove = (move: PointerEvent) => {\n const node = ref.current;\n if (!node || move.pointerId !== state.pointerId) return;\n const dx = move.clientX - state.startX;\n const dy = move.clientY - state.startY;\n if (!state.moved) {\n if (Math.hypot(dx, dy) < DRAG_THRESHOLD) return;\n state.moved = true;\n setDragging(true);\n // Capture so moves and the release reach us even outside the window;\n // the post-drag click retargets to the bar and is suppressed anyway.\n try {\n node.setPointerCapture(state.pointerId);\n } catch {\n /* ignore */\n }\n }\n move.preventDefault(); // no text selection, no page scroll on touch\n state.lastDx = dx;\n state.lastDy = dy;\n // Pure compositor move — position committed to state only on release.\n // bottom must go, or the CSS bottom anchor + inline top stretch the bar.\n node.style.bottom = 'auto';\n node.style.left = '0px';\n node.style.top = '0px';\n node.style.translate = `${state.baseX + dx}px ${state.baseY + dy}px`;\n };\n const killDrag = (dragEvent: Event) => dragEvent.preventDefault();\n const onUp = (up: PointerEvent) => {\n if (up.pointerId !== state.pointerId) return;\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', onUp);\n window.removeEventListener('pointercancel', onUp);\n window.removeEventListener('dragstart', killDrag, true);\n drag.current = null;\n const node = ref.current;\n if (!node || !state.moved) return; // plain click — let it through\n setDragging(false);\n justDragged.current = true;\n // Use the last tracked move deltas — a pointercancel arrives with\n // zeroed coordinates and must not teleport the bar.\n const snapped = snapClampPos(\n state.baseX + state.lastDx,\n state.baseY + state.lastDy,\n node.offsetWidth,\n node.offsetHeight,\n );\n // Leave the DOM exactly as React will render it — clearing left/top\n // here would desync React's style prop diffing from reality.\n node.style.bottom = 'auto';\n node.style.left = '0px';\n node.style.top = '0px';\n node.style.translate = `${snapped.x}px ${snapped.y}px`;\n applyPos(snapped, true);\n };\n window.addEventListener('pointermove', onMove, { passive: false });\n window.addEventListener('pointerup', onUp);\n window.addEventListener('pointercancel', onUp);\n // A native drag (image/text) fires pointercancel and kills the gesture.\n window.addEventListener('dragstart', killDrag, true);\n };\n\n const onClickCapture = (event: ReactMouseEvent) => {\n if (justDragged.current) {\n justDragged.current = false;\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n const onGripKeyDown = (event: ReactKeyboardEvent<HTMLButtonElement>) => {\n const el = ref.current;\n if (!el) return;\n const stepSize = event.shiftKey ? 24 : 8;\n const rect = el.getBoundingClientRect();\n let dx = 0;\n let dy = 0;\n if (event.key === 'ArrowLeft') dx = -stepSize;\n else if (event.key === 'ArrowRight') dx = stepSize;\n else if (event.key === 'ArrowUp') dy = -stepSize;\n else if (event.key === 'ArrowDown') dy = stepSize;\n else return;\n event.preventDefault();\n // Clamp only — snapping here would glue the bar to an edge it sits near.\n applyPos(clampPos(rect.left + dx, rect.top + dy, el.offsetWidth, el.offsetHeight), true);\n };\n\n const open = (kind: EditorKind) => {\n if (!selection) return;\n // Hand the editor a pristine element — its \"before\" must be the original.\n revertElementPreview(selection.element);\n dispatch({ type: 'OPEN_EDITOR', editor: { kind, element: selection.element, target: selection.target } });\n };\n\n const hasImage = selection !== null && findImage(selection.element) !== null;\n\n const classes = [\n 'rk-toolbar',\n pos !== null ? 'rk-toolbar-free' : '',\n dragging ? 'rk-toolbar-dragging' : '',\n mode === 'pick' && selection === null ? 'rk-ghost' : '',\n ]\n .filter(Boolean)\n .join(' ');\n const style = pos !== null ? { left: 0, top: 0, translate: `${pos.x}px ${pos.y}px` } : undefined;\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n role=\"menu\"\n aria-label=\"Feedback actions\"\n onPointerDown={onPointerDown}\n onClickCapture={onClickCapture}\n >\n <button\n type=\"button\"\n className=\"rk-toolbar-grip\"\n aria-label=\"Move the toolbar — drag, or use arrow keys; double-click to reset its position\"\n onKeyDown={onGripKeyDown}\n onDoubleClick={() => applyPos(null, true)}\n >\n <svg width=\"8\" height=\"14\" viewBox=\"0 0 8 14\" aria-hidden=\"true\" fill=\"currentColor\">\n <circle cx=\"2\" cy=\"2\" r=\"1.1\" />\n <circle cx=\"6\" cy=\"2\" r=\"1.1\" />\n <circle cx=\"2\" cy=\"7\" r=\"1.1\" />\n <circle cx=\"6\" cy=\"7\" r=\"1.1\" />\n <circle cx=\"2\" cy=\"12\" r=\"1.1\" />\n <circle cx=\"6\" cy=\"12\" r=\"1.1\" />\n </svg>\n </button>\n <PresenceStrip />\n {hasPeers && <span className=\"rk-toolbar-sep\" />}\n <div className=\"rk-seg rk-tool-seg\" role=\"group\" aria-label=\"Tools\">\n {TOOLS.map((entry) => (\n <button\n key={entry.tool}\n type=\"button\"\n aria-pressed={mode === 'pick' && tool === entry.tool}\n title={`${shortcutTitle(entry.hintId) || entry.label}${keyHint(entry.hintId)}`}\n aria-label={`${entry.label}${keyHint(entry.hintId)}`}\n onClick={() => dispatch({ type: 'SET_TOOL', tool: entry.tool })}\n >\n {entry.icon(13)}\n </button>\n ))}\n </div>\n {selection && <span className=\"rk-toolbar-sep\" />}\n {selection && (\n <>\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"rk-toolbar-btn\"\n title={`Rewrite text${keyHint('tool-copy')}`}\n onClick={() => open('copy')}\n >\n <IconText size={14} /> Rewrite\n </button>\n {hasImage && (\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"rk-toolbar-btn\"\n title={`Replace image${keyHint('tool-image')}`}\n onClick={() => open('image')}\n >\n <IconImage size={14} /> Image\n </button>\n )}\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"rk-toolbar-btn\"\n title={`Comment${keyHint('tool-comment')}`}\n onClick={() => open('comment')}\n >\n <IconComment size={14} /> Comment\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"rk-toolbar-btn\" onClick={() => open('style')}>\n <IconStyle size={14} /> Style\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"rk-toolbar-btn\" onClick={() => open('move')}>\n <IconMove size={14} /> Move\n </button>\n <button type=\"button\" role=\"menuitem\" className=\"rk-toolbar-btn rk-danger\" onClick={() => open('delete')}>\n <IconTrash size={14} /> Delete\n </button>\n <span className=\"rk-toolbar-sep\" />\n <button\n type=\"button\"\n className=\"rk-icon-btn\"\n aria-label=\"Deselect\"\n onClick={() => dispatch({ type: 'SELECT', selection: null })}\n >\n <IconClose size={13} />\n </button>\n </>\n )}\n </div>\n );\n}\n","/** Toast notifications: auto-dismissing, stacked bottom-center. */\n\nimport { useEffect } from 'react';\nimport type { ToastData } from '../store';\nimport { useDispatch, useStore } from '../store';\nimport { IconCheck, IconComment, IconWarning } from './icons';\n\nfunction ToastRow({ toast }: { toast: ToastData }) {\n const dispatch = useDispatch();\n useEffect(() => {\n const timer = window.setTimeout(() => dispatch({ type: 'DISMISS_TOAST', id: toast.id }), 3500);\n return () => window.clearTimeout(timer);\n }, [toast.id, dispatch]);\n\n return (\n <div className={`rk-toast rk-${toast.tone}`} role=\"status\">\n {toast.tone === 'success' ? <IconCheck size={13} /> : toast.tone === 'error' ? <IconWarning size={13} /> : <IconComment size={13} />}\n {toast.message}\n </div>\n );\n}\n\nexport function ToastHost() {\n const { toasts } = useStore();\n if (toasts.length === 0) return null;\n return (\n <div className=\"rk-toasts\" aria-live=\"polite\">\n {toasts.map((toast) => (\n <ToastRow key={toast.id} toast={toast} />\n ))}\n </div>\n );\n}\n","/** Plugin root inside the shadow DOM: boot, persistence, keyboard, layout. */\n\nimport { useEffect, useRef } from 'react';\nimport { takeFocusItem } from './env';\nimport { defaultStorageKey, loadSession, saveSession } from './persist';\nimport { revealTarget } from './reveal';\nimport { resolveTarget } from './target';\nimport { trackPointer } from './pointer';\nimport { useAppliedPreview } from './preview';\nimport { IS_MAC, isTypingContext, matchShortcut, SHORTCUTS } from './shortcuts';\nimport { useEmblemaAutoPush } from './emblemaPush';\nimport { useRealtimeSync } from './sync';\nimport { setEffectAssetsUrl } from './effectsLazy';\nimport { isPluginElement } from './target';\nimport {\n createSession,\n DispatchContext,\n reducer,\n useConfig,\n useDispatch,\n useStore,\n} from './store';\nimport { Badge } from './components/Badge';\nimport { CheatSheet } from './components/CheatSheet';\nimport { EmblemaConnect } from './components/EmblemaConnect';\nimport { COACH_KEY, CoachMark } from './components/CoachMark';\nimport { ConfirmHost } from './components/Confirm';\nimport { ImageEditor } from './components/ImageEditor';\nimport { InlineEditor } from './components/InlineEditor';\nimport { NoteComposer } from './components/NoteComposer';\nimport { Panel } from './components/Panel';\nimport { PeerCursors } from './components/Presence';\nimport { QuickComment } from './components/QuickComment';\nimport { PickLayer } from './components/PickLayer';\nimport { Pins } from './components/Pins';\nimport { Toolbar } from './components/Toolbar';\nimport { ToastHost } from './components/Toast';\n\nexport function App() {\n const state = useStore();\n const rawDispatch = useDispatch();\n const config = useConfig();\n\n // Realtime bridge: mirrored dispatch (re-provided below) + remote handlers.\n const dispatch = useRealtimeSync(state, rawDispatch, config, reducer);\n const saveTimer = useRef<number | null>(null);\n const storageKey = config.storageKey ?? defaultStorageKey();\n\n // Mirror saved copy/image changes into the page (Original ⇄ Edited view).\n useAppliedPreview(state, dispatch);\n\n // Automatic realtime push of changed items to Emblema (silent-fail).\n useEmblemaAutoPush(state, dispatch, config);\n\n // Where `/` effect soundtracks are fetched from (unset = silent effects).\n useEffect(() => {\n setEffectAssetsUrl(config.fxAssetsUrl);\n }, [config.fxAssetsUrl]);\n\n\n // Boot: load the persisted session for this origin, or start a fresh one.\n useEffect(() => {\n let cancelled = false;\n void loadSession(storageKey).then((stored) => {\n if (cancelled) return;\n const session = stored ?? createSession(config.defaultAuthor ?? '');\n dispatch({ type: 'INIT_SESSION', session });\n let coachSeen = false;\n try {\n coachSeen = window.localStorage.getItem(COACH_KEY) !== null;\n } catch {\n /* ignore */\n }\n if (!coachSeen) dispatch({ type: 'SET_COACH', open: true });\n });\n return () => {\n cancelled = true;\n };\n }, [storageKey, config.defaultAuthor, dispatch]);\n\n // Autosave (debounced) + change callback.\n const { session } = state;\n useEffect(() => {\n if (!session) return;\n if (saveTimer.current !== null) window.clearTimeout(saveTimer.current);\n saveTimer.current = window.setTimeout(() => {\n void saveSession(storageKey, session);\n config.onSessionChange?.(session);\n }, 400);\n return () => {\n if (saveTimer.current !== null) window.clearTimeout(saveTimer.current);\n };\n }, [session, storageKey, config]);\n\n // Track the pointer for the `/` composer and cursor anchoring.\n useEffect(() => trackPointer(), []);\n\n // Cross-page hand-off: a panel row clicked on another route navigated here\n // with the item id stashed — select and scroll to its pin once the target\n // resolves (the page may still be hydrating, so poll briefly).\n const focusHandled = useRef(false);\n useEffect(() => {\n if (!session || focusHandled.current) return;\n focusHandled.current = true;\n const id = takeFocusItem();\n if (!id) return;\n const item = session.items.find((entry) => entry.id === id);\n if (!item || item.route !== window.location.pathname) return;\n let cancelled = false;\n const startedAt = Date.now();\n const attempt = () => {\n if (cancelled) return;\n if (resolveTarget(item.target)) {\n dispatch({ type: 'SET_ACTIVE_ITEM', id });\n void revealTarget(item.target).then(() => {\n if (!cancelled) resolveTarget(item.target)?.element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n });\n return;\n }\n if (Date.now() - startedAt < 10_000) window.setTimeout(attempt, 300);\n };\n attempt();\n return () => {\n cancelled = true;\n };\n }, [session, dispatch]);\n\n // Route watcher: SPA navigations (history API) and popstate.\n useEffect(() => {\n let last = window.location.pathname;\n const check = () => {\n if (window.location.pathname !== last) {\n last = window.location.pathname;\n dispatch({ type: 'SET_ROUTE', route: last });\n }\n };\n const interval = window.setInterval(check, 300);\n window.addEventListener('popstate', check);\n return () => {\n window.clearInterval(interval);\n window.removeEventListener('popstate', check);\n };\n }, [dispatch]);\n\n // Global keyboard, fully driven by the shortcut registry (shortcuts.ts).\n const stateRef = useRef(state);\n stateRef.current = state;\n useEffect(() => {\n const onKeyDown = (event: KeyboardEvent) => {\n const current = stateRef.current;\n for (const def of SHORTCUTS) {\n if (!matchShortcut(def, event, IS_MAC)) continue;\n // Presentation mode: only H brings the layer back.\n if (current.hidden && def.id !== 'hide-layer') return;\n if (!def.allowWhileTyping && isTypingContext(event)) return;\n const handled = def.run({ state: current, dispatch, event });\n if (handled !== false) event.preventDefault();\n return;\n }\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [dispatch]);\n\n // While an editor is open, clicking outside plugin UI and the edited element cancels it.\n useEffect(() => {\n if (!state.editor) return;\n const editorEl = state.editor.element;\n const onPointerDown = (event: PointerEvent) => {\n if (isPluginElement(event.target)) return;\n if (event.target instanceof Node && editorEl.contains(event.target)) return;\n dispatch({ type: 'CLOSE_EDITOR' });\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n return () => document.removeEventListener('pointerdown', onPointerDown, true);\n }, [state.editor, dispatch]);\n\n if (!session) return null;\n\n // Presentation mode: the page stays clean; only the key listener lives on.\n if (state.hidden) {\n return <DispatchContext.Provider value={dispatch}>{null}</DispatchContext.Provider>;\n }\n\n return (\n <DispatchContext.Provider value={dispatch}>\n <PickLayer />\n <PeerCursors />\n <Toolbar />\n {state.editor?.kind === 'copy' && <InlineEditor editor={state.editor} />}\n {state.editor?.kind === 'image' && <ImageEditor editor={state.editor} />}\n {state.editor && state.editor.kind !== 'copy' && state.editor.kind !== 'image' && (\n <NoteComposer editor={state.editor} />\n )}\n <Pins />\n <QuickComment />\n <Panel />\n <Badge />\n <CoachMark />\n <CheatSheet />\n <EmblemaConnect />\n <ConfirmHost />\n <ToastHost />\n </DispatchContext.Provider>\n );\n}\n","/** <ReviewKit /> — the two-line integration: render once, activate via URL. */\n\nimport { useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { DEACTIVATE_EVENT, resolveActivation } from './env';\nimport { setLayerRoot } from './pointer';\nimport { buildStylesheet } from './styles';\nimport { HOST_ATTR } from './target';\nimport type { ReviewKitConfig } from './store';\nimport { StoreProvider } from './store';\nimport { App } from './App';\n\nexport type ReviewKitProps = ReviewKitConfig;\n\nfunction ShadowHost({ config }: { config: ReviewKitConfig }) {\n const [mount, setMount] = useState<HTMLElement | null>(null);\n\n useEffect(() => {\n const host = document.createElement('div');\n host.setAttribute(HOST_ATTR, '');\n // The host itself is a click-through overlay; interactive children opt in.\n host.style.position = 'fixed';\n host.style.inset = '0';\n host.style.zIndex = '2147483000';\n host.style.pointerEvents = 'none';\n document.body.appendChild(host);\n const shadow = host.attachShadow({ mode: 'open' });\n\n const css = buildStylesheet();\n let styleInjected = false;\n try {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(css);\n shadow.adoptedStyleSheets = [sheet];\n styleInjected = true;\n } catch {\n /* constructed stylesheets unsupported — fall back to a <style> element */\n }\n if (!styleInjected) {\n const style = document.createElement('style');\n style.textContent = css;\n shadow.appendChild(style);\n }\n\n const root = document.createElement('div');\n root.className = 'rk-root';\n shadow.appendChild(root);\n setMount(root);\n setLayerRoot(root);\n\n return () => {\n setLayerRoot(null);\n setMount(null);\n host.remove();\n };\n }, []);\n\n if (!mount) return null;\n return createPortal(\n <StoreProvider config={config}>\n <App />\n </StoreProvider>,\n mount,\n );\n}\n\n/**\n * Drop-in visual review layer. Renders nothing unless activated via\n * `?review=<token>` (or the per-tab session it starts), or forced on with\n * `devAutoOn`. `enabled={false}` is a hard off switch. All UI lives in a\n * shadow root on `document.body` — host CSS never leaks in, plugin CSS never\n * leaks out.\n */\nexport function ReviewKit(props: ReviewKitProps) {\n const [active, setActive] = useState(false);\n const { enabled, token, allowedHosts, devAutoOn } = props;\n const hostsKey = allowedHosts?.join('\\u0000') ?? '';\n\n useEffect(() => {\n if (enabled === false) {\n setActive(false);\n return;\n }\n setActive(resolveActivation({ token, allowedHosts, devAutoOn, enabled }));\n const onDeactivate = () => setActive(false);\n window.addEventListener(DEACTIVATE_EVENT, onDeactivate);\n return () => window.removeEventListener(DEACTIVATE_EVENT, onDeactivate);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- allowedHosts compared by content via hostsKey\n }, [enabled, token, devAutoOn, hostsKey]);\n\n if (enabled === false || !active) return null;\n return <ShadowHost config={props} />;\n}\n","export { ReviewKit } from './ReviewKit';\nexport type { ReviewKitProps } from './ReviewKit';\nexport type { ReviewKitConfig, BadgeCorner } from './store';\nexport { resolveTarget, captureTarget } from './target';\nexport type { Resolved, ResolveMethod } from './target';\nexport {\n downloadSession,\n copySessionToClipboard,\n importSessionFile,\n sessionToJson,\n exportFilename,\n} from './exportSession';\nexport * from '../schema';\n","'use client';\n\n/**\n * `@satanwagen/reviewkit/next` — one-line Next.js (App Router) integration.\n * The directive above survives bundling, so the built file is a client\n * boundary and can be rendered straight from a server `layout.tsx`:\n *\n * import { ReviewKit } from '@satanwagen/reviewkit/next';\n * <ReviewKit token={process.env.NEXT_PUBLIC_REVIEW_TOKEN} />\n *\n * Renders nothing on the server; on the client it evaluates URL + sticky\n * session after mount and only then downloads the review core. Need the\n * activation decision in a Server Component? Import `shouldActivate` from\n * `@satanwagen/reviewkit/activate` — everything exported here is\n * client-only by virtue of the directive.\n */\n\nexport { LazyReviewKit as ReviewKit } from './LazyReviewKit';\nexport type { ReviewKitProps } from './client/ReviewKit';\n","/**\n * Shared implementation of the `/lazy` and `/next` entries: decide on the\n * client after mount (URL + sticky session via `shouldActivate`), and only\n * then dynamically import the review core. Visitors without a review link\n * never download the core chunk; SSR renders nothing.\n */\n\nimport { useEffect, useState } from 'react';\nimport type { ComponentType } from 'react';\nimport { shouldActivate } from './activate';\nimport type { ReviewKitProps } from './client/ReviewKit';\n\ntype Core = ComponentType<ReviewKitProps>;\n\nlet coreModule: Promise<Core> | null = null;\nfunction loadCore(): Promise<Core> {\n if (!coreModule) coreModule = import('./client/index').then((mod) => mod.ReviewKit);\n return coreModule;\n}\n\nexport function LazyReviewKit(props: ReviewKitProps) {\n const [Core, setCore] = useState<Core | null>(null);\n const { enabled, token, allowedHosts, devAutoOn } = props;\n const hostsKey = allowedHosts?.join(' ') ?? '';\n\n useEffect(() => {\n if (!shouldActivate({ enabled, token, allowedHosts, devAutoOn })) return;\n let cancelled = false;\n loadCore()\n .then((component) => {\n if (!cancelled) setCore(() => component);\n })\n .catch((error: unknown) => {\n console.warn('[review-kit] failed to load the review layer chunk', error);\n });\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- allowedHosts compared by content via hostsKey\n }, [enabled, token, devAutoOn, hostsKey]);\n\n if (!Core || enabled === false) return null;\n return <Core {...props} />;\n}\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","names":["safeRemove","active","toast","el","session","route","preview","editor","hidden","import_react","restore","toast","setEffectBroadcaster","cancelEffects","runEffect","cancelEffects","import_react","queued","active","status","reducer","id","runEffect","active","setEffectBroadcaster","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","loading","import_react","import_jsx_runtime","delta","before","import_react","import_jsx_runtime","import_react","import_jsx_runtime","active","import_react","import_jsx_runtime","import_react","import_jsx_runtime","runEffect","import_react","import_jsx_runtime","pad","import_react","import_jsx_runtime","import_react","import_jsx_runtime","POS_KEY","DRAG_THRESHOLD","import_react","import_jsx_runtime","toast","import_react","import_jsx_runtime","session","import_react","import_jsx_runtime","active","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}