overplay 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overplay.esm.js","sources":["../src/core/data.ts","../src/storage/HostedAdapter.ts","../src/storage/LocalStorageAdapter.ts","../src/core/shortcut.ts","../src/core/identity.ts","../src/core/activity.ts","../src/core/version.ts","../src/core/settings.ts","../src/widget/dom.ts","../src/design/tokens.ts","../src/widget/styles.ts","../src/core/reveal.ts","../src/core/anchors.ts","../src/core/filter.ts","../src/widget/Overlay.ts","../src/storage/APIAdapter.ts","../src/index.ts"],"sourcesContent":["import type { Comment, Reply, RevealStep } from './types';\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid comment data.');\n return value as Record<string, unknown>;\n}\nfunction string(value: unknown, field: string): string {\n if (typeof value !== 'string' || !value.trim()) throw new Error(`Invalid ${field}.`);\n return value;\n}\nfunction date(value: unknown): Date {\n const result = new Date(value as string);\n if (!Number.isFinite(result.getTime())) throw new Error('Invalid comment date.');\n return result;\n}\nfunction reply(value: unknown): Reply {\n const r = record(value);\n return { id: string(r.id, 'reply ID'), text: string(r.text, 'reply text'), author: string(r.author, 'author'),\n authorId: typeof r.authorId === 'string' ? r.authorId : undefined,\n via: typeof r.via === 'string' ? r.via.slice(0,60) : undefined,\n avatarUrl: typeof r.avatarUrl === 'string' ? r.avatarUrl : undefined,\n timestamp: date(r.timestamp), commentId: string(r.commentId, 'comment ID') };\n}\n/** Saved open steps: at most 6, short strings, known actions only. */\nexport function revealSteps(value: unknown): { reveal?: RevealStep[] } {\n if (!Array.isArray(value)) return {};\n const short = (v: unknown, max: number) => typeof v === 'string' && v.trim() ? v.trim().slice(0, max) : undefined;\n const steps = value.slice(0, 6).flatMap((step): RevealStep[] => {\n const s = step && typeof step === 'object' ? step as Record<string, unknown> : {};\n const t = s.target && typeof s.target === 'object' ? s.target as Record<string, unknown> : {};\n const selector = short(t.selector, 500);\n if (!['press', 'hover', 'focus'].includes(s.action as string) || !selector) return [];\n const role = short(t.role, 40), name = short(t.name, 120), tag = short(t.tag, 40);\n return [{ action: s.action as RevealStep['action'], target: { selector, ...(role ? { role } : {}), ...(name ? { name } : {}), ...(tag ? { tag } : {}) } }];\n });\n return steps.length ? { reveal: steps } : {};\n}\nexport function normalizeComments(value: unknown): Comment[] {\n if (!Array.isArray(value)) throw new Error('Expected a list of comments.');\n return value.map(value => {\n const c = record(value);\n if (typeof c.x !== 'number' || typeof c.y !== 'number' || !Number.isFinite(c.x) || !Number.isFinite(c.y)) {\n throw new Error('Invalid comment position.');\n }\n const anchor = c.anchor ? record(c.anchor) : null;\n const info = c.element && typeof c.element === 'object' ? c.element as Record<string, unknown> : null;\n const text = (v: unknown) => typeof v === 'string' && v.trim() ? v.trim().slice(0, 120) : undefined;\n return { id: string(c.id, 'comment ID'), text: string(c.text, 'comment text'), author: string(c.author, 'author'),\n authorId: typeof c.authorId === 'string' ? c.authorId : undefined,\n via: typeof c.via === 'string' ? c.via.slice(0,60) : undefined,\n revision: typeof c.revision === 'number' ? c.revision : undefined,\n updatedAt: typeof c.updatedAt === 'string' ? c.updatedAt : undefined,\n avatarUrl: typeof c.avatarUrl === 'string' ? c.avatarUrl : undefined,\n timestamp: date(c.timestamp), x: c.x, y: c.y, resolved: c.resolved === true,\n pageUrl: string(c.pageUrl, 'page URL'), pageTitle: typeof c.pageTitle === 'string' && c.pageTitle.trim() ? c.pageTitle.trim().slice(0, 300) : undefined, replies: Array.isArray(c.replies) ? c.replies.map(reply) : [],\n selector: typeof c.selector === 'string' ? c.selector : undefined,\n element: info && text(info.label) ? { label: text(info.label)!, ...(text(info.place) ? { place: text(info.place) } : {}), ...revealSteps(info.reveal) } : undefined,\n anchor: anchor && typeof anchor.x === 'number' && typeof anchor.y === 'number' && Number.isFinite(anchor.x) && Number.isFinite(anchor.y)\n ? { x: Math.max(0, Math.min(1, anchor.x)), y: Math.max(0, Math.min(1, anchor.y)) } : undefined };\n });\n}\n/** Prevent callers or adapters from mutating live state. */\nexport function copyComments(comments: Comment[]): Comment[] { return normalizeComments(comments); }\nexport function safePageUrl(path: string, base: string): URL {\n const url = new URL(path, base);\n if (!['http:', 'https:'].includes(url.protocol) || url.origin !== new URL(base).origin) {\n throw new Error('Comments can only link to pages on this site.');\n }\n return url;\n}\n/** Remove only the MCP thread parameter, preserving application query encoding and order. */\nexport function withoutCommentLink(search: string): string {\n const parts = search.replace(/^\\?/, '').split('&').filter(part => {\n try { return decodeURIComponent(part.split('=')[0].replace(/\\+/g, ' ')) !== 'cw_comment'; }\n catch { return true; }\n });\n const value = parts.join('&');\n return value ? '?' + value : '';\n}\n/** Default route identity. In-page anchors stay on the same page; hash routes do not. */\nexport function defaultPageId(location: Pick<Location, 'pathname' | 'search' | 'hash'>): string {\n return `${location.pathname}${withoutCommentLink(location.search)}${/^#!?\\//.test(location.hash) ? location.hash : ''}`;\n}\n/** Comments saved before 2.1 kept in-page anchors in their page ID. Compare them without it. */\nexport function samePage(pageUrl: string, pageId: string): boolean {\n return pageUrl === pageId || pageUrl.replace(/#(?!!?\\/).*$/, '') === pageId;\n}\n","import type { Comment, CommentUser, Reply } from \"../core/types\";\nimport type { StorageAdapter } from \"./StorageAdapter\";\nimport { normalizeComments } from \"../core/data\";\n\n/** Hosts the hosted service used before it moved. They only redirect now, so the widget calls the current host directly. */\nconst MOVED_SERVICES: Record<string, string> = {\n \"comments.artsvit.com\": \"https://overplay.app\",\n};\n/** Returns the origin the widget should call: the current host for a moved service, otherwise the origin unchanged. */\nexport function serviceOrigin(origin: string): string {\n return MOVED_SERVICES[new URL(origin).hostname] ?? origin;\n}\n\n/** Authenticated storage for the hosted Overplay service. Tokens are scoped to one project and website origin. */\nexport class HostedAdapter implements StorageAdapter {\n private base: string;\n private key: string;\n private accessToken = \"\";\n private expiresAt = 0;\n private initialized = false;\n private pending?: Promise<void>;\n private cancelSignIn?: () => void;\n user?: CommentUser;\n constructor(\n serverUrl: string,\n private projectId: string,\n private page: () => string,\n private sessionChanged: (user?: CommentUser) => void,\n ) {\n const url = new URL(serverUrl);\n if (\n url.protocol !== \"https:\" &&\n !(\n url.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\"].includes(url.hostname)\n )\n )\n throw new Error(\"serverUrl must use HTTPS.\");\n if (\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n url.pathname !== \"/\"\n )\n throw new Error(\"serverUrl must be a service origin without a path.\");\n this.base = serviceOrigin(url.origin);\n this.key = `overplay:${this.base}:${projectId}:session`;\n try {\n const saved = JSON.parse(sessionStorage.getItem(this.key) || \"null\");\n if (saved?.expiresAt > Date.now()) {\n this.accessToken = saved.accessToken;\n this.expiresAt = saved.expiresAt;\n }\n } catch {\n /* Storage may be blocked. */\n }\n }\n get signedIn(): boolean {\n return !!this.user && this.expiresAt > Date.now();\n }\n private clear(): void {\n this.accessToken = \"\";\n this.expiresAt = 0;\n this.user = undefined;\n try {\n sessionStorage.removeItem(this.key);\n } catch {\n /* Memory-only session. */\n }\n this.sessionChanged();\n }\n private async request(\n path: string,\n method = \"GET\",\n body?: unknown,\n ): Promise<unknown> {\n const url = new URL(`/api${path}`, this.base);\n url.searchParams.set(\"projectId\", this.projectId);\n const response = await fetch(url, {\n method,\n credentials: \"omit\",\n headers: {\n ...(body !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n ...(this.accessToken\n ? { Authorization: `Bearer ${this.accessToken}` }\n : {}),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n // A proxy or CDN can answer with an HTML error page, so JSON is optional until the status is known.\n const result = (await response.json().catch(() => null)) as {\n error?: string;\n } | null;\n if (!response.ok) {\n // 401 means the session is gone. A 403 on a read means project or website access was removed.\n // A 403 on a write can be an author-only rule, which must not sign the user out.\n if (\n response.status === 401 ||\n (response.status === 403 && method === \"GET\")\n )\n this.clear();\n throw new Error(\n result?.error || `Comment service returned ${response.status}.`,\n );\n }\n if (result === null)\n throw new Error(\"Comment service returned an invalid response.\");\n return result;\n }\n private async initialize(): Promise<void> {\n if (this.initialized) return;\n this.initialized = true;\n if (!this.accessToken) return;\n try {\n this.user = ((await this.request(\"/me\")) as { user: CommentUser }).user;\n this.sessionChanged(this.user);\n } catch (error) {\n // request() already cleared a rejected session. Keep it after a network error and retry on the next load.\n if (this.accessToken) this.initialized = false;\n throw error;\n }\n }\n signIn(): Promise<void> {\n if (this.pending) return this.pending;\n const popup = window.open(\n \"about:blank\",\n `overplay-${this.projectId}`,\n \"popup,width=520,height=760\",\n );\n if (!popup)\n return Promise.reject(\n new Error(\"Allow popups to sign in to Overplay.\"),\n );\n this.pending = new Promise<void>((resolve, reject) => {\n let done = false;\n const finish = (error?: Error) => {\n if (done) return;\n done = true;\n window.removeEventListener(\"message\", receive);\n clearInterval(closed);\n clearTimeout(timeout);\n popup.close();\n this.pending = undefined;\n this.cancelSignIn = undefined;\n if (error) reject(error);\n else resolve();\n };\n const verifier = Array.from(\n crypto.getRandomValues(new Uint8Array(32)),\n (b) => b.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n let exchanging = false;\n const receive = (event: MessageEvent) => {\n if (\n exchanging ||\n event.origin !== this.base ||\n event.source !== popup ||\n event.data?.type !== \"overplay:authorization\" ||\n event.data.projectId !== this.projectId ||\n typeof event.data.code !== \"string\"\n )\n return;\n exchanging = true;\n void (async () => {\n const result = (await this.request(\"/connect/token\", \"POST\", {\n code: event.data.code,\n verifier,\n })) as { accessToken: string; expiresAt: number };\n if (done) return;\n this.accessToken = result.accessToken;\n this.expiresAt = result.expiresAt;\n this.user = (\n (await this.request(\"/me\")) as { user: CommentUser }\n ).user;\n if (done) {\n this.clear();\n return;\n }\n this.initialized = true;\n try {\n sessionStorage.setItem(\n this.key,\n JSON.stringify({\n accessToken: this.accessToken,\n expiresAt: this.expiresAt,\n }),\n );\n } catch {\n /* Memory-only session. */\n }\n this.sessionChanged(this.user);\n finish();\n })().catch((e) => {\n this.clear();\n finish(e instanceof Error ? e : new Error(\"Sign-in failed.\"));\n });\n };\n const closed = setInterval(() => {\n if (popup.closed && !exchanging)\n finish(new Error(\"Sign-in window was closed.\"));\n }, 750);\n const timeout = setTimeout(\n () => finish(new Error(\"Sign-in timed out. Please try again.\")),\n 5 * 60_000,\n );\n this.cancelSignIn = () => finish(new Error(\"Widget was closed.\"));\n window.addEventListener(\"message\", receive);\n void crypto.subtle\n .digest(\"SHA-256\", new TextEncoder().encode(verifier))\n .then((hash) => {\n if (done) return;\n const encoded = btoa(String.fromCharCode(...new Uint8Array(hash)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n const url = new URL(\"/connect\", this.base);\n url.search = new URLSearchParams({\n projectId: this.projectId,\n origin: location.origin,\n challenge: encoded,\n }).toString();\n popup.location.href = url.href;\n })\n .catch(() => finish(new Error(\"Secure sign-in is unavailable.\")));\n });\n return this.pending;\n }\n async signOut(): Promise<void> {\n try {\n if (this.accessToken) await this.request(\"/connect/logout\", \"POST\", {});\n } finally {\n this.clear();\n }\n }\n destroy(): void {\n this.cancelSignIn?.();\n }\n async loadComments(): Promise<Comment[]> {\n await this.initialize();\n if (this.expiresAt && this.expiresAt <= Date.now()) this.clear();\n if (!this.signedIn) return [];\n const sessionToken = this.accessToken;\n const comments: unknown[] = [];\n let after = \"\";\n do {\n // Every page of the project, so the widget can show \"All comments\". The widget filters the current page.\n const query = new URLSearchParams({ after });\n const page = (await this.request(`/comments?${query}`)) as {\n comments: unknown[];\n next: string | null;\n };\n comments.push(...page.comments);\n after = page.next || \"\";\n } while (after);\n return sessionToken === this.accessToken && this.signedIn\n ? normalizeComments(comments)\n : [];\n }\n subscribeToChanges(callback: (comments: Comment[]) => void): () => void {\n let running = false;\n let stopped = false;\n const poll = async () => {\n if (\n stopped ||\n running ||\n document.visibilityState === \"hidden\" ||\n !this.user\n )\n return;\n running = true;\n const pageId = this.page();\n const sessionToken = this.accessToken;\n try {\n const comments = await this.loadComments();\n if (\n !stopped &&\n this.signedIn &&\n sessionToken === this.accessToken &&\n pageId === this.page()\n )\n callback(comments);\n } catch {\n /* Keep the current snapshot during a temporary outage. Authentication failures clear the session. */\n } finally {\n running = false;\n }\n };\n const interval = setInterval(() => {\n void poll();\n }, 30_000);\n const visible = () => {\n if (document.visibilityState === \"visible\") void poll();\n };\n document.addEventListener(\"visibilitychange\", visible);\n return () => {\n stopped = true;\n clearInterval(interval);\n document.removeEventListener(\"visibilitychange\", visible);\n };\n }\n async saveComments(): Promise<void> {\n throw new Error(\"Hosted storage requires individual comment mutations.\");\n }\n async upsertComment(comment: Comment): Promise<void> {\n await this.request(\n `/comments/${encodeURIComponent(comment.id)}`,\n \"PUT\",\n comment,\n );\n }\n async deleteComment(id: string): Promise<void> {\n await this.request(`/comments/${encodeURIComponent(id)}`, \"DELETE\");\n }\n async addReply(id: string, reply: Reply): Promise<void> {\n await this.request(\n `/comments/${encodeURIComponent(id)}/replies`,\n \"POST\",\n reply,\n );\n }\n async setResolved(id: string, resolved: boolean): Promise<void> {\n await this.request(`/comments/${encodeURIComponent(id)}`, \"PATCH\", {\n resolved,\n });\n }\n}\n","import type { StorageAdapter } from './StorageAdapter';\nimport type { Comment, Reply } from '../core/types';\nimport { normalizeComments } from '../core/data';\nexport class LocalStorageAdapter implements StorageAdapter {\n constructor(private storageKey = 'overplay-comments') {}\n async loadComments(): Promise<Comment[]> {\n const value = localStorage.getItem(this.storageKey);\n return value === null ? [] : normalizeComments(JSON.parse(value));\n }\n async saveComments(comments: Comment[]): Promise<void> {\n localStorage.setItem(this.storageKey, JSON.stringify(comments));\n }\n async upsertComment(comment: Comment): Promise<void> {\n await this.change(comments => [...comments.filter(c => c.id !== comment.id), comment]);\n }\n async deleteComment(id: string): Promise<void> { await this.change(comments => comments.filter(c => c.id !== id)); }\n async addReply(id: string, reply: Reply): Promise<void> {\n await this.change(comments => {\n if (!comments.some(c => c.id === id)) throw new Error('This comment was removed. Refresh to see the latest notes.');\n return comments.map(c => c.id === id && !c.replies.some(r => r.id === reply.id) ? { ...c, replies: [...c.replies, reply] } : c);\n });\n }\n async setResolved(id: string, resolved: boolean): Promise<void> {\n await this.change(comments => {\n if (!comments.some(c => c.id === id)) throw new Error('This comment was removed. Refresh to see the latest notes.');\n return comments.map(c => c.id === id ? { ...c, resolved } : c);\n });\n }\n private async change(update: (comments: Comment[]) => Comment[]): Promise<void> {\n const write = async () => this.saveComments(update(await this.loadComments()));\n if (typeof navigator !== 'undefined' && navigator.locks) {\n await navigator.locks.request(`overplay:${this.storageKey}`, write);\n } else await write();\n }\n subscribeToChanges(callback: (comments: Comment[]) => void): () => void {\n const listener = (event: StorageEvent) => {\n if (event.storageArea !== localStorage || (event.key !== this.storageKey && event.key !== null)) return;\n void this.loadComments().then(callback).catch(() => { /* Explicit refresh exposes invalid data. */ });\n };\n window.addEventListener('storage', listener);\n return () => window.removeEventListener('storage', listener);\n }\n}\n","export interface Shortcut { key: string; alt: boolean; shift: boolean; ctrl: boolean; meta: boolean }\ntype KeyInput = Pick<KeyboardEvent, 'key' | 'code' | 'altKey' | 'shiftKey' | 'ctrlKey' | 'metaKey'>;\n/** Accepts \"c\" or modifier combinations such as \"alt+shift+c\". */\nexport function parseShortcut(value: string): Shortcut | null {\n const parts = value.toLowerCase().split('+').map(part => part.trim());\n const key = parts.pop();\n if (!key) return null;\n const shortcut = { key, alt: false, shift: false, ctrl: false, meta: false };\n for (const part of parts) {\n if (part === 'alt' || part === 'option') shortcut.alt = true;\n else if (part === 'shift') shortcut.shift = true;\n else if (part === 'ctrl' || part === 'control') shortcut.ctrl = true;\n else if (part === 'meta' || part === 'cmd') shortcut.meta = true;\n else return null;\n }\n return shortcut;\n}\nexport function matchesShortcut(event: KeyInput, shortcut: Shortcut): boolean {\n if (event.altKey !== shortcut.alt || event.ctrlKey !== shortcut.ctrl || event.metaKey !== shortcut.meta) return false;\n // Shift only matters when it was requested, so a single \"c\" still matches Caps Lock or Shift+C.\n if (shortcut.shift && !event.shiftKey) return false;\n // Alt changes event.key on macOS (Alt+C types \"ç\"), so compare the physical key for letters and digits.\n const code = /^[a-z]$/.test(shortcut.key) ? `Key${shortcut.key.toUpperCase()}` : /^\\d$/.test(shortcut.key) ? `Digit${shortcut.key}` : '';\n return event.key.toLowerCase() === shortcut.key || (!!code && event.code === code);\n}\n","import type { CommentUser } from './types';\n/** randomUUID exists only on HTTPS and localhost. getRandomValues also works on plain HTTP pages. */\nexport function newId(): string {\n if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6] & 0x0f) | 0x40; bytes[8] = (bytes[8] & 0x3f) | 0x80; // RFC 4122 version 4.\n const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\nexport function validateUser(user: CommentUser): CommentUser {\n if (!user || typeof user.id !== 'string' || !user.id.trim() || typeof user.name !== 'string' || !user.name.trim()) {\n throw new Error('A user needs a stable ID and a name.');\n }\n const role = user.role === 'owner' || user.role === 'admin' || user.role === 'member' ? { role: user.role } : {};\n return { id: user.id.trim(), name: user.name.trim().slice(0, 80), avatarUrl: user.avatarUrl, ...role };\n}\nexport function guestIdentity(key: string): { user: CommentUser; persistent: boolean } {\n let saved: CommentUser | undefined;\n try {\n const value = localStorage.getItem(key);\n if (value) saved = validateUser(JSON.parse(value));\n } catch { /* A blocked browser store still allows a session identity. */ }\n const user = saved ?? { id: newId(), name: 'Guest' };\n return { user, persistent: saveGuest(key, user) };\n}\nexport function saveGuest(key: string, user: CommentUser): boolean {\n try { localStorage.setItem(key, JSON.stringify(user)); return true; } catch { return false; }\n}\n","import type { Comment } from './types';\n\nexport interface Activity { kind: 'comment' | 'reply'; commentId: string; author: string; avatarUrl?: string; text: string }\n\n/**\n * Returns comments and replies that are not in `seen` and that another person wrote.\n * Every item is added to `seen`, so each one is reported only once.\n */\nexport function newActivity(comments: Comment[], seen: Set<string>, selfId: string): Activity[] {\n const found: Activity[] = [];\n const visit = (key: string, kind: Activity['kind'], commentId: string, item: { author: string; authorId?: string; avatarUrl?: string; text: string }) => {\n if (seen.has(key)) return;\n seen.add(key);\n if (item.authorId !== selfId) found.push({ kind, commentId, author: item.author, avatarUrl: item.avatarUrl, text: item.text });\n };\n for (const comment of comments) {\n visit(comment.id, 'comment', comment.id, comment);\n for (const reply of comment.replies) visit(`${comment.id}/${reply.id}`, 'reply', comment.id, reply);\n }\n return found;\n}\n\n/** Two snapshots hold the same data. Used to skip renders when a poll returns no change. */\nexport function sameComments(a: Comment[], b: Comment[]): boolean {\n return a.length === b.length && JSON.stringify(a) === JSON.stringify(b);\n}\n","import { version } from '../../package.json';\n\n/** The version of this widget build. */\nexport const VERSION: string = version;\nexport const PACKAGE = 'overplay';\nexport const UPDATE_COMMAND = `npm install ${PACKAGE}@latest`;\n\n/** True when `latest` is a higher x.y.z release than `current`. Pre-release tags are ignored. */\nexport function isNewer(latest: string, current: string): boolean {\n const parse = (v: string) => /^(\\d+)\\.(\\d+)\\.(\\d+)$/.exec(v.trim())?.slice(1).map(Number);\n const a = parse(latest), b = parse(current);\n if (!a || !b) return false;\n for (let i = 0; i < 3; i++) if (a[i] !== b[i]) return a[i] > b[i];\n return false;\n}\n\n/** Development hosts, where the person who sees the widget can also run npm. */\nexport function developmentHost(hostname: string): boolean {\n return ['localhost', '127.0.0.1', '[::1]', '::1'].includes(hostname) || /\\.(localhost|local|test)$/.test(hostname);\n}\n\nconst CACHE_MS = 12 * 60 * 60 * 1000;\n/**\n * The latest published version from the npm registry, cached for 12 hours in localStorage.\n * Returns null when the registry cannot be reached. The registry allows cross-origin reads.\n */\nexport async function latestVersion(fetcher: typeof fetch = fetch, now = Date.now()): Promise<string | null> {\n const key = 'overplay:latest-version';\n try {\n const cached = JSON.parse(localStorage.getItem(key) || 'null');\n if (cached && typeof cached.version === 'string' && now - cached.checkedAt < CACHE_MS) return cached.version;\n } catch { /* Storage may be blocked. */ }\n try {\n const response = await fetcher(`https://registry.npmjs.org/${PACKAGE}/latest`, { credentials: 'omit', referrerPolicy: 'no-referrer' });\n if (!response.ok) return null;\n const result = (await response.json()) as { version?: unknown };\n if (typeof result.version !== 'string') return null;\n try { localStorage.setItem(key, JSON.stringify({ version: result.version, checkedAt: now })); } catch { /* Check again next time. */ }\n return result.version;\n } catch { return null; }\n}\n","/** Display choices that each person makes for one project. They stay in this browser. */\nexport interface Settings {\n /** \"system\" follows the device's light or dark mode. */\n theme: 'light' | 'dark' | 'system';\n /** \"site\" uses the project's primaryColor. */\n pinColor: 'site' | 'indigo' | 'violet' | 'blue' | 'teal' | 'amber' | 'orange' | 'red' | 'pink' | 'graphite';\n /** The floating Comments button. \"default\" is the dark button that takes the site color while open. */\n buttonColor: 'default' | 'site' | Exclude<Settings['pinColor'], 'site' | 'graphite'>;\n resolvedPins: 'green' | 'gray';\n pinSize: 'regular' | 'small';\n /** What the pin shows: the note number, or the author's initials. */\n pinLabel: 'number' | 'initials';\n /** The open sidebar pushes the page aside instead of covering it. */\n pushContent: boolean;\n /** A short notification when someone else comments or replies. */\n notifications: boolean;\n /** The keyboard shortcut opens and closes the comments. */\n shortcut: boolean;\n}\nexport const PIN_COLORS: Record<Exclude<Settings['pinColor'], 'site'>, { label: string; color: string }> = {\n indigo: { label: 'Indigo', color: '#575ce5' },\n violet: { label: 'Violet', color: '#8048d8' },\n blue: { label: 'Blue', color: '#0068f9' },\n teal: { label: 'Teal', color: '#0f8a8c' },\n amber: { label: 'Amber', color: '#b97a06' },\n orange: { label: 'Orange', color: '#d9641e' },\n red: { label: 'Red', color: '#d23c3c' },\n pink: { label: 'Pink', color: '#d0427f' },\n graphite: { label: 'Graphite', color: '#242736' },\n};\nconst CHOICES: { [K in keyof Settings]: readonly Settings[K][] } = {\n theme: ['light', 'dark', 'system'],\n pinColor: ['site', 'indigo', 'violet', 'blue', 'teal', 'amber', 'orange', 'red', 'pink', 'graphite'],\n buttonColor: ['default', 'site', 'indigo', 'violet', 'blue', 'teal', 'amber', 'orange', 'red', 'pink'],\n resolvedPins: ['green', 'gray'],\n pinSize: ['regular', 'small'],\n pinLabel: ['number', 'initials'],\n pushContent: [true, false],\n notifications: [true, false],\n shortcut: [true, false],\n};\n\n/**\n * Reads the saved choices. Only the choices a person changed are saved, so a new default from the site owner's\n * configuration still reaches everyone who did not change that option. Unknown or broken values are ignored.\n */\nexport function readSettings(key: string, defaults: Settings): Settings {\n const settings = { ...defaults };\n try {\n const saved = JSON.parse(localStorage.getItem(key) || '{}') as Record<string, unknown>;\n for (const name of Object.keys(CHOICES) as (keyof Settings)[]) {\n if ((CHOICES[name] as readonly unknown[]).includes(saved[name])) Object.assign(settings, { [name]: saved[name] });\n }\n } catch { /* Defaults. */ }\n return settings;\n}\n/** Saves the choices that differ from the defaults. Returns false when the browser blocks storage. */\nexport function writeSettings(key: string, settings: Settings, defaults: Settings): boolean {\n const changed = Object.fromEntries(Object.entries(settings).filter(([name, value]) => defaults[name as keyof Settings] !== value));\n try {\n if (Object.keys(changed).length) localStorage.setItem(key, JSON.stringify(changed)); else localStorage.removeItem(key);\n return true;\n } catch { return false; }\n}\n/** Two letters for a pin or an avatar, such as \"AS\" for \"Artem Svitelskyi\" or \"AL\" for \"Alex\". */\nexport function initials(name: string): string {\n const words = name.trim().split(/\\s+/).filter(Boolean);\n const letters = words.length > 1 ? `${[...words[0]][0]}${[...words[words.length - 1]][0]}` : [...(words[0] ?? '?')].slice(0, 2).join('');\n return letters.toUpperCase();\n}\n","import { initials } from '../core/settings';\nexport function element<K extends keyof HTMLElementTagNameMap>(tag: K, className = '', text?: string): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag);\n if (className) el.className = className;\n if (text !== undefined) el.textContent = text;\n return el;\n}\nconst paths = {\n comment: 'M21 11.5a8.4 8.4 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7a8.4 8.4 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.4 8.4 0 0 1 3.8-.9h.5a8.5 8.5 0 0 1 8 8v.5Z',\n plus: 'M12 5v14M5 12h14', close: 'm6 6 12 12M6 18 18 6',\n check: 'm5 12 4 4L19 6', back: 'm12 5-7 7 7 7M5 12h14',\n arrow: 'M12 19V5m-6 6 6-6 6 6', refresh: 'M20.5 12a8.5 8.5 0 1 1-2.6-6.1L20.5 8.5M20.5 3.5v5h-5',\n open: 'M7 17 17 7M9 7h8v8',\n trash: 'M3 6h18M9 6V4h6v2M5 6l1 14h12l1-14M10 10v6m4-6v6',\n pin: 'M12 21s7-6 7-13A7 7 0 0 0 5 8c0 7 7 13 7 13ZM12 6v4M10 8h4',\n search: 'm21 21-5-5M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Z',\n eye: 'M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12ZM12 14.8a2.8 2.8 0 1 0 0-5.6 2.8 2.8 0 0 0 0 5.6Z',\n eyeOff: 'M3 3l18 18M10.6 5.6A9 9 0 0 1 12 5.5c6 0 9.5 6.5 9.5 6.5a16 16 0 0 1-2.9 3.6M6.5 6.9A16 16 0 0 0 2.5 12S6 18.5 12 18.5a9 9 0 0 0 4.6-1.3M10 10a2.8 2.8 0 0 0 4 4',\n unlink: 'M4.5 4.5h15v15h-15zM9.5 9.5l5 5M14.5 9.5l-5 5',\n dock: 'M4 5h16v14H4zM15 5v14',\n settings: 'M4 7h9m4 0h3M4 17h3m4 0h9M15 5v4M9 15v4',\n edit: 'M4 20h4L19 9l-4-4L4 16v4ZM13 7l4 4',\n signin: 'M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M15 12H3',\n signout: 'M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9', more: 'M5 12h.01M12 12h.01M19 12h.01', popout: 'M14 4h6v6M20 4l-8 8M18 14v5H5V6h5',\n} as const;\nexport function icon(name: keyof typeof paths): SVGSVGElement {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('viewBox', '0 0 24 24'); svg.setAttribute('fill', 'none'); svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '1.65'); svg.setAttribute('stroke-linecap', 'round'); svg.setAttribute('stroke-linejoin', 'round');\n svg.setAttribute('aria-hidden', 'true');\n const path = document.createElementNS(svg.namespaceURI, 'path'); path.setAttribute('d', paths[name]); svg.append(path);\n return svg;\n}\nexport function button(label: string, className: string, onClick: () => void, name?: keyof typeof paths): HTMLButtonElement {\n const el = element('button', className); el.type = 'button'; el.setAttribute('aria-label', label); el.title = label;\n if (name) el.append(icon(name));\n if (!className.includes('icon-button')) el.append(element('span', '', label));\n el.addEventListener('click', onClick); return el;\n}\nexport function avatar(name: string, url?: string): HTMLElement {\n const el = element('span', 'avatar', initials(name)); el.setAttribute('aria-hidden', 'true');\n if (url) {\n try {\n const safe = new URL(url, location.href);\n if (safe.protocol === 'https:' || (safe.protocol === 'http:' && safe.origin === location.origin)) {\n const img = element('img'); img.src = safe.href; img.alt = ''; img.referrerPolicy = 'no-referrer';\n // A cached image shows at once, so a re-render does not flash the initials first.\n if (img.complete && img.naturalWidth) el.replaceChildren(img);\n else img.addEventListener('load', () => el.replaceChildren(img));\n }\n } catch { /* Initials remain visible for invalid avatars. */ }\n }\n return el;\n}\nexport function relativeTime(date: Date): string {\n const minutes = Math.max(0, Math.floor((Date.now() - date.getTime()) / 60000));\n if (minutes < 1) return 'Just now';\n if (minutes < 60) return `${minutes}m ago`;\n if (minutes < 1440) return `${Math.floor(minutes / 60)}h ago`;\n return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n}\n","/**\n * Design tokens shared by the widget, the website, the workspace and emails.\n * This file is the source of truth. `npm run tokens` writes service/public/tokens.css from it,\n * and a test fails when the two differ. Emails cannot read CSS variables, so they use the hex values.\n */\nexport const tokens = {\n // Brand: Overplay blue. One accent for buttons, links, open pins and focus.\n accent: '#0068f9',\n 'accent-strong': '#0055d4',\n 'accent-soft': '#eef4ff',\n 'accent-line': '#d3e3fd',\n 'accent-focus': '#99c2ff',\n // Text\n ink: '#121722',\n 'ink-soft': '#3a3f4a',\n muted: '#636874',\n subtle: '#8a8e97',\n // Surfaces and lines\n surface: '#ffffff',\n canvas: '#f7f7f8',\n 'surface-soft': '#f0f1f3',\n line: '#e8e9ec',\n 'line-strong': '#dedfe3',\n // People\n 'avatar-bg': '#e8f1ff',\n 'avatar-ink': '#2560c4',\n // Raised dark chips on the page: the launcher button, toasts and the placing notice.\n inverse: '#121722',\n 'on-inverse': '#ffffff',\n 'inverse-muted': '#b8bcc6',\n // States. \"Resolved\" is the one positive state: resolved pins, saved, verified, approved.\n resolved: '#0f9a6c',\n 'resolved-text': '#0b7a55',\n 'resolved-soft': '#e7f6ef',\n danger: '#c43d3d',\n 'danger-soft': '#fff4f3',\n 'danger-line': '#f3cfcf',\n warning: '#745320',\n 'warning-soft': '#fff8e8',\n 'warning-line': '#ebd59f',\n // Shape. Buttons and chips are pills; cards and windows have soft corners; big page panels have 26px.\n 'radius-sm': '6px',\n radius: '10px',\n 'radius-md': '12px',\n 'radius-lg': '16px',\n 'radius-xl': '26px',\n 'radius-pill': '999px',\n // Hairline rings instead of heavy shadows.\n 'shadow-sm': '0 0 0 1px #1217221a,0 1px 2px #12172229',\n shadow: '0 1px 3px #1217221a,0 16px 32px -12px #12172233',\n font: '\"Inter\",-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif',\n} as const;\n\nexport type TokenName = keyof typeof tokens;\n\n/**\n * The dark theme changes colors and shadows only. The accent stays the brand color (or a site's primaryColor);\n * its soft tints mix with the dark surface, so they follow any accent.\n */\nexport const darkTokens: Partial<Record<TokenName, string>> = {\n 'accent-strong': 'color-mix(in srgb,var(--cw-accent) 66%,#ffffff)',\n 'accent-soft': 'color-mix(in srgb,var(--cw-accent) 18%,#16181d)',\n 'accent-line': 'color-mix(in srgb,var(--cw-accent) 42%,#16181d)',\n 'accent-focus': 'color-mix(in srgb,var(--cw-accent) 60%,#16181d)',\n ink: '#eef0f3',\n 'ink-soft': '#c6c9d0',\n muted: '#9a9ea8',\n subtle: '#767a84',\n surface: '#16181d',\n canvas: '#0e0f12',\n 'surface-soft': '#1f2228',\n line: '#262930',\n 'line-strong': '#33373f',\n 'avatar-bg': '#1b2a45',\n 'avatar-ink': '#9cc3ff',\n inverse: '#23262d',\n 'inverse-muted': '#a6aab3',\n resolved: '#16a877',\n 'resolved-text': '#48d3a0',\n 'resolved-soft': '#13302a',\n danger: '#ec6a6a',\n 'danger-soft': '#341c21',\n 'danger-line': '#5b2b31',\n warning: '#efc56e',\n 'warning-soft': '#2f2718',\n 'warning-line': '#57472a',\n 'shadow-sm': '0 0 0 1px #ffffff14,0 1px 2px #00000066',\n shadow: '0 1px 3px #00000066,0 16px 40px -12px #000000b3',\n};\n\n/** CSS custom property declarations, such as `--cw-accent:#0068f9;`. */\nexport function tokenDeclarations(set: Partial<Record<TokenName, string>> = tokens): string {\n return Object.entries(set).map(([name, value]) => `--cw-${name}:${value};`).join('');\n}\n\n/** The stylesheet the website and workspace load before app.css. */\nexport function tokensStylesheet(): string {\n const lines = (set: Partial<Record<TokenName, string>>, indent: string) =>\n Object.entries(set).map(([name, value]) => `${indent}--cw-${name}: ${value};`).join('\\n');\n // theme.js sets data-theme on <html> when a visitor picks a theme. Without a choice the system setting wins.\n return `/* Generated from src/design/tokens.ts by \\`npm run tokens\\`. Do not edit by hand. */\\n:root {\\n${lines(tokens, ' ')}\\n color-scheme: light;\\n}\\n` +\n `:root[data-theme=\"dark\"] {\\n${lines(darkTokens, ' ')}\\n color-scheme: dark;\\n}\\n` +\n `@media (prefers-color-scheme: dark) {\\n :root:not([data-theme=\"light\"]) {\\n${lines(darkTokens, ' ')}\\n color-scheme: dark;\\n }\\n}\\n`;\n}\n","import { darkTokens, tokenDeclarations } from '../design/tokens';\n\n/** All styles live in the shadow root. No reset or utilities leak into the host. */\nexport const styles = `\n:host{all:initial;${tokenDeclarations()}color:var(--cw-ink);font:16px/1.5 var(--cw-font);letter-spacing:normal;text-align:left;color-scheme:light}\n:host([data-theme=dark]){${tokenDeclarations(darkTokens)}color-scheme:dark}\n@media(prefers-color-scheme:dark){:host([data-theme=system]){${tokenDeclarations(darkTokens)}color-scheme:dark}}\n:host>div{font:16px/1.5 var(--cw-font);color:var(--cw-ink);letter-spacing:normal;text-align:left}*,*::before,*::after{box-sizing:border-box}button,input,textarea,select{font:inherit}button{cursor:pointer}button:disabled{cursor:default;opacity:.45}button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:3px solid var(--cw-accent);outline-offset:3px}button{color:inherit}svg{width:18px;height:18px;flex-shrink:0}button{touch-action:manipulation}img{max-width:100%}[hidden]{display:none!important}\n.launcher{position:fixed;bottom:24px;right:24px;display:flex;align-items:center;justify-content:center;width:52px;height:52px;border:1px solid #ffffff24;background:var(--cw-inverse);color:var(--cw-on-inverse);padding:0;border-radius:50%;box-shadow:0 6px 24px #12172233;font-weight:600;font-size:16px;pointer-events:auto;touch-action:none;user-select:none;-webkit-user-select:none;cursor:grab;transition:transform .16s,box-shadow .16s}.launcher:hover{transform:translateY(-2px);box-shadow:0 8px 28px #20243733}.launcher.dragging{cursor:grabbing;transition:none;transform:scale(1.06);box-shadow:0 12px 32px #2024374d}.launcher[aria-expanded=true]{background:var(--cw-accent)}.launcher>svg{width:23px;height:23px}.badge{position:absolute;top:-5px;right:-5px;font-weight:650;font-size:12px;line-height:18px;min-width:22px;height:22px;border:2px solid var(--cw-surface);border-radius:999px;background:var(--cw-accent);color:#fff;text-align:center;padding:0 4px}.launcher[aria-expanded=true] .badge{background:var(--cw-inverse)}\n.panel{position:fixed;top:0;right:0;bottom:0;width:400px;max-width:100vw;display:flex;flex-direction:column;background:var(--cw-surface);border-left:1px solid var(--cw-line);box-shadow:var(--cw-shadow);pointer-events:auto;overflow:hidden}.panel.entering{animation:slide-in .2s ease-out}.panel.left{right:auto;left:0;border-left:0;border-right:1px solid var(--cw-line);--cw-slide:-24px}.detail{display:flex;flex-direction:column;flex:1;min-height:0}.detail.entering{animation:enter .16s ease-out}.detail:focus{outline:0}.head{display:flex;align-items:center;gap:10px;padding:22px 20px 16px}.brand-icon{width:34px;height:34px;display:grid;place-items:center;background:var(--cw-accent-soft);color:var(--cw-accent);border-radius:50%}.heading{flex:1;min-width:0}.heading h2{font-size:19px;line-height:1.3;letter-spacing:-.4px;margin:0;font-weight:650}.eyebrow{font-size:12px;font-weight:700;letter-spacing:1.4px;color:var(--cw-muted);text-transform:uppercase;margin:0 0 4px}.subtext{color:var(--cw-muted);font-size:14px;margin:4px 0 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.icon-button{width:32px;height:32px;display:inline-grid;place-items:center;background:transparent;border:0;border-radius:50%;flex-shrink:0}.icon-button:hover{background:var(--cw-surface-soft)}.icon-button.danger{color:var(--cw-danger)}.icon-button svg{width:16px;height:16px}.icon-button.outlined{width:42px;height:42px;border:1px solid var(--cw-line-strong);border-radius:50%;color:var(--cw-ink-soft)}.icon-button.outlined svg{width:18px;height:18px}.icon-button.busy:disabled{opacity:1;color:var(--cw-accent)}.icon-button.busy svg{animation:spin .9s linear infinite}.toolbar{padding:0 20px 16px;display:flex;gap:10px;align-items:center}.primary{border:0;border-radius:var(--cw-radius-pill);background:var(--cw-accent);color:#fff;display:inline-flex;gap:7px;align-items:center;justify-content:center;padding:10px 16px;font-size:14px;font-weight:550;white-space:nowrap;box-shadow:inset 0 -1px 0 #12172238;transition:filter .16s}.primary:hover{filter:brightness(.94)}.toolbar .primary{flex:1}.quiet{border:1px solid var(--cw-line-strong);background:var(--cw-surface);color:var(--cw-ink);border-radius:var(--cw-radius-pill);padding:9px 16px;font-size:14px}.quiet:hover{background:var(--cw-canvas)}.quiet.update{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;flex-shrink:0;color:var(--cw-accent);border-color:var(--cw-accent-line);background:var(--cw-accent-soft);font-weight:600}.quiet.update:hover{border-color:var(--cw-accent)}.quiet.update svg{width:14px;height:14px}.scope{display:grid;grid-template-columns:1fr 1fr;gap:4px;margin:0 20px 8px;padding:4px;background:var(--cw-surface-soft);border-radius:var(--cw-radius-pill)}.scope-option{display:flex;gap:7px;align-items:center;justify-content:center;border:0;background:transparent;border-radius:var(--cw-radius-pill);padding:8px 6px;font-size:14px;font-weight:550;color:var(--cw-muted);white-space:nowrap}.scope-option:hover{color:var(--cw-ink)}.scope-option[aria-pressed=true]{background:var(--cw-surface);color:var(--cw-ink);box-shadow:0 1px 3px #2024371f}.scope-option[aria-pressed=true] .count{background:var(--cw-accent-soft);color:var(--cw-accent)}.tabs{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;margin:0 20px 8px;padding:4px;border:1px solid var(--cw-line);border-radius:var(--cw-radius-pill)}.tab{display:flex;gap:7px;align-items:center;justify-content:center;border:0;border-radius:var(--cw-radius-pill);background:transparent;padding:7px 6px;color:var(--cw-muted);font-size:14px;font-weight:550;white-space:nowrap}.tab[aria-pressed=true]{color:var(--cw-on-inverse);background:var(--cw-inverse)}.tab[aria-pressed=true] .count{background:#ffffff2e;color:var(--cw-on-inverse)}.count{background:var(--cw-surface-soft);padding:0 6px;border-radius:5px;font-size:12px;line-height:18px}.search{position:relative;margin:4px 20px 8px}.search>svg{position:absolute;left:11px;top:11px;width:15px;height:15px;color:var(--cw-subtle);pointer-events:none}.search input{border:1px solid var(--cw-line);border-radius:var(--cw-radius);background:var(--cw-canvas);width:100%;padding:9px 38px 9px 34px;color:var(--cw-ink);font-size:14px}.search input::placeholder{color:var(--cw-subtle)}.search input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}.search-clear{position:absolute;right:5px;top:50%;transform:translateY(-50%);width:28px;height:28px;color:var(--cw-muted)}.search-clear svg{width:14px;height:14px}.people{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 20px 6px}.filter-chip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--cw-line);background:var(--cw-surface);color:var(--cw-ink-soft);border-radius:999px;padding:4px 6px 4px 11px;font-size:13px;font-weight:600;white-space:nowrap}.filter-chip:hover{background:var(--cw-canvas)}.filter-chip[aria-pressed=true]{background:var(--cw-accent-soft);border-color:var(--cw-accent-line);color:var(--cw-accent)}.filter-chip[aria-pressed=true] .count{background:var(--cw-surface);color:var(--cw-accent)}.select{position:relative;display:inline-flex;min-width:0;max-width:220px;color:var(--cw-muted)}.select::after{content:'';position:absolute;right:12px;top:50%;width:6px;height:6px;border:solid currentColor;border-width:0 1.5px 1.5px 0;transform:translateY(-70%) rotate(45deg);pointer-events:none}.select select{appearance:none;-webkit-appearance:none;border:1px solid var(--cw-line);background:var(--cw-surface);color:var(--cw-ink-soft);border-radius:999px;padding:5px 30px 5px 11px;font-size:13px;font-weight:600;line-height:18px;max-width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.select select:hover{background:var(--cw-canvas)}.select.chosen{color:var(--cw-accent)}.select.chosen select{background:var(--cw-accent-soft);border-color:var(--cw-accent-line);color:var(--cw-accent)}.select option{color:var(--cw-ink);background:var(--cw-surface)}.link-button{margin-left:auto;border:0;background:transparent;color:var(--cw-accent);font-size:13px;font-weight:600;padding:4px 2px;white-space:nowrap}.link-button:hover{text-decoration:underline}mark.hit{background:color-mix(in srgb,var(--cw-accent) 22%,transparent);color:inherit;border-radius:3px;padding:0 1px;-webkit-box-decoration-break:clone;box-decoration-break:clone}.note-match{display:flex;align-items:center;gap:5px;margin:4px 0 0 31px;font-size:12.5px;line-height:1.5;color:var(--cw-muted);min-width:0}.note-match svg{width:12px;height:12px}.note-match-label{font-weight:600;color:var(--cw-ink-soft);white-space:nowrap;flex-shrink:0;max-width:45%;overflow:hidden;text-overflow:ellipsis}.note-match-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.list{flex:1;overflow:auto;overscroll-behavior:contain;padding:8px 12px 16px;min-height:0}.list-title{display:flex;align-items:center;gap:8px;padding:12px 8px 6px;color:var(--cw-muted);font-size:12px;letter-spacing:1.15px;text-transform:uppercase;font-weight:600}.page-path{text-transform:none;letter-spacing:0;font-size:13px;color:var(--cw-ink-soft);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.page-name{text-transform:none;letter-spacing:0;font-size:13px;font-weight:600;color:var(--cw-ink-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.here{flex-shrink:0;padding:0 6px;border-radius:5px;background:var(--cw-accent-soft);color:var(--cw-accent);font-size:11px;letter-spacing:.4px;line-height:18px}.go{margin-left:auto;display:inline-flex;align-items:center;gap:4px;color:var(--cw-accent);font-weight:600}.note.current{background:var(--cw-accent-soft);border-color:var(--cw-accent-line)}.note{display:block;text-align:left;width:100%;border:1px solid transparent;background:var(--cw-surface);color:var(--cw-ink);border-radius:10px;padding:9px 10px;margin-bottom:2px}.note .note-header .via{color:var(--cw-muted);font-size:10px;max-width:110px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.note-header{margin-bottom:4px;gap:7px}.note .avatar{width:24px;height:24px;font-size:11px}.note .name{font-size:13px}.note .time{margin-left:0}.note-meta{margin-left:auto;display:inline-flex;align-items:center;gap:8px;font-size:12px;color:var(--cw-muted);white-space:nowrap;flex-shrink:0}.note-meta svg{width:12px;height:12px}.note:hover{background:var(--cw-canvas);border-color:var(--cw-line)}.note-header{display:flex;align-items:center;gap:8px;margin-bottom:9px}.avatar{display:inline-grid;place-items:center;width:29px;height:29px;border-radius:50%;background:var(--cw-avatar-bg);color:var(--cw-avatar-ink);font-size:12px;font-weight:700;flex-shrink:0;overflow:hidden}.avatar img{height:100%;width:100%;object-fit:cover}.name{font-size:14px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.time{font-size:12px;color:var(--cw-muted);margin-left:auto;white-space:nowrap}.note-text{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;margin:0 0 0 31px;line-height:1.5;font-size:14px;color:var(--cw-ink-soft);overflow-wrap:anywhere}.note-footer{display:flex;gap:6px;align-items:center;margin:6px 0 0 31px;color:var(--cw-muted);font-size:12px}.note-footer svg{width:12px;height:12px}.note-number{color:var(--cw-accent);font-weight:700}.status{display:inline-flex;align-items:center;gap:4px}.status.resolved{color:var(--cw-resolved-text)}.status-dot{width:5px;height:5px;background:var(--cw-accent);border-radius:50%;display:inline-block}.empty{height:100%;min-height:230px;display:flex;align-items:center;justify-content:center;text-align:center;padding:32px 16px}.empty-icon{position:relative;display:grid;place-items:center;margin:0 auto 18px;width:64px;height:64px;border:1px solid var(--cw-line);border-radius:21px;transform:rotate(-7deg);background:var(--cw-canvas);color:var(--cw-accent)}.empty-icon svg{width:27px;height:27px}.empty h3{font-size:17px;letter-spacing:-.25px;margin:0 0 8px}.empty p{font-size:14px;color:var(--cw-muted);line-height:1.7;margin:0 auto 18px;max-width:230px}.footer{display:flex;align-items:center;gap:9px;border-top:1px solid var(--cw-line);padding:14px 20px;background:var(--cw-canvas)}.footer .avatar{width:25px;height:25px;font-size:11px}.identity{border:0;background:transparent;text-align:left;padding:0;min-width:0;flex:1}.identity strong{display:block;font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.identity small{font-size:12px;color:var(--cw-muted)}.storage-label{font-size:11px;color:var(--cw-muted);text-align:right;line-height:1.5;max-width:105px}.storage-dot{display:inline-block;width:5px;height:5px;background:var(--cw-resolved);border-radius:50%;margin-right:4px}.error{padding:12px 16px;margin:12px 20px;border:1px solid var(--cw-danger-line);background:var(--cw-danger-soft);color:var(--cw-danger);border-radius:10px;font-size:14px;overflow-wrap:anywhere}.error button{display:block;margin-top:8px}.notice{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:1;background:var(--cw-inverse);color:var(--cw-on-inverse);border:1px solid #ffffff20;border-radius:12px;padding:12px 15px;display:flex;align-items:center;gap:12px;font-size:14px;box-shadow:0 6px 30px #0002;pointer-events:auto;max-width:calc(100vw - 32px)}.notice kbd{font-size:12px;color:var(--cw-inverse-muted);border:1px solid #ffffff30;border-radius:4px;padding:2px 5px}.notice button{color:var(--cw-on-inverse)}.notice.beside-panel{left:calc(50% - 200px)}.notice.beside-panel.left{left:calc(50% + 200px)}.pins{position:fixed;inset:0;pointer-events:none}.pin{position:absolute;width:32px;height:36px;transform:translate(-50%,-100%);border:2px solid #fff;border-radius:15px 15px 15px 4px;background:var(--cw-accent);color:#fff;box-shadow:var(--cw-shadow-sm);display:grid;place-items:center;font-size:13px;font-weight:650;pointer-events:auto;transition:scale .15s}.pin:hover,.pin[aria-pressed=true]{scale:1.12}.pin.resolved{background:var(--cw-resolved)}.pin.highlight{animation:pulse 1s ease-out 2}.pin.hovered{animation:pulse 1s ease-out infinite;scale:1.12;opacity:1!important}.focus-ring.hover-ring{animation:none;border-style:dashed}.focus-ring{position:absolute;border:2px solid var(--cw-accent);border-radius:var(--cw-radius);background:color-mix(in srgb,var(--cw-accent) 6%,transparent);pointer-events:none;animation:enter .16s ease-out}.pick-ring{border-style:dashed;animation:none;transition:left .08s,top .08s,width .08s,height .08s}.pin:focus-visible{outline-offset:3px}.pin.preview{pointer-events:none;opacity:.7}.pin.movable{cursor:grab;touch-action:none}.pins.focused .pin:not([aria-pressed=true]):not(.dragging){opacity:.3;transition:opacity .15s,scale .15s}.pins.focused .pin:hover,.pins.focused .pin:focus-visible{opacity:1}.pin.dragging{cursor:grabbing;scale:1.15;pointer-events:none;box-shadow:var(--cw-shadow);transition:none;z-index:1}.detail-hint{margin:16px 20px 12px;color:var(--cw-muted);font-size:14px;line-height:1.6}.compose{padding:0 20px 20px}.compose textarea,.reply-bar textarea{scrollbar-width:none}\n.compose textarea::-webkit-scrollbar,.reply-bar textarea::-webkit-scrollbar{display:none}\n.compose textarea{width:100%;display:block;resize:vertical;min-height:120px;max-height:40vh;border:1px solid var(--cw-line);border-radius:var(--cw-radius);padding:12px;color:var(--cw-ink);background:var(--cw-canvas);font-size:16px;line-height:1.6}.compose textarea::placeholder{color:var(--cw-subtle)}.compose-bar{display:flex;align-items:center;gap:10px;justify-content:space-between;margin-top:12px}.compose-hint{font-size:11px;color:var(--cw-muted)}.thread-body{overflow:auto;overscroll-behavior:contain;flex:1;min-height:0;padding:18px 20px 4px}.message{padding:16px 0;border-bottom:1px solid var(--cw-line)}.message:first-child{padding-top:0}.message:last-child{border:0}.message-text{font-size:16px;line-height:1.7;white-space:pre-wrap;overflow-wrap:anywhere;margin:10px 0 0 37px}.thread-actions{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:12px 20px;border-top:1px solid var(--cw-line)}.resolve{display:inline-flex;align-items:center;gap:7px;white-space:nowrap;font-weight:600}.resolve svg{width:16px;height:16px;color:var(--cw-resolved)}.resolve:hover{border-color:var(--cw-resolved);background:var(--cw-resolved-soft);color:var(--cw-resolved-text)}.resolve.done svg{color:var(--cw-muted)}.resolve.done:hover{border-color:var(--cw-line-strong);background:var(--cw-canvas);color:var(--cw-ink)}.confirm-delete{display:flex;align-items:center;gap:8px}.danger-button{display:inline-flex;align-items:center;gap:6px;border:0;border-radius:var(--cw-radius-pill);background:var(--cw-danger);color:#fff;padding:10px 12px;font-size:14px;font-weight:600;white-space:nowrap}.danger-button svg{width:15px;height:15px}.detail-head{padding:12px 20px 16px;border-bottom:1px solid var(--cw-line)}.detail-bar{display:flex;align-items:center;justify-content:space-between;margin:0 -8px 12px -10px}.back-link{display:inline-flex;align-items:center;gap:6px;border:0;background:transparent;border-radius:var(--cw-radius-sm);padding:6px 10px;font-size:14px;font-weight:600;color:var(--cw-muted)}.back-link:hover{background:var(--cw-surface-soft);color:var(--cw-ink)}.back-link svg{width:16px;height:16px}.detail-title{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.detail-title h2{font-size:20px;line-height:1.3;letter-spacing:-.4px;margin:0;font-weight:650}.detail-head .subtext{white-space:normal}.chip{display:inline-flex;align-items:center;gap:6px;padding:1px 9px;border-radius:999px;background:var(--cw-accent-soft);color:var(--cw-accent);font-size:12px;font-weight:600;line-height:20px}.chip svg{width:12px;height:12px}.chip.resolved{background:var(--cw-resolved-soft);color:var(--cw-resolved-text)}.thread .compose{padding-top:12px;border-top:1px solid var(--cw-line)}.thread textarea{min-height:88px}.anchor-status{margin:0 20px 12px;padding:12px;background:var(--cw-canvas);border:1px solid var(--cw-line);border-radius:10px;color:var(--cw-muted);font-size:13px;line-height:1.55}.anchor-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:8px}.anchor-icon{display:grid;place-items:center;flex-shrink:0;width:28px;height:28px;border-radius:8px;background:var(--cw-warning-soft);color:var(--cw-warning)}.anchor-status.removed .anchor-icon{background:var(--cw-danger-soft);color:var(--cw-danger)}.anchor-icon svg{width:16px;height:16px}.anchor-titles{display:flex;flex-direction:column;min-width:0}.anchor-titles strong{color:var(--cw-ink);font-size:13px;font-weight:650;line-height:1.35}.anchor-target{color:var(--cw-ink-soft);overflow-wrap:anywhere}.identity-form{padding:0 20px 20px}.identity-form label{font-size:14px;font-weight:600;display:block;margin-bottom:7px}.identity-form input{width:100%;border:1px solid var(--cw-line);background:var(--cw-canvas);color:var(--cw-ink);padding:10px;border-radius:var(--cw-radius);margin-bottom:14px}.identity-form p{font-size:13px;color:var(--cw-muted);line-height:1.7;margin:0 0 14px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n@keyframes enter{from{opacity:0;translate:0 5px}to{opacity:1;translate:0 0}}@keyframes slide-in{from{opacity:0;translate:var(--cw-slide,24px) 0}to{opacity:1;translate:0 0}}@keyframes pulse{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--cw-accent) 55%,transparent)}100%{box-shadow:0 0 0 16px transparent}}@keyframes spin{to{rotate:360deg}}@keyframes toast-out{to{opacity:0;translate:0 6px}}\n.toasts{position:fixed;right:24px;bottom:88px;width:320px;max-width:calc(100vw - 32px);display:flex;flex-direction:column;gap:8px;pointer-events:none}.toasts.left{right:auto;left:24px}.toasts.top{bottom:auto;top:88px;flex-direction:column-reverse}.toasts.beside-panel{right:424px;bottom:24px;max-width:calc(100vw - 448px)}.toasts.beside-panel.left{right:auto;left:424px}.toasts.beside-panel.top{top:24px;bottom:auto}.toast{display:flex;gap:10px;align-items:flex-start;background:var(--cw-inverse);color:var(--cw-on-inverse);border:1px solid #ffffff20;border-radius:var(--cw-radius-md,12px);padding:12px 14px;box-shadow:var(--cw-shadow,var(--cw-shadow));animation:enter .18s ease-out}.toast.leaving{animation:toast-out .2s ease-in forwards}.toast-icon{background:var(--cw-accent-soft,var(--cw-accent-soft));color:var(--cw-accent)}.toast-icon svg{width:15px;height:15px}.toast-body{min-width:0;flex:1}.toast-title{margin:0;font-size:14px;line-height:1.4;color:var(--cw-inverse-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.toast-title strong{color:var(--cw-on-inverse);font-weight:600}.toast-number{margin-left:6px;padding:0 6px;border-radius:5px;background:var(--cw-accent-soft,var(--cw-accent-soft));color:var(--cw-accent);font-size:12px;font-weight:650;line-height:18px;display:inline-block}.toast-text{margin:3px 0 0;font-size:14px;line-height:1.5;color:#fff;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}\n.popover{position:fixed;left:0;top:0;z-index:1;width:320px;max-height:min(560px,calc(100vh - 24px));display:flex;flex-direction:column;background:var(--cw-surface);border:1px solid var(--cw-line);border-radius:var(--cw-radius-lg);box-shadow:var(--cw-shadow);pointer-events:auto;color:var(--cw-ink)}.popover>.detail{min-height:0}.popover .detail.entering{animation:pop .18s cubic-bezier(.2,.9,.3,1.15)}@keyframes pop{from{opacity:0;transform:translateY(6px) scale(.97)}}.popover.sheet{left:8px;right:8px;top:auto;bottom:8px;width:auto;max-height:75vh}\n.card-head .detail-bar{margin:0;padding:12px 12px 0 10px}.pop-head{position:relative;display:flex;align-items:center;gap:10px;padding:14px 10px 12px 14px}.panel .pop-head{padding:12px 14px 12px 20px}.pop-icon{display:grid;place-items:center;flex-shrink:0;width:30px;height:30px;border-radius:50%;background:var(--cw-accent-soft);color:var(--cw-accent)}.pop-icon svg{width:15px;height:15px}.pop-title{flex:1;min-width:0}.pop-title h2{margin:0;font-size:14px;font-weight:650;letter-spacing:-.2px;line-height:1.35}.pop-sub{margin:0;font-size:12px;line-height:1.5;color:var(--cw-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pop-head .icon-button{width:28px;height:28px;color:var(--cw-muted)}.pop-head .icon-button:hover{background:var(--cw-surface-soft);color:var(--cw-ink)}.pop-head .icon-button svg{width:16px;height:16px}.pop-head .more svg{stroke-width:3.2}\n.pop-menu{position:absolute;top:46px;right:10px;z-index:2;min-width:190px;padding:4px;background:var(--cw-surface);border:1px solid var(--cw-line);border-radius:var(--cw-radius-md);box-shadow:var(--cw-shadow)}.menu-item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 10px;border:0;border-radius:8px;background:transparent;font-size:13px;text-align:left;color:var(--cw-ink)}.menu-item:hover{background:var(--cw-surface-soft)}.menu-item svg{width:15px;height:15px;color:var(--cw-muted)}.menu-item.danger,.menu-item.danger svg{color:var(--cw-danger)}\n.thread .thread-body{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;padding:0 14px}.panel .thread .thread-body{padding:0 20px}.thread .message{padding:12px 0;border-top:1px solid var(--cw-line);border-bottom:0}.thread .message:first-child{padding-top:12px}.thread .note-header{gap:8px;margin:0}.thread .avatar{width:26px;height:26px;font-size:10px}.thread .name{font-size:14px}.thread .time{font-size:12px}.thread .message-text{margin:4px 0 0 34px;font-size:14px;line-height:1.55;color:var(--cw-ink-soft)}.panel .thread .message-text{font-size:15px}\n.thread-actions{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;border-top:1px solid var(--cw-line)}.panel .thread-actions{padding:12px 20px}.reply-bar{flex:1;min-width:0;display:flex;align-items:flex-end;gap:8px}.reply-bar textarea{flex:1;min-width:0;min-height:32px;max-height:120px;resize:none;padding:6px 10px;border:1px solid var(--cw-line-strong);border-radius:var(--cw-radius);background:var(--cw-surface);color:var(--cw-ink);font-size:13px;line-height:1.45;overflow:auto}.reply-bar textarea:focus-visible{outline:0;border-color:var(--cw-accent);box-shadow:0 0 0 3px var(--cw-accent-line)}.reply-bar textarea::placeholder{color:var(--cw-subtle)}.thread-actions .primary{padding:7px 12px;font-size:13px;border-radius:var(--cw-radius-pill);white-space:nowrap}.thread-actions .primary svg{width:14px;height:14px}.thread-actions .primary.resolve,.thread-actions .primary.resolve:hover{border:0;background:var(--cw-accent);color:#fff}.thread-actions .primary.resolve:hover{filter:brightness(.94)}.thread-actions .primary.resolve svg{color:currentColor}.thread-actions .status{display:inline-flex;align-items:center;gap:5px;font-size:13px;font-weight:600;color:var(--cw-resolved-text)}.thread-actions .status svg{width:14px;height:14px}.thread-actions .reopen{padding:6px 12px;font-size:13px;font-weight:500}\n.popover .anchor-status,.popover .error{margin:0 14px 10px}.new-comment .compose{margin:0 14px;padding:14px 0;border-top:1px solid var(--cw-line)}.panel .new-comment .compose{margin:0 20px;padding:16px 0 20px}.popover .compose textarea:focus-visible{outline:0;border-color:var(--cw-accent);box-shadow:0 0 0 3px var(--cw-accent-line)}.popover .new-comment .compose textarea{min-height:76px;font-size:14px}.popover .compose-hint{font-size:11px}\n.pin.below{transform:translate(-50%,0);border-radius:4px 15px 15px 15px}\n.pick-ring{border-style:solid;background:transparent}.head-actions{display:flex;align-items:center;gap:2px;margin-right:-6px}\n.head-actions>.icon-button{color:var(--cw-muted)}\n.head-actions>.icon-button:hover{color:var(--cw-ink)}\n.menu-wrap{position:relative;display:flex}\n.user-button{display:grid;place-items:center;width:36px;height:36px;padding:0;border:0;border-radius:50%;background:transparent}\n.user-button .avatar{width:28px;height:28px;font-size:11px;box-shadow:0 0 0 2px var(--cw-surface),0 0 0 3px var(--cw-line)}\n.user-button:hover .avatar,.user-button[aria-expanded=true] .avatar{box-shadow:0 0 0 2px var(--cw-surface),0 0 0 3px var(--cw-accent)}\n.quiet.sign-in{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;font-size:13px;font-weight:600;margin-right:2px}\n.quiet.sign-in svg{width:14px;height:14px}\n.user-menu{top:calc(100% + 8px);right:-40px;min-width:256px;padding:6px}\n.menu-user{display:flex;align-items:center;gap:10px;padding:8px 8px 10px;margin-bottom:4px;border-bottom:1px solid var(--cw-line)}\n.menu-user .avatar{width:34px;height:34px;font-size:13px}\n.menu-user-text{min-width:0}\n.menu-user-text strong{display:block;font-size:14px;font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.menu-user-text small{display:block;font-size:12px;color:var(--cw-muted)}\n.menu-note{display:flex;align-items:center;gap:2px;margin:4px 0 0;padding:8px 10px 4px;border-top:1px solid var(--cw-line);font-size:12px;color:var(--cw-muted)}\n.footer{justify-content:space-between}\n.footer-note{font-size:13px;color:var(--cw-muted)}\n.settings-body{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;padding:4px 20px 12px}\n.setting-group{padding:14px 0 6px}\n.setting-group+.setting-group{border-top:1px solid var(--cw-line)}\n.setting-group h3{margin:0 0 6px;font-size:12px;font-weight:650;letter-spacing:1.1px;text-transform:uppercase;color:var(--cw-muted)}\n.setting{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:9px 0}\n.setting-text{min-width:0}\n.setting-text strong{display:block;font-size:14px;font-weight:600}\n.setting-text small{display:block;font-size:12px;line-height:1.5;color:var(--cw-muted)}\n.segmented{display:inline-flex;flex-shrink:0;gap:2px;padding:3px;background:var(--cw-surface-soft);border-radius:var(--cw-radius-pill)}\n.segment{border:0;background:transparent;border-radius:var(--cw-radius-pill);padding:5px 10px;font-size:13px;font-weight:600;color:var(--cw-muted);white-space:nowrap}\n.segment:hover{color:var(--cw-ink)}\n.segment[aria-pressed=true]{background:var(--cw-surface);color:var(--cw-ink);box-shadow:0 1px 3px #2024371f}\n.switch{position:relative;flex-shrink:0;width:38px;height:22px;padding:0;border:0;border-radius:999px;background:var(--cw-line-strong);transition:background .16s}\n.switch::after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 3px #20243733;transition:translate .16s}\n.switch[aria-checked=true]{background:var(--cw-accent)}\n.switch[aria-checked=true]::after{translate:16px 0}\n.switch:disabled{opacity:.45;cursor:not-allowed}\n.swatches{display:flex;justify-content:space-between;gap:6px;width:100%}\n.setting.wide{flex-direction:column;align-items:stretch;gap:10px}\n.swatch{width:22px;height:22px;padding:0;border:0;border-radius:50%;background:var(--swatch);box-shadow:inset 0 0 0 1px var(--cw-line-strong)}\n.swatch[aria-pressed=true]{box-shadow:0 0 0 2px var(--cw-surface),0 0 0 4px var(--swatch)}\n.swatch:hover{scale:1.1}\n.pin-sample{display:flex;align-items:flex-end;gap:14px;height:62px;margin:2px 0 6px;padding:0 16px 12px;border:1px dashed var(--cw-line-strong);border-radius:var(--cw-radius-md);background:var(--cw-canvas)}\n.pin-sample .pin{position:static;transform:none;pointer-events:none}\n.pin-sample.small .pin{width:26px;height:30px;border-radius:13px 13px 13px 4px;font-size:11px}\n.pin-sample.resolved-gray .pin.resolved{background:var(--cw-subtle)}\n.launcher.colored,.launcher.colored[aria-expanded=true]{background:var(--cw-launcher)}.launcher.colored .badge,.launcher-mini.colored .badge{background:var(--cw-inverse)}\n.launcher-sample{display:flex;align-items:center;gap:14px;height:72px;margin:2px 0 6px;padding:0 16px;border:1px dashed var(--cw-line-strong);border-radius:var(--cw-radius-md);background:var(--cw-canvas)}\n.launcher-mini{position:relative;display:grid;place-items:center;width:42px;height:42px;border:1px solid #ffffff24;border-radius:50%;background:var(--cw-inverse);color:var(--cw-on-inverse);box-shadow:0 6px 24px #12172233}.launcher-mini.colored{background:var(--cw-launcher)}\n.launcher-mini>svg{width:19px;height:19px}\n.pin-sample-text{margin-left:auto;font-size:12px;color:var(--cw-muted)}\n.settings-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 20px;border-top:1px solid var(--cw-line);background:var(--cw-canvas);font-size:12px;color:var(--cw-muted)}\n.settings-foot .quiet{padding:7px 11px;font-size:13px}\n.pins.small .pin{width:26px;height:30px;border-radius:13px 13px 13px 4px;font-size:11px}\n.pins.resolved-gray .pin.resolved{background:var(--cw-subtle)}\n.pins.small .pin.below{border-radius:4px 13px 13px 13px}\n.note{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:12px;align-items:start}\n.note-main{min-width:0}\n.note .time{margin-left:0}\n.note-meta{flex-direction:column;align-items:flex-end;gap:2px;margin:2px 0 0;min-width:64px;line-height:18px}\n.note-number,.count{font-variant-numeric:tabular-nums}\n.count{min-width:20px;text-align:center}\n.hidden-flag{display:inline-flex;align-items:center;gap:4px;max-width:100%;padding:1px 7px 1px 6px;border-radius:6px;background:var(--cw-warning-soft);color:var(--cw-warning);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.hidden-flag.removed{background:var(--cw-danger-soft);color:var(--cw-danger)}.note-footer .hidden-flag svg{width:12px;height:12px;flex-shrink:0}\n.pin.detached{border-style:dashed;opacity:.85;background:color-mix(in srgb,var(--cw-accent) 70%,var(--cw-subtle))}\n.anchor-status p{margin:0}\n.page-path.sub{font-size:11px;color:var(--cw-subtle);flex-shrink:1}\n.anchor-status .quiet{display:inline-flex;align-items:center;gap:6px;margin-top:10px;padding:6px 11px 6px 9px;font-size:13px;font-weight:600}.anchor-status .quiet svg{width:15px;height:15px;flex-shrink:0}\n@media(max-width:600px){.panel,.panel.left{inset:0;width:auto;border:0}.panel.placing{visibility:hidden}.panel.behind{visibility:hidden}.launcher{right:16px;bottom:16px}.notice,.notice.beside-panel,.notice.beside-panel.left{left:50%;bottom:24px;width:calc(100vw - 32px);font-size:13px}.compose-hint{display:none}.compose-bar{justify-content:flex-end}.toasts,.toasts.left,.toasts.beside-panel,.toasts.beside-panel.left{left:16px;right:16px;width:auto;max-width:none;bottom:82px}.toasts.top,.toasts.beside-panel.top{top:82px;bottom:auto}.toasts.beside-panel{display:none}.head{padding-top:18px}}\n.popover.moving{visibility:hidden;pointer-events:none}\n.update-bar{display:grid;grid-template-columns:30px 1fr auto;align-items:start;gap:4px 12px;padding:14px 12px 16px 20px;background:var(--cw-accent-soft);border-top-color:var(--cw-accent-line)}.update-icon{display:grid;place-items:center;width:30px;height:30px;border-radius:9px;background:var(--cw-surface);color:var(--cw-accent);box-shadow:var(--cw-shadow-sm)}.update-icon svg{width:16px;height:16px}.update-text{display:flex;flex-direction:column;gap:1px;min-width:0;color:var(--cw-muted);font-size:12.5px;line-height:1.45}.update-text strong{color:var(--cw-ink);font-size:13px;font-weight:650}.update-command{grid-column:1/-1;display:flex;align-items:center;gap:8px;margin:8px 8px 0 0;padding:4px 4px 4px 10px;border:1px solid var(--cw-line);border-radius:9px;background:var(--cw-surface)}.update-command code{flex:1;min-width:0;color:var(--cw-ink);font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.update-bar .quiet.update{padding:5px 12px;border-radius:var(--cw-radius-pill)}\n@media(max-width:600px){.search input{font-size:16px}.select{max-width:100%}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}\n`;\n","import type { RevealStep, RevealTarget } from './types';\n\n/*\n * Opens the menu, drawer, tab or popover that hides a comment's element.\n *\n * When a person makes a note, the menu that holds the element is open on their screen. That is the only moment we know\n * for sure what opened it. The recorder watches each real (trusted) press and hover, and what changed on the page in the\n * next moment. At pick time it walks back from the element: the newest action whose changes contain the element is a\n * step, then the action that showed that trigger, and so on. Later, replay() repeats the steps the way a person would.\n * This works the same for every framework, because it only looks at events and DOM changes.\n */\n\nconst WINDOW = 700; // How long after an action its page changes count.\nconst MAX_AGE = 120_000; // Older actions are not part of the open path.\nconst MAX_STEPS = 6;\n\n// ---------- visibility ----------\n\n/**\n * Rendered and not hidden by a closed <details>, opacity, a collapsed parent (max-height: 0), `inert`, or a fixed\n * drawer moved off the screen. An element scrolled out of view, or out of a scroll box, still counts as visible.\n */\nexport function isVisible(el: Element | null | undefined): boolean {\n if (!el || !el.isConnected || !el.getClientRects().length) return false;\n const rect = el.getBoundingClientRect();\n if (rect.width < 1 || rect.height < 1 || getComputedStyle(el).visibility !== 'visible' || el.closest('[inert]')) return false;\n const check = (el as Element & { checkVisibility?: (options: object) => boolean }).checkVisibility;\n if (check && !check.call(el, { opacityProperty: true, visibilityProperty: true })) return false;\n let fixed = false;\n for (let parent: Element | null = el; parent && parent !== document.documentElement; parent = parent.parentElement) {\n const style = getComputedStyle(parent);\n if (!check && parseFloat(style.opacity) < .05) return false;\n if (style.position === 'fixed') fixed = true;\n if (parent === el || parent === document.body) continue;\n const clips = /(hidden|clip)/.test(style.overflowX + style.overflowY);\n const collapsed = /(auto|scroll)/.test(style.overflowX + style.overflowY) && (parent.clientWidth < 1 || parent.clientHeight < 1);\n if (clips || collapsed) {\n const box = parent.getBoundingClientRect();\n if (Math.min(rect.right, box.right) - Math.max(rect.left, box.left) < 1 || Math.min(rect.bottom, box.bottom) - Math.max(rect.top, box.top) < 1) return false;\n }\n }\n return !(fixed && (rect.right <= 0 || rect.bottom <= 0 || rect.left >= innerWidth || rect.top >= innerHeight));\n}\n\n// ---------- naming and finding triggers ----------\n\nconst clean = (text: string | null | undefined, max = 120) => (text ?? '').replace(/\\s+/g, ' ').trim().slice(0, max);\n// Framework ids change on each load: React useId, Radix, Headless UI, MUI, Vue, React Aria.\nconst GENERATED = /:|(^|[-_])(r\\d+|radix|headlessui|mui|v-\\d|react-aria|\\d{3,})/i;\nconst NESTED = 'ul,ol,[role=menu],[role=listbox],[popover],dialog,nav';\n/** The element's own text, so a menu item's name does not include its submenu. textContent ignores text-transform. */\nfunction ownText(el: Element): string {\n let text = '';\n for (const node of Array.from(el.childNodes)) {\n if (node.nodeType === Node.TEXT_NODE) text += node.textContent;\n else if (node instanceof Element && !node.matches(NESTED) && !node.querySelector(`${NESTED},a,button`)) text += ` ${node.textContent}`;\n }\n return clean(text) || clean(el.firstElementChild?.textContent);\n}\nfunction nameOf(el: Element): string {\n const ids = el.getAttribute('aria-labelledby');\n return clean(el.getAttribute('aria-label')) ||\n clean(ids?.split(/\\s+/).map(id => document.getElementById(id)?.textContent ?? '').join(' ')) ||\n clean(el.getAttribute('title')) || ownText(el) ||\n clean(el.querySelector('img[alt]')?.getAttribute('alt')) || clean(el.querySelector('svg title')?.textContent);\n}\nconst sameName = (a: string, b: string) => a.toLowerCase() === b.toLowerCase();\nconst ROLES: Record<string, string> = { BUTTON: 'button', SUMMARY: 'button', A: 'link', LABEL: 'label', INPUT: 'input' };\nfunction selectorOf(el: Element): string {\n const parts: string[] = [];\n for (let node: Element | null = el; node && node !== document.body && node !== document.documentElement; node = node.parentElement) {\n for (const attr of ['data-overplay-anchor', 'data-testid', 'data-test', 'data-cy']) {\n const value = node.getAttribute(attr);\n const selector = value && `[${attr}=\"${CSS.escape(value)}\"]`;\n if (selector && document.querySelectorAll(selector).length === 1) { parts.unshift(selector); return parts.join(' > '); }\n }\n if (node.id && !GENERATED.test(node.id) && document.querySelectorAll(`#${CSS.escape(node.id)}`).length === 1) {\n parts.unshift(`#${CSS.escape(node.id)}`); return parts.join(' > ');\n }\n const tag = node.tagName;\n const siblings = node.parentElement ? Array.from(node.parentElement.children).filter(child => child.tagName === tag) : [node];\n parts.unshift(`${tag.toLowerCase()}:nth-of-type(${siblings.indexOf(node) + 1})`);\n }\n return parts.join(' > ');\n}\nfunction describe(el: Element): RevealTarget {\n const name = nameOf(el);\n return { selector: selectorOf(el), role: el.getAttribute('role') || ROLES[el.tagName] || el.tagName.toLowerCase(), tag: el.tagName.toLowerCase(), ...(name ? { name } : {}) };\n}\n/** By the saved selector when its name still matches, else by role or tag and name, else by the selector alone. Visible matches win. */\nexport function findTarget(target: RevealTarget): Element | null {\n const pool: Element[] = [];\n const bySelector = () => { try { return document.querySelector(target.selector); } catch { return null; } };\n const first = bySelector();\n if (first && (!target.name || sameName(nameOf(first), target.name))) pool.push(first);\n if (target.name) {\n const selector = [target.tag, target.role && /^[a-z]+$/.test(target.role) ? `[role=\"${target.role}\"]` : ''].filter(Boolean).join(',');\n try { pool.push(...Array.from(document.querySelectorAll(selector || '*')).filter(el => sameName(nameOf(el), target.name!))); } catch { /* Invalid tag. */ }\n }\n if (!pool.length && first) pool.push(first);\n return pool.find(isVisible) ?? pool[0] ?? null;\n}\n\n// ---------- recording ----------\n\ntype Action = { kind: 'press' | 'hover'; el: Element; time: number; changed: Set<Element>; added: Set<Element> };\nconst CONTROL = 'button,summary,label,[role=button],[role=tab],[role=menuitem],[aria-haspopup],[aria-expanded],[aria-controls],[popovertarget],[data-bs-toggle],a[href^=\"#\"],input[type=checkbox],input[type=radio]';\n// Never replay a press that leaves the page or sends a form. Steps come from other people, so replay checks this too,\n// and also skips buttons named like an action that changes data.\nconst unsafe = (el: Element) => el.matches('a[href]:not([href^=\"#\"]):not([href=\"\"]),[type=submit],form button:not([type])') && !el.matches('[aria-haspopup],[aria-expanded]');\nconst ACTION = /\\b(delete|remove|erase|destroy|pay|buy|purchase|checkout|order|send|submit|publish|confirm|sign ?out|log ?out|unsubscribe|cancel subscription|deactivate)\\b/i;\nconst risky = (el: Element) => unsafe(el) || (!el.matches('[aria-haspopup],[aria-expanded],[aria-controls],summary,[popovertarget],[data-bs-toggle]') && ACTION.test(nameOf(el)));\nconst KEYS = ['Enter', ' ', 'ArrowDown', 'ArrowRight'];\nconst VISUAL = /^(display|visibility|opacity|transform|translate|max-height|height|clip|clip-path|left|top|right|bottom|inset|pointer-events)$/;\n\n/** What a person meant to press: a control, else the outermost element with a pointer cursor (icons drawn with ::before/::after). */\nfunction pressable(el: Element): Element {\n const control = el.closest(CONTROL);\n if (control) return control;\n let best = el;\n for (let parent: Element | null = el; parent && parent !== document.body; parent = parent.parentElement) {\n if (getComputedStyle(parent).cursor === 'pointer') best = parent; else if (best !== el) break;\n }\n return best;\n}\n\nexport class RevealRecorder {\n private actions: Action[] = [];\n private open = new Set<Action>();\n private lastHover: Element | null = null;\n private observer: MutationObserver | null = null;\n /**\n * @param ignore The widget's own elements.\n * @param paused True while the widget takes page presses itself (placing a note, dragging a pin). Those presses open\n * nothing on the page, and page changes right after them are not theirs.\n */\n constructor(private ignore: (el: Element) => boolean, private paused: () => boolean = () => false) {}\n\n start(signal: AbortSignal): void {\n const options = { capture: true, signal };\n for (const type of ['pointerdown', 'mousedown', 'click', 'keydown']) document.addEventListener(type, this.onPress as EventListener, options);\n document.addEventListener('mouseover', this.onHover, options);\n // Native popovers, checkboxes and hash links change state without a DOM mutation.\n document.addEventListener('toggle', this.onState, options);\n document.addEventListener('change', this.onState, options);\n window.addEventListener('hashchange', () => {\n const id = decodeURIComponent(location.hash.slice(1));\n const el = id && document.getElementById(id);\n if (el) this.note(el, false);\n }, { signal });\n this.observer = new MutationObserver(this.onMutations);\n this.observer.observe(document, { subtree: true, childList: true, attributes: true,\n attributeFilter: ['class', 'style', 'hidden', 'open', 'aria-expanded', 'aria-hidden', 'data-state', 'data-open', 'data-headlessui-state'] });\n signal.addEventListener('abort', () => { this.observer?.disconnect(); this.actions = []; this.open.clear(); });\n }\n\n private track(kind: Action['kind'], el: Element): void {\n const action: Action = { kind, el, time: performance.now(), changed: new Set(), added: new Set() };\n this.actions.push(action); this.keep(action);\n if (this.actions.length > 40) this.actions.shift();\n }\n private keep(action: Action): void { this.open.add(action); setTimeout(() => this.open.delete(action), WINDOW); }\n private target(event: Event): Element | null {\n const el = event.composedPath().find((node): node is Element => node instanceof Element);\n return el && !this.ignore(el) ? el : null;\n }\n private onPress = (event: KeyboardEvent | MouseEvent): void => {\n if (!event.isTrusted || (event instanceof KeyboardEvent && !KEYS.includes(event.key))) return;\n const el = this.target(event);\n if (!el) return;\n if (this.paused()) { this.open.clear(); return; }\n // pointerdown, mousedown and click are one press. A click on a label also clicks its checkbox.\n const last = this.lastAction('press');\n if (last && (last.el === el || (last.el as HTMLLabelElement).control === el) && performance.now() - last.time < 500) { this.keep(last); return; }\n this.track('press', el);\n };\n private onHover = (event: MouseEvent): void => {\n if (!event.isTrusted) return;\n const el = this.target(event);\n if (!el || el === this.lastHover) return;\n this.lastHover = el;\n // Hovers are frequent. Keep only the ones that changed something.\n this.actions = this.actions.filter(action => action.kind === 'press' || this.open.has(action) || action.changed.size);\n this.track('hover', el);\n };\n private onState = (event: Event): void => { if (event.target instanceof Element) this.note(event.target, false); };\n private onMutations = (records: MutationRecord[]): void => {\n if (!this.open.size) return;\n for (const record of records) {\n // The widget pushes the page aside with a margin on <html> or <body>. That is not the page opening something.\n if (record.type === 'attributes' && record.attributeName === 'style' && (record.target === document.body || record.target === document.documentElement)) continue;\n const nodes = record.type === 'childList' ? Array.from(record.addedNodes) : [record.target];\n for (const node of nodes) if (node instanceof Element) this.note(node, record.type === 'childList');\n }\n };\n /** A change belongs to the newest action still in its window, or a submenu hover is credited to the first click. */\n private note(el: Element, added: boolean): void {\n if (this.ignore(el)) return;\n let action: Action | undefined;\n for (const candidate of this.actions) if (this.open.has(candidate)) action = candidate;\n if (!action) return;\n action.changed.add(el); if (added) action.added.add(el);\n }\n private lastAction(kind: Action['kind']): Action | undefined {\n for (let i = this.actions.length - 1; i >= 0; i--) if (this.actions[i].kind === kind) return this.actions[i];\n return undefined;\n }\n\n /** The steps that show `target` again. Call it when the person picks the element. Empty when it is on the page itself. */\n capture(target: Element): RevealStep[] {\n const now = performance.now();\n const steps: RevealStep[] = [];\n const elements: Element[] = [];\n const used = new Set<Action>();\n let want = target;\n for (let i = this.actions.length - 1; i >= 0 && steps.length < MAX_STEPS; i--) {\n const action = this.actions[i];\n if (now - action.time > MAX_AGE || used.has(action) || !action.el.isConnected || want.contains(action.el)) continue;\n const el = action.kind === 'press' ? pressable(action.el) : action.el;\n if ((el.contains(want) && !el.matches('label')) || risky(el) || !this.opened(action, el, want)) continue;\n // Class changes during a hover right after a press that opened the same thing are that press's transitions.\n if (action.kind === 'hover' && !Array.from(action.added).some(node => node.isConnected && node.contains(want)) &&\n this.actions.some(press => press.kind === 'press' && press.time <= action.time && action.time - press.time < 800 && this.changedFor(press, want))) continue;\n if (action.kind === 'hover' && elements[0] === el) continue;\n steps.unshift({ action: action.kind, target: describe(el) }); elements.unshift(el);\n used.add(action); want = el;\n if (this.onPage(el)) break;\n }\n const pseudo = pseudoSteps(target).filter(step => !elements.includes(step.el)).map(step => ({ action: step.action, target: describe(step.el) }));\n return [...pseudo, ...steps].slice(0, MAX_STEPS);\n }\n private changedFor(action: Action, want: Element): boolean {\n for (const node of action.changed) {\n if (!node.isConnected) continue;\n if (node === want || node.contains(want)) return true;\n // The checkbox hack: a :checked rule shows a later sibling.\n if (node instanceof HTMLInputElement && /^(checkbox|radio)$/.test(node.type)) {\n for (let sibling = node.nextElementSibling; sibling; sibling = sibling.nextElementSibling) if (sibling.contains(want)) return true;\n }\n }\n return false;\n }\n private opened(action: Action, el: Element, want: Element): boolean {\n if (this.changedFor(action, want)) return true;\n if (action.kind !== 'press') return false;\n const control = el instanceof HTMLLabelElement ? el.control : null;\n const popover = el.getAttribute('popovertarget');\n const hash = el.matches('a[href^=\"#\"]') ? el.getAttribute('href')! : '';\n return !!(popover && document.getElementById(popover)?.contains(want)) ||\n !!(hash.length > 1 && location.hash === hash && document.getElementById(hash.slice(1))?.contains(want)) ||\n !!(control instanceof HTMLInputElement && control.checked) ||\n (el.matches('summary') && !!(el.parentElement as HTMLDetailsElement | null)?.open && el.parentElement!.contains(want));\n }\n /** The trigger sits on the page itself, not inside a layer that another action opened. */\n private onPage(el: Element): boolean {\n if (el.parentElement?.closest('[role=menu],[role=dialog],[role=listbox],[popover],dialog')) return false;\n return !this.actions.some(action => action.el !== el && !action.el.contains(el) &&\n Array.from(action.changed).some(node => node.isConnected && node !== document.body && node !== document.documentElement && node.contains(el)));\n }\n}\n\n/** CSS-only menus: :hover and :focus-within rules that show the element's layer. No event records these. */\nfunction pseudoSteps(target: Element): { action: 'hover' | 'focus'; el: Element }[] {\n const rules: CSSStyleRule[] = [];\n const walk = (list: CSSRuleList) => {\n for (const rule of Array.from(list)) {\n if (rule instanceof CSSStyleRule) { if (/:(hover|focus-within)\\b/.test(rule.selectorText) && Array.from(rule.style).some(p => VISUAL.test(p))) rules.push(rule); }\n else if ('cssRules' in rule) walk((rule as CSSGroupingRule).cssRules);\n }\n };\n for (const sheet of Array.from(document.styleSheets)) { try { walk(sheet.cssRules); } catch { /* A cross-origin sheet cannot be read. */ } }\n if (!rules.length) return [];\n const steps: { action: 'hover' | 'focus'; el: Element }[] = [];\n for (const kind of ['hover', 'focus-within'] as const) {\n for (const el of Array.from(document.querySelectorAll(`:${kind}`))) {\n if (el === document.documentElement || el === document.body || target.contains(el)) continue;\n const shows = rules.some(rule => rule.selectorText.split(',').some(selector => {\n const at = selector.indexOf(`:${kind}`);\n // The rule must reach another element (`li:hover > .sub`), not style the hovered element itself.\n if (at < 0 || !/^\\s*[\\s>~+]/.test(selector.slice(at + kind.length + 1)) || !selector.slice(at + kind.length + 1).trim()) return false;\n try {\n return el.matches(selector.slice(0, at).trim() || '*') && Array.from(document.querySelectorAll(selector.split(`:${kind}`).join(''))).some(shown =>\n shown !== el && (el.contains(shown) || shown.parentElement === el.parentElement) && shown.contains(target));\n } catch { return false; }\n }));\n if (shows) steps.push({ action: kind === 'hover' ? 'hover' : 'focus', el });\n }\n }\n return steps.sort((a, b) => a.el.contains(b.el) ? -1 : b.el.contains(a.el) ? 1 : 0);\n}\n\n// ---------- replay ----------\n\nconst frame = () => new Promise<void>(done => requestAnimationFrame(() => done()));\nasync function waitFor(check: () => boolean, ms: number): Promise<boolean> {\n const end = performance.now() + ms;\n while (performance.now() < end) { if (check()) return true; await frame(); }\n return check();\n}\nfunction pointer(el: Element, type: string): void {\n const rect = el.getBoundingClientRect();\n const init = { bubbles: true, cancelable: true, composed: true, view: window, button: 0, buttons: type.endsWith('down') ? 1 : 0,\n clientX: rect.left + rect.width / 2, clientY: rect.top + rect.height / 2 };\n el.dispatchEvent(type.startsWith('pointer')\n ? new PointerEvent(type, { ...init, pointerId: 1, pointerType: 'mouse', isPrimary: true })\n : new MouseEvent(type, init));\n}\n/** Like a person: Radix opens on pointerdown, most others on click, some on mousedown. */\nfunction press(el: Element): void {\n for (const type of ['pointerover', 'pointerenter', 'mouseover', 'mouseenter', 'pointermove', 'mousemove', 'pointerdown', 'mousedown']) pointer(el, type);\n (el as HTMLElement).focus?.({ preventScroll: true });\n for (const type of ['pointerup', 'mouseup']) pointer(el, type);\n (el as HTMLElement).click?.();\n}\nfunction key(el: Element, name: string): void {\n (el as HTMLElement).focus?.({ preventScroll: true });\n for (const type of ['keydown', 'keyup']) el.dispatchEvent(new KeyboardEvent(type, { key: name, code: name === ' ' ? 'Space' : name, bubbles: true, cancelable: true, composed: true }));\n}\nconst looksOpen = (el: Element) => el.matches('[aria-expanded=true],[data-state=open],[role=tab][aria-selected=true]') ||\n (el.matches('summary') && !!(el.parentElement as HTMLDetailsElement | null)?.open) || (el instanceof HTMLInputElement && el.checked);\n\n/** A script cannot set :hover. Copy the page's :hover (or :focus-within) rules to an attribute and set that attribute. */\nclass PseudoStates {\n private sheet: CSSStyleSheet | null = null;\n private marked: [Element, string][] = [];\n set(el: Element, kind: 'hover' | 'focus'): void {\n const attr = `data-overplay-${kind}`;\n const pattern = kind === 'hover' ? /:hover\\b/g : /:focus-within\\b/g;\n if (!this.sheet) {\n try { this.sheet = new CSSStyleSheet(); document.adoptedStyleSheets = [...document.adoptedStyleSheets, this.sheet]; } catch { return; }\n }\n const copy = (list: CSSRuleList, wrap: (rule: string) => string) => {\n for (const rule of Array.from(list)) {\n if (rule instanceof CSSStyleRule && rule.selectorText.match(pattern)) {\n try { this.sheet!.insertRule(wrap(`${rule.selectorText.replace(pattern, `[${attr}]`)}{${rule.style.cssText}}`), this.sheet!.cssRules.length); } catch { /* Unsupported selector. */ }\n } else if (rule instanceof CSSMediaRule) copy(rule.cssRules, text => wrap(`@media ${rule.media.mediaText}{${text}}`));\n }\n };\n if (!this.marked.some(([, a]) => a === attr)) for (const sheet of Array.from(document.styleSheets)) { try { copy(sheet.cssRules, text => text); } catch { /* Cross-origin sheet. */ } }\n el.setAttribute(attr, ''); this.marked.push([el, attr]);\n }\n clear(): void {\n for (const [el, attr] of this.marked) el.removeAttribute(attr);\n this.marked = [];\n if (this.sheet) { document.adoptedStyleSheets = document.adoptedStyleSheets.filter(sheet => sheet !== this.sheet); this.sheet = null; }\n }\n}\nconst pseudo = new PseudoStates();\n/** Ends CSS hover and focus states that replay() set. Call when the note closes. */\nexport function clearReveal(): void { pseudo.clear(); }\n\nexport type RevealResult = { shown: boolean; failed?: RevealStep };\n/**\n * Repeats the steps until `target()` is visible. Each step waits for the next trigger to show. A press falls back to the\n * keyboard. A hidden trigger is not pressed (for example a phone menu at desktop width).\n */\nexport async function replay(steps: RevealStep[], target: () => Element | null): Promise<RevealResult> {\n const goal = () => isVisible(target());\n if (goal()) return { shown: true };\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i];\n const el = findTarget(step.target);\n // A risky step is not named either: the note must not tell people to press it.\n if (step.action === 'press' && el && risky(el)) return { shown: false };\n if (!el || (step.action !== 'focus' && !isVisible(el))) return { shown: false, failed: step };\n const next = steps[i + 1] ? () => isVisible(findTarget(steps[i + 1].target)) : goal;\n if (step.action === 'hover') {\n for (const type of ['pointerover', 'pointerenter', 'mouseover', 'mouseenter', 'pointermove', 'mousemove']) pointer(el, type);\n if (!await waitFor(next, 500)) {\n pseudo.set(el, 'hover');\n if (!await waitFor(next, 300)) { press(el); if (!await waitFor(next, 500)) key(el, 'ArrowRight'); }\n }\n } else if (step.action === 'focus') {\n (el as HTMLElement).focus?.({ preventScroll: true });\n if (!await waitFor(next, 200)) pseudo.set(el, 'focus');\n } else if (!looksOpen(el)) {\n const changed = () => next() || looksOpen(el);\n press(el);\n if (!await waitFor(changed, 900)) {\n let worked = false;\n for (const name of KEYS) { key(el, name); if (await waitFor(changed, 400)) { worked = true; break; } }\n if (!worked) return { shown: false, failed: step };\n }\n }\n await waitFor(next, 1200);\n }\n return { shown: await waitFor(goal, 1500) };\n}\n","import type { Comment, CommentPosition, ElementInfo } from './types';\nimport { isVisible } from './reveal';\n\n// Controls and form fields are what people mean when they click inside them.\nconst CONTROL = 'a[href],button,label,summary,select,textarea,input,[role=button],[role=link],[role=tab],[role=menuitem],[role=checkbox],[role=switch],[role=option]';\n// Replaced elements are inline, but they are a component on their own.\nconst REPLACED = new Set(['IMG', 'svg', 'VIDEO', 'CANVAS', 'IFRAME', 'PICTURE', 'INPUT', 'SELECT', 'TEXTAREA', 'BUTTON']);\n\n/**\n * The component a person points at: an explicit component key, else the control, image or text block under the pointer.\n * Ancestor IDs are not used here. Layout roots such as #root, #__next or #main have IDs and would take every click.\n * componentSelector still uses the nearest unique ID to make a stable path.\n */\nconst area = (el: Element) => { const r = el.getBoundingClientRect(); return r.width * r.height; };\nexport function componentTarget(target: Element, container?: HTMLElement | null): Element | null {\n const permitted = (el: Element) => el !== document.body && el !== document.documentElement &&\n (!container || container.contains(el)) && !el.closest('[data-overplay]');\n if (target.closest('[data-overplay]')) return null;\n const keyed = target.closest('[data-overplay-anchor]');\n const key = keyed?.getAttribute('data-overplay-anchor');\n // Ambiguous keys must not silently attach a comment to the wrong component.\n const anchor = keyed && key && permitted(keyed) && resolveComponent(`[data-overplay-anchor=\"${CSS.escape(key)}\"]`, container) === keyed ? keyed : null;\n let el = target;\n // Icon parts (path, circle, g) are not useful alone. Use the whole drawing.\n if (el instanceof SVGElement) for (let svg = el.closest('svg'); svg; svg = svg.parentElement?.closest('svg') ?? null) el = svg;\n const control = el.closest(CONTROL);\n if (control && permitted(control)) el = control;\n else {\n // Inline text (em, span, strong) belongs to its paragraph, heading or cell.\n while (!REPLACED.has(el.tagName) && el.parentElement && permitted(el.parentElement) &&\n /^(inline|contents)$/.test(getComputedStyle(el).display)) el = el.parentElement;\n }\n // A named component wins. A large anchored region, such as a whole dashboard or app frame that covers more than a\n // quarter of the screen, gives way to the row, cell or control inside it, like a browser inspector.\n if (anchor && (el === anchor || !anchor.contains(el) || !permitted(el) || area(anchor) <= innerWidth * innerHeight / 4)) return anchor;\n if (permitted(el)) return el;\n // Empty page space still takes a note. It attaches to the container, or to the page itself.\n if (container) return container;\n return document.body.getClientRects().length && document.body.getBoundingClientRect().height ? document.body : document.documentElement;\n}\n\n/**\n * IDs that frameworks make at run time, such as React useId (\":r1:\", \"«r1»\", \"_r_3p_\"), Radix (\"radix-_r_3p_\"),\n * Headless UI, React Aria and Ember. They change between page loads, so a saved selector must not start from them.\n */\nconst GENERATED_ID = /^(radix-|headlessui-|react-aria\\d*-|mui-\\d|ember\\d|_r_)|[:«»]|^[a-f0-9]{8}-[a-f0-9]{4}-/i;\nexport const generatedId = (id: string) => GENERATED_ID.test(id);\n\nexport function componentSelector(target: Element, container?: HTMLElement | null): string {\n const key = target.getAttribute('data-overplay-anchor');\n if (key && resolveComponent(`[data-overplay-anchor=\"${CSS.escape(key)}\"]`, container) === target) {\n return `[data-overplay-anchor=\"${CSS.escape(key)}\"]`;\n }\n if (target === document.body) return 'body';\n if (target === document.documentElement) return 'html';\n const parts: string[] = [];\n for (let el: Element | null = target; el && el !== document.body; el = el.parentElement) {\n if (el.id && !generatedId(el.id) && document.querySelectorAll(`#${CSS.escape(el.id)}`).length === 1) {\n parts.unshift(`#${CSS.escape(el.id)}`); break;\n }\n // A unique component key above the target keeps the path short and stable.\n const key = el !== target ? el.getAttribute('data-overplay-anchor') : null;\n if (key && document.querySelectorAll(`[data-overplay-anchor=\"${CSS.escape(key)}\"]`).length === 1) {\n parts.unshift(`[data-overplay-anchor=\"${CSS.escape(key)}\"]`); break;\n }\n const siblings = el.parentElement ? Array.from(el.parentElement.children).filter(sibling => sibling.tagName === el!.tagName) : [];\n parts.unshift(`${el.tagName.toLowerCase()}:nth-of-type(${siblings.indexOf(el) + 1})`);\n }\n return parts.join(' > ');\n}\n\nexport function resolveComponent(selector: string, container?: HTMLElement | null): Element | null {\n try {\n const matches = Array.from(document.querySelectorAll(selector)).filter(el => !container || container.contains(el));\n if (matches.length === 1) return matches[0];\n // Responsive representations may share a component key if exactly one is rendered.\n const visible = matches.filter(el => {\n const rect = el.getBoundingClientRect();\n return el.getClientRects().length && rect.width && rect.height && getComputedStyle(el).visibility === 'visible';\n });\n return visible.length === 1 ? visible[0] : null;\n } catch { return null; }\n}\n\nexport function componentPosition(comment: Pick<Comment, 'selector' | 'anchor' | 'x' | 'y'>, container?: HTMLElement | null): CommentPosition | null {\n if (!comment.selector) return { x: comment.x - scrollX, y: comment.y - scrollY }; // Legacy coordinate-only notes.\n const target = resolveComponent(comment.selector, container);\n if (!target || !target.getClientRects().length) return null;\n const rect = target.getBoundingClientRect();\n if (!rect.width || !rect.height || getComputedStyle(target).visibility !== 'visible') return null;\n const anchor = comment.anchor ?? { x: .5, y: .5 };\n const point = { x: rect.left + rect.width * anchor.x, y: rect.top + rect.height * anchor.y };\n // A pin must not float over unrelated content when its component scrolls behind a clip.\n for (let parent = target.parentElement; parent && parent !== document.body && parent !== document.documentElement; parent = parent.parentElement) {\n const style = getComputedStyle(parent);\n const bounds = parent.getBoundingClientRect();\n const left = bounds.left + parent.clientLeft, top = bounds.top + parent.clientTop;\n if (/(auto|scroll|hidden|clip)/.test(style.overflowX) && (point.x < left || point.x > left + parent.clientWidth)) return null;\n if (/(auto|scroll|hidden|clip)/.test(style.overflowY) && (point.y < top || point.y > top + parent.clientHeight)) return null;\n }\n return point;\n}\n\n/**\n * Opens what hides a component: closed <details>, a popover, a collapsed menu or accordion (a button with\n * aria-controls and aria-expanded=\"false\"), or an inactive tab. Outer parts open first. Returns true when it changed something.\n */\nexport function revealElement(target: Element): boolean {\n const chain: HTMLElement[] = [];\n for (let el = target instanceof HTMLElement ? target : target.parentElement; el && el !== document.body; el = el.parentElement) chain.unshift(el);\n let changed = false;\n for (const el of chain) {\n if (el instanceof HTMLDetailsElement && !el.open) { el.open = true; changed = true; }\n if (el.hasAttribute('popover') && !el.matches(':popover-open')) {\n try { el.showPopover(); changed = true; } catch { /* Not supported, or not allowed now. */ }\n }\n if (!el.id || !(el.hidden || getComputedStyle(el).display === 'none')) continue;\n const id = CSS.escape(el.id);\n const toggle = document.querySelector<HTMLElement>(`[aria-controls~=\"${id}\"][aria-expanded=\"false\"]`) ??\n (el.getAttribute('role') === 'tabpanel' ? document.querySelector<HTMLElement>(`[role=tab][aria-controls~=\"${id}\"][aria-selected=\"false\"]`) : null);\n if (toggle) { toggle.click(); changed = true; }\n }\n return changed;\n}\n\n/**\n * \"shown\": the component is rendered (it can still be scrolled out of view). \"hidden\": it is on the page but not\n * rendered, for example in a closed menu. \"removed\": nothing on the page matches it now.\n */\nexport type ElementState = 'shown' | 'hidden' | 'removed';\nexport function elementState(comment: Pick<Comment, 'selector'>, container?: HTMLElement | null): ElementState {\n if (!comment.selector) return 'shown';\n let found = false;\n try { found = Array.from(document.querySelectorAll(comment.selector)).some(el => !container || container.contains(el)); } catch { /* Invalid selector. */ }\n if (!found) return 'removed';\n // Closed <details>, opacity 0, a collapsed parent and a drawer moved off the screen are hidden too. See isVisible.\n return isVisible(resolveComponent(comment.selector, container)) ? 'shown' : 'hidden';\n}\n/** The component is gone or not rendered at all, as opposed to scrolled out of view or clipped by a scroll box. */\nexport function isDetached(comment: Pick<Comment, 'selector'>, container?: HTMLElement | null): boolean {\n return elementState(comment, container) !== 'shown';\n}\n\nconst KINDS: [string, string][] = [\n ['input[type=checkbox],[role=checkbox]', 'Checkbox'], ['input[type=radio],[role=radio]', 'Option'], ['[role=switch]', 'Switch'],\n ['button,input[type=button],input[type=submit],[role=button]', 'Button'], ['a[href],[role=link]', 'Link'], ['[role=tab]', 'Tab'],\n ['[role=menuitem]', 'Menu item'], ['[role=option],option', 'Option'], ['select', 'Menu'], ['input,textarea', 'Field'],\n ['img,picture,[role=img]', 'Image'], ['svg', 'Icon'], ['video', 'Video'], ['canvas', 'Canvas'], ['iframe', 'Frame'],\n ['h1,h2,h3,h4,h5,h6,[role=heading]', 'Heading'], ['label', 'Label'], ['li', 'List item'], ['tr', 'Row'], ['td,th', 'Cell'],\n ['table', 'Table'], ['nav', 'Navigation'], ['form', 'Form'], ['p', 'Text'], ['summary', 'Button'],\n];\nconst clean = (text: string | null | undefined, max = 48) => {\n const value = (text ?? '').replace(/\\s+/g, ' ').trim();\n return value.length > max ? `${value.slice(0, max - 1).trimEnd()}…` : value;\n};\nconst byIds = (ids: string | null) => clean(ids?.split(/\\s+/).map(id => document.getElementById(id)?.textContent ?? '').join(' '));\n/** The accessible name, or the visible text when there is none. */\nfunction nameOf(el: Element): string {\n const field = el as HTMLInputElement;\n const label = el.id ? document.querySelector(`label[for=\"${CSS.escape(el.id)}\"]`) : null;\n return clean(el.getAttribute('aria-label')) || byIds(el.getAttribute('aria-labelledby')) || clean(el.getAttribute('alt')) ||\n clean(label?.textContent) || clean(el.closest('label')?.textContent) || clean(field.placeholder) || clean(el.getAttribute('title')) ||\n clean(el.querySelector('title')?.textContent) || clean((el as HTMLElement).innerText ?? el.textContent);\n}\nconst words = (key: string) => clean(key.replace(/[-_:./]+/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2').replace(/^./, c => c.toUpperCase()));\n/**\n * Names a component for people who did not make the note: its kind and name, and the closed menu, tab, dialog or\n * section it is in. For example { label: 'Checkbox “Peanuts”', place: 'Filters' }.\n */\nexport function describeElement(el: Element): ElementInfo {\n const key = el.getAttribute('data-overplay-anchor');\n const kind = key ? words(key) : KINDS.find(([selector]) => el.matches(selector))?.[1] ?? (el === document.body || el === document.documentElement ? 'Page' : 'Element');\n const name = key || el === document.body || el === document.documentElement ? '' : nameOf(el);\n const info: ElementInfo = { label: name && name !== kind ? `${kind} “${name}”` : kind };\n for (let parent = el.parentElement; parent && parent !== document.body; parent = parent.parentElement) {\n const id = parent.id ? CSS.escape(parent.id) : '';\n const toggle = id ? document.querySelector(`[aria-controls~=\"${id}\"]`) : null;\n const place = toggle ? nameOf(toggle)\n : parent instanceof HTMLDetailsElement ? clean(parent.querySelector('summary')?.textContent)\n : parent instanceof HTMLFieldSetElement ? clean(parent.querySelector('legend')?.textContent)\n : parent.hasAttribute('data-overplay-anchor') ? words(parent.getAttribute('data-overplay-anchor')!)\n : parent.matches('[role=dialog],[role=menu],[role=listbox],[role=tabpanel],dialog,nav,section,aside,form,[popover]')\n ? clean(parent.getAttribute('aria-label')) || byIds(parent.getAttribute('aria-labelledby')) : '';\n if (place && place !== name) { info.place = place; break; }\n }\n return info;\n}\n","import type { Comment, ElementInfo, Reply } from './types';\n\n/**\n * Search and filters for the notes list. Pure functions, so the widget and the tests share one set of rules.\n * Search ignores case and accents (\"cafe\" finds \"Café\"). Every word must appear somewhere in the note: its text,\n * its author, a reply or a reply's author, or the name of its element.\n */\nexport type StatusFilter = 'open' | 'resolved' | 'all';\nexport interface NoteFilters {\n status: StatusFilter;\n query: string;\n /** Only notes the current person started. */\n mine: boolean;\n /** An author key from authorKey(), or '' for anyone. */\n author: string;\n}\nexport const DEFAULT_FILTERS: Readonly<NoteFilters> = Object.freeze({ status: 'open', query: '', mine: false, author: '' });\nexport interface FilterContext {\n /** The current person's ID. Notes with this authorId are \"mine\". */\n userId: string;\n /** The element's saved name. Older notes have none saved; the widget can name them from the page. */\n elementOf?: (comment: Comment) => ElementInfo | undefined;\n /** Also match the page title and path, for the \"All Pages\" view. */\n includePage?: boolean;\n}\n/** Where a note matched, so the list can show a reply or element that holds the words. */\nexport interface NoteMatch { reply?: Reply; element?: string }\nexport interface Author { key: string; name: string; count: number }\nexport interface FilterCounts { open: number; resolved: number; all: number; mine: number; authors: Author[] }\n\nconst MAX_QUERY = 200, MAX_WORDS = 8;\n/** One character folded for search: lower case, accents removed. Can be empty (a lone combining mark). */\nfunction foldChar(char: string): string {\n return char.normalize('NFKD').replace(/\\p{M}/gu, '').toLowerCase();\n}\n/** The folded text, and for each folded character the index of the original character it came from. */\nexport function fold(text: string): { folded: string; map: number[] } {\n let folded = ''; const map: number[] = [];\n for (let i = 0; i < text.length;) {\n const code = text.codePointAt(i)!, char = String.fromCodePoint(code), part = foldChar(char);\n for (let j = 0; j < part.length; j++) map.push(i);\n folded += part; i += char.length;\n }\n map.push(text.length);\n return { folded, map };\n}\n/** The search words: folded, without duplicates, at most 8. */\nexport function parseQuery(query: string): string[] {\n const words = fold(query.slice(0, MAX_QUERY)).folded.split(/\\s+/).filter(Boolean);\n return [...new Set(words)].slice(0, MAX_WORDS);\n}\nconst includesAll = (text: string, words: string[]) => { const folded = fold(text).folded; return words.filter(word => folded.includes(word)); };\n/**\n * The parts of `text` to highlight for these words, as sorted [start, end) ranges in the original text.\n * Overlapping and touching ranges are merged.\n */\nexport function highlightRanges(text: string, words: string[]): [number, number][] {\n if (!words.length || !text) return [];\n const { folded, map } = fold(text), ranges: [number, number][] = [];\n for (const word of words) {\n for (let at = folded.indexOf(word); at !== -1; at = folded.indexOf(word, at + word.length)) {\n const start = map[at], last = map[at + word.length - 1];\n // The end is after the last original character that the match covers (it may be two UTF-16 units).\n const end = map.slice(at + word.length).find(index => index > last) ?? text.length;\n ranges.push([start, end]);\n }\n }\n ranges.sort((a, b) => a[0] - b[0] || a[1] - b[1]);\n const merged: [number, number][] = [];\n for (const range of ranges) {\n const previous = merged[merged.length - 1];\n if (previous && range[0] <= previous[1]) previous[1] = Math.max(previous[1], range[1]);\n else merged.push([...range]);\n }\n return merged;\n}\n/** A short part of `text` around its first match, with \"…\" where it was cut. */\nexport function excerpt(text: string, words: string[], size = 90): string {\n const clean = text.replace(/\\s+/g, ' ').trim();\n if (clean.length <= size) return clean;\n const first = highlightRanges(clean, words)[0]?.[0] ?? 0;\n const start = Math.max(0, Math.min(first - Math.floor(size / 3), clean.length - size));\n return `${start > 0 ? '…' : ''}${clean.slice(start, start + size).trim()}${start + size < clean.length ? '…' : ''}`;\n}\nexport function elementName(info?: ElementInfo): string {\n return info ? info.place ? `${info.label} in ${info.place}` : info.label : '';\n}\n/**\n * Whether the note holds every search word, and where. Null when it does not match.\n * An empty search matches every note.\n */\nexport function matchNote(comment: Comment, words: string[], context: Pick<FilterContext, 'elementOf' | 'includePage'> = {}): NoteMatch | null {\n if (!words.length) return {};\n const element = elementName(context.elementOf ? context.elementOf(comment) : comment.element);\n const own = [comment.text, comment.author, context.includePage ? `${comment.pageTitle ?? ''} ${comment.pageUrl}` : ''].join('\\n');\n const found = new Set(includesAll(own, words));\n const match: NoteMatch = {};\n if (found.size < words.length) {\n for (const reply of comment.replies) {\n const hits = includesAll(`${reply.text}\\n${reply.author}`, words);\n if (hits.some(word => !found.has(word))) { match.reply ??= reply; hits.forEach(word => found.add(word)); }\n }\n }\n if (found.size < words.length && element) {\n const hits = includesAll(element, words);\n if (hits.some(word => !found.has(word))) { match.element = element; hits.forEach(word => found.add(word)); }\n }\n return found.size === words.length ? match : null;\n}\n/** Groups authors by account. Notes without an account (older local notes) group by name. */\nexport function authorKey(note: Pick<Comment, 'author' | 'authorId'>): string {\n return note.authorId ? `id:${note.authorId}` : `name:${note.author.trim().toLowerCase()}`;\n}\nexport function isMine(note: Pick<Comment, 'authorId'>, userId: string): boolean {\n return !!note.authorId && note.authorId === userId;\n}\nfunction statusMatches(comment: Comment, status: StatusFilter): boolean {\n return status === 'all' || (status === 'resolved' ? comment.resolved : !comment.resolved);\n}\n/** The notes that pass every filter, in the given order. */\nexport function filterNotes(comments: Comment[], filters: NoteFilters, context: FilterContext): Comment[] {\n const words = parseQuery(filters.query);\n return comments.filter(c => statusMatches(c, filters.status) && (!filters.mine || isMine(c, context.userId)) &&\n (!filters.author || authorKey(c) === filters.author) && !!matchNote(c, words, context));\n}\n/**\n * Counts for each filter choice. Each count applies the other filters, so it says how many notes that choice shows.\n * Authors are every author in `comments`, by name, even when the other filters leave them none.\n */\nexport function filterCounts(comments: Comment[], filters: NoteFilters, context: FilterContext): FilterCounts {\n const words = parseQuery(filters.query);\n const searched = comments.filter(c => !!matchNote(c, words, context));\n const byPerson = (c: Comment) => (!filters.mine || isMine(c, context.userId)) && (!filters.author || authorKey(c) === filters.author);\n const people = searched.filter(byPerson);\n const inStatus = searched.filter(c => statusMatches(c, filters.status));\n const authors = new Map<string, Author>();\n for (const c of comments) {\n const key = authorKey(c), entry = authors.get(key) ?? { key, name: c.author, count: 0 };\n // The newest name wins: people rename themselves.\n entry.name = c.author; authors.set(key, entry);\n }\n // A person choice counts with the status and search, and without the other person choice (they replace each other).\n for (const c of inStatus) { const entry = authors.get(authorKey(c)); if (entry) entry.count++; }\n return {\n open: people.filter(c => !c.resolved).length,\n resolved: people.filter(c => c.resolved).length,\n all: people.length,\n mine: inStatus.filter(c => isMine(c, context.userId)).length,\n authors: [...authors.values()].sort((a, b) => a.name.localeCompare(b.name) || a.key.localeCompare(b.key)),\n };\n}\n/** Search, Mine or an author is set. The status tabs are always in view, so they do not count. */\nexport function filtersActive(filters: NoteFilters): boolean {\n return !!filters.query.trim() || filters.mine || !!filters.author;\n}\n/** Clear Filters: no search, anyone, and the Open tab, or All when nothing is open. */\nexport function clearFilters(comments: Comment[]): NoteFilters {\n return { ...DEFAULT_FILTERS, status: comments.some(c => !c.resolved) || !comments.length ? 'open' : 'all' };\n}\n/** Saved filters from session storage. Anything unknown falls back to the defaults. */\nexport function readFilters(value: unknown): NoteFilters {\n const v = value && typeof value === 'object' ? value as Record<string, unknown> : {};\n return {\n status: v.status === 'resolved' || v.status === 'all' ? v.status : 'open',\n query: typeof v.query === 'string' ? v.query.slice(0, MAX_QUERY) : '',\n mine: v.mine === true,\n author: typeof v.author === 'string' ? v.author.slice(0, 300) : '',\n };\n}\n","import type { OverplayConfig } from '../config';\nimport type { Comment, CommentPosition, CommentUser, ElementInfo, Reply } from '../core/types';\nimport type { StorageAdapter } from '../storage/StorageAdapter';\nimport { HostedAdapter } from '../storage/HostedAdapter';\nimport { LocalStorageAdapter } from '../storage/LocalStorageAdapter';\nimport { copyComments, defaultPageId, normalizeComments, safePageUrl, samePage, withoutCommentLink } from '../core/data';\nimport { matchesShortcut, parseShortcut, type Shortcut } from '../core/shortcut';\nimport { guestIdentity, newId, saveGuest, validateUser } from '../core/identity';\nimport { newActivity, sameComments, type Activity } from '../core/activity';\nimport { UPDATE_COMMAND, VERSION, developmentHost, isNewer, latestVersion } from '../core/version';\nimport { avatar, button, element, icon, relativeTime } from './dom';\nimport { PIN_COLORS, initials, readSettings, writeSettings, type Settings } from '../core/settings';\nimport { styles } from './styles';\nimport { componentTarget, componentSelector, componentPosition, describeElement, elementState, isDetached, resolveComponent, revealElement, type ElementState } from '../core/anchors';\nimport { RevealRecorder, clearReveal, findTarget, replay, type RevealResult } from '../core/reveal';\nimport { DEFAULT_FILTERS, clearFilters, excerpt, filterCounts, filterNotes, filtersActive, highlightRanges, matchNote, parseQuery, readFilters, type FilterContext, type NoteFilters } from '../core/filter';\n\nexport interface OverplayAPI {\n /** Initial storage load. Errors are shown in the UI and sent to onError. */\n ready: Promise<void>;\n destroy(): void;\n show(): void;\n hide(): void;\n startComment(position?: CommentPosition): void;\n getAllComments(): Comment[];\n getUser(): CommentUser;\n /** Call on sign-in, sign-out, or account changes. Omit to restore the saved guest. */\n setUser(user?: CommentUser): void;\n signIn(): Promise<void>;\n signOut(): Promise<void>;\n refresh(): Promise<void>;\n navigateToComment(id: string): void;\n /** Changes the site's default theme, for example when the page switches to dark mode. A theme the person chose in Settings still wins. */\n setTheme(theme: 'light' | 'dark' | 'system'): void;\n}\n\ntype Scope = 'page' | 'all';\ntype Spot = { x: number; y: number };\nconst THEMES = ['light', 'dark', 'system'] as const;\nconst LAUNCHER = 52, EDGE = 12, SIDEBAR = 400, PIN_HEIGHT = 36, PIN_HALF = 16;\nconst UPDATE_DISMISSED = 'overplay:update-dismissed';\nconst clamp = (value: number, min: number, max: number) => Math.max(min, Math.min(Math.max(min, max), value));\n/** The fields our own handlers read from a press, to copy it inside the shadow root. */\nfunction eventInit(event: Event): PointerEventInit {\n const e = event as PointerEvent;\n return { view: window, clientX: e.clientX, clientY: e.clientY, screenX: e.screenX, screenY: e.screenY, button: e.button, buttons: e.buttons,\n ctrlKey: e.ctrlKey, shiftKey: e.shiftKey, altKey: e.altKey, metaKey: e.metaKey, pointerId: e.pointerId, pointerType: e.pointerType,\n isPrimary: e.isPrimary, width: e.width, height: e.height, pressure: e.pressure };\n}\n/** Browsers without popovers or :modal do not know these selectors. */\nfunction matchAll(selector: string): Element[] {\n try { return Array.from(document.querySelectorAll(selector)); } catch { return []; }\n}\n/** The saved launcher place, as the center in viewport fractions. */\nfunction readSpot(key: string): Spot | null {\n try {\n const value = JSON.parse(localStorage.getItem(key) || 'null');\n return value && Number.isFinite(value.x) && Number.isFinite(value.y) ? { x: clamp(value.x, 0, 1), y: clamp(value.y, 0, 1) } : null;\n } catch { return null; }\n}\n/** A short label for a page ID, such as \"/pricing\". */\nfunction pageLabel(pageUrl: string): string {\n try { const url = new URL(pageUrl, location.href); return `${url.pathname}${url.search}${url.hash}`; }\n catch { return pageUrl; }\n}\n/**\n * A name for the page, for the \"All comments\" groups. Single-page apps often keep one document title, such as the\n * app name, on every route. Then the main heading names the page better, so it comes first when the title is that generic.\n */\nfunction pageTitle(): string | undefined {\n const clean = (text?: string | null) => (text ?? '').replace(/\\s+/g, ' ').trim();\n const title = clean(document.title);\n const heading = Array.from(document.querySelectorAll('main h1, [role=main] h1, h1'))\n .find(h => !h.closest('[data-overplay]') && h.getClientRects().length);\n const name = clean(heading?.textContent).slice(0, 120);\n // \"Pricing — Acme\" already names the page. \"Acme\" or \"Vite + React\" on every route does not.\n const generic = !title || title.toLowerCase() === location.hostname.toLowerCase() || !/[-–—|·:]/.test(title) && !!name && !title.includes(name);\n return (generic && name ? name : title || name).slice(0, 300) || undefined;\n}\n/** Puts the text in `target`, with the search words in <mark>. One letter would mark half the text, so it is not marked. */\nfunction marked<T extends HTMLElement>(target: T, text: string, words: string[]): T {\n let at = 0;\n for (const [start, end] of highlightRanges(text, words.filter(word => word.length > 1))) {\n if (start > at) target.append(document.createTextNode(text.slice(at, start)));\n target.append(element('mark', 'hit', text.slice(start, end))); at = end;\n }\n target.append(document.createTextNode(text.slice(at)));\n return target;\n}\ntype Draft = { id: string; timestamp: Date; position: CommentPosition; selector?: string; anchor?: Comment['anchor']; element?: ElementInfo; pageUrl: string };\n\nexport class Overlay implements OverplayAPI {\n readonly ready: Promise<void>;\n private config: OverplayConfig;\n private storage: StorageAdapter;\n private host = element('div');\n private shadow: ShadowRoot;\n private surface = element('div');\n private pins = element('div', 'pins');\n /** While placing: the component under the pointer, outlined before the click. */\n private pickTarget: Element | null = null;\n private live = element('div', 'sr-only');\n private toasts = element('div', 'toasts');\n private toastTimers = new Set<ReturnType<typeof setTimeout>>();\n private seen = new Set<string>();\n private seenKey = '';\n private detailKey = '';\n private events = new AbortController();\n private resizeObserver: ResizeObserver;\n private mutationObserver: MutationObserver;\n private anchorObserver: ResizeObserver;\n private observedAnchors = new Set<Element>();\n private unsubscribe?: () => void;\n private routeTimer: ReturnType<typeof setInterval>;\n private frame = 0;\n private motionFrame = 0;\n private destroyed = false;\n private visible = false;\n private placing = false;\n /** A pin being dragged, in viewport coordinates. It stays set until the move is saved, so the pin does not jump back. */\n private pinDrag: { id: string; x: number; y: number } | null = null;\n private suppressPinClick = false;\n private loading = true;\n /** The current page and account have loaded once. Later loads keep the list on screen. */\n private loaded = false;\n private loadFailed = false;\n private saving = false;\n private error = '';\n private comments: Comment[] = [];\n private activeId: string | null = null;\n private draft: Draft | null = null;\n private text = '';\n private replyText = '';\n private replyId = newId();\n /** Search, status, Mine and author for the list and the pins. Kept for this browser tab (session storage). */\n private filters: NoteFilters = { ...DEFAULT_FILTERS };\n private scope: Scope = 'page';\n private filterKey: string;\n private searchTimer?: ReturnType<typeof setTimeout>;\n private launcherKey: string;\n private openKey: string;\n private launcherSpot: Spot | null;\n private dragging = false;\n private suppressClick = false;\n private highlightId: string | null = null;\n private hoverId: string | null = null;\n private highlightTimer?: ReturnType<typeof setTimeout>;\n private sidebarOpen = false;\n /** Show the open comment in the sidebar instead of next to its pin. The person's choice is saved. */\n private docked = false;\n private dockKey: string;\n private project: string;\n /** The person's display choices for this project, read again when the account changes. */\n private settingsCache: { key: string; value: Settings } | null = null;\n /** A newer npm version, found when the sidebar first opens. See checkForUpdate(). */\n private update: string | null = null;\n private updateChecked = false;\n /** The page margin we replaced to make room for the sidebar, restored when it closes. */\n private pushed: { property: string; value: string; priority: string } | null = null;\n /** Records how menus were opened, so a note in a menu can open it again. See src/core/reveal.ts. */\n private recorder = new RevealRecorder(el => el === this.host || el.getRootNode() === this.shadow, () => this.placing || !!this.pinDrag);\n /** The note whose menu Show Element opened, and the result. The menu stays open while that note is open. */\n private revealed: { id: string; result: RevealResult } | null = null;\n /** Show Element is pressing the page's menu buttons. A label's click on its checkbox counts as trusted, so we also check this. */\n private replaying = false;\n /** A view that fills the sidebar instead of the list: the guest name form or the settings. */\n private editing: 'identity' | 'settings' | null = null;\n private user: CommentUser;\n private managedUser: boolean;\n private identityKey: string;\n private persistentGuest: boolean;\n private pageId: string;\n private loadVersion = 0;\n private queuedSnapshot: Comment[] | null = null;\n private returnFocus: Element | null = null;\n private shortcut: Shortcut | null;\n private composing = false;\n private renderDeferred = false;\n\n constructor(config: OverplayConfig = {}) {\n this.config = { primaryColor: '#0068f9', position: 'bottom-right', keyboardShortcut: 'alt+shift+c', enableKeyboardShortcuts: true, ...config };\n if (!/^#[0-9a-f]{3}([0-9a-f]{3})?$/i.test(this.config.primaryColor ?? '')) {\n throw new Error('primaryColor must be a 3- or 6-digit hex color.');\n }\n if (this.config.theme !== undefined && !THEMES.includes(this.config.theme)) throw new Error('theme must be \"light\", \"dark\" or \"system\".');\n this.shortcut = parseShortcut(this.config.keyboardShortcut ?? '');\n if (this.config.enableKeyboardShortcuts && !this.shortcut) throw new Error('keyboardShortcut must be a key such as \"alt+shift+c\".');\n const project = config.projectId || location.hostname || 'default';\n this.identityKey = `overplay:${project}:user`;\n this.launcherKey = `overplay:${project}:launcher`;\n this.openKey = `overplay:${project}:open`;\n this.dockKey = `overplay:${project}:docked`;\n this.filterKey = `overplay:${project}:filters`;\n this.restoreFilters();\n this.project = project;\n try { this.docked = localStorage.getItem(this.dockKey) === '1'; } catch { /* Next to the pin by default. */ }\n this.launcherSpot = readSpot(this.launcherKey);\n const guest = guestIdentity(this.identityKey);\n this.user = config.user ? validateUser(config.user) : guest.user;\n this.persistentGuest = guest.persistent;\n this.managedUser = !!config.user;\n if (config.serverUrl && (!config.projectId || config.storage || config.user)) throw new Error('Hosted mode requires projectId and manages storage and user itself.');\n this.storage = config.serverUrl ? new HostedAdapter(config.serverUrl, project, () => this.currentPage(), user => this.hostedSession(user)) : config.storage ?? new LocalStorageAdapter(`overplay:${project}:comments`);\n if (config.serverUrl) { this.user = { id: 'signed-out', name: 'Sign in' }; this.managedUser = true; }\n this.pageId = this.currentPage();\n this.host.dataset.overplay = 'root';\n // Only our own host is styled. The one change to the page is the margin that makes room for the open sidebar (pushPage).\n this.host.style.cssText = 'all:initial;position:fixed;inset:0;pointer-events:none;z-index:2147483646;';\n this.shadow = this.host.attachShadow({ mode: 'open' });\n const style = element('style'); style.textContent = styles;\n if (config.nonce) style.nonce = config.nonce;\n this.host.style.setProperty('--cw-accent', this.config.primaryColor!);\n this.live.setAttribute('role', 'status'); this.live.setAttribute('aria-live', 'polite');\n this.toasts.setAttribute('role', 'status'); this.toasts.setAttribute('aria-live', 'polite');\n this.shadow.append(style, this.pins, this.surface, this.toasts, this.live);\n document.body.append(this.host);\n const options = { signal: this.events.signal };\n if (this.config.autoReveal !== false) this.recorder.start(this.events.signal);\n // Presses and focus in the widget are not presses outside the page's open menu (Bootstrap, Radix): they stop at our host.\n for (const type of ['pointerdown', 'mousedown', 'pointerup', 'mouseup', 'click', 'touchstart', 'touchend', 'focusin', 'focusout']) {\n this.host.addEventListener(type, event => event.stopPropagation(), options);\n }\n // Some libraries listen for outside presses on window in the capture phase (Headless UI) or trap focus (Radix).\n // Presses in the widget stop here, before them, so a page menu stays open while a person adds a note in it or\n // Show Element opened it. The browser still focuses and clicks as usual; our own handlers get a copy of the press.\n for (const type of ['pointerdown', 'mousedown', 'touchstart']) window.addEventListener(type, this.shieldPress, { ...options, capture: true });\n // Focus traps (Radix, MUI) pull focus back when it moves out of their menu. Focus moving into the widget is not news to the page.\n window.addEventListener('focusin', event => { if (event.composedPath().includes(this.host)) event.stopImmediatePropagation(); }, { ...options, capture: true });\n window.addEventListener('focusout', event => {\n if (event.relatedTarget === this.host && !event.composedPath().includes(this.host)) event.stopImmediatePropagation();\n }, { ...options, capture: true });\n // Modal menus hide the rest of the page from screen readers (aria-hidden on <body> children). The widget is not part of it.\n const unhide = new MutationObserver(() => { this.host.removeAttribute('aria-hidden'); this.host.removeAttribute('inert'); });\n unhide.observe(this.host, { attributes: true, attributeFilter: ['aria-hidden', 'inert'] });\n this.events.signal.addEventListener('abort', () => unhide.disconnect());\n // Rebuilding a field during IME composition cancels the composition, so renders wait for it to end.\n this.shadow.addEventListener('compositionstart', () => { this.composing = true; }, options);\n this.shadow.addEventListener('compositionend', () => {\n this.composing = false;\n if (this.renderDeferred) { this.renderDeferred = false; this.render(); }\n }, options);\n this.shadow.addEventListener('focusout', () => setTimeout(this.applyQueuedSnapshot), options);\n document.addEventListener('keydown', this.onKeyDown, options);\n document.addEventListener('click', this.onPageClick, { ...options, capture: true });\n // A press anywhere outside an open menu closes it, on the page and inside the widget.\n document.addEventListener('pointerdown', event => {\n if (!event.composedPath().some(el => el instanceof Element && el.matches('[role=menu],[aria-haspopup=menu]'))) this.closeMenus();\n }, { ...options, capture: true });\n document.addEventListener('pointermove', this.onPointerMove, { ...options, passive: true });\n window.addEventListener('scroll', this.schedulePosition, { ...options, capture: true, passive: true });\n window.addEventListener('resize', this.schedulePosition, options);\n window.addEventListener('resize', this.placeLauncher, options);\n window.addEventListener('resize', this.pushPage, options);\n window.visualViewport?.addEventListener('resize', this.schedulePosition, options);\n window.visualViewport?.addEventListener('scroll', this.schedulePosition, options);\n window.addEventListener('popstate', this.onRouteChange, options);\n window.addEventListener('hashchange', this.onRouteChange, options);\n this.resizeObserver = new ResizeObserver(this.schedulePosition);\n this.resizeObserver.observe(config.container ?? document.documentElement);\n this.anchorObserver = new ResizeObserver(this.schedulePosition);\n document.addEventListener('load', this.schedulePosition, { ...options, capture: true });\n document.fonts?.addEventListener('loadingdone', this.schedulePosition, options);\n document.addEventListener('transitionrun', this.trackLayoutMotion, { ...options, capture: true });\n document.addEventListener('animationstart', this.trackLayoutMotion, { ...options, capture: true });\n this.mutationObserver = new MutationObserver(this.schedulePosition);\n this.mutationObserver.observe(config.container ?? document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style', 'id', 'data-overplay-anchor', 'hidden', 'open'] });\n // Detect pushState/replaceState without patching the host router's methods.\n this.routeTimer = setInterval(this.onRouteChange, 500);\n this.render();\n this.ready = this.refresh().then(() => {\n if (!this.destroyed && this.storage.subscribeToChanges) {\n try { this.unsubscribe = this.storage.subscribeToChanges(this.receiveSnapshot); }\n catch (error) { this.report(error); this.render(); }\n }\n });\n }\n\n /** Site defaults come from the configuration. Each person can change them for this project. */\n private settingDefaults(): Settings {\n return { theme: this.config.theme ?? 'light', pinColor: 'site', buttonColor: 'default', resolvedPins: 'green', pinSize: 'regular', pinLabel: 'number', pushContent: this.config.pushContent !== false,\n notifications: this.config.showNotifications !== false, shortcut: !!this.config.enableKeyboardShortcuts && !!this.shortcut };\n }\n /** Saved per project and per account, so people who share a browser keep their own choices. */\n private settingsKey(): string { return `overplay:${this.project}:settings:${this.user.id}`; }\n private get settings(): Settings {\n const key = this.settingsKey();\n if (this.settingsCache?.key !== key) this.settingsCache = { key, value: readSettings(key, this.settingDefaults()) };\n return this.settingsCache.value;\n }\n private setSetting<K extends keyof Settings>(name: K, value: Settings[K]): void {\n const key = this.settingsKey(), settings = { ...this.settings, [name]: value };\n this.settingsCache = { key, value: settings };\n if (!writeSettings(key, settings, this.settingDefaults())) this.announce('Browser storage is unavailable. This choice lasts for this page view.');\n this.render();\n }\n setTheme(theme: 'light' | 'dark' | 'system'): void {\n if (!THEMES.includes(theme)) throw new Error('theme must be \"light\", \"dark\" or \"system\".');\n if (this.destroyed || this.config.theme === theme) return;\n // Saved choices are kept; only the defaults change.\n this.config.theme = theme; this.settingsCache = null; this.render();\n }\n private resetSettings(): void {\n const key = this.settingsKey(), defaults = this.settingDefaults();\n writeSettings(key, defaults, defaults); this.settingsCache = { key, value: defaults };\n this.docked = false;\n try { localStorage.removeItem(this.dockKey); } catch { /* Next to the pin for this page view. */ }\n this.render(); this.announce('Settings reset to the site defaults.');\n }\n private currentPage(): string {\n return this.config.getPageId?.() ?? defaultPageId(location);\n }\n private onCurrentPage(pageUrl: string): boolean {\n const page = this.currentPage();\n return this.config.getPageId ? pageUrl === page : samePage(pageUrl, page);\n }\n /** A field in the widget has focus. Background updates wait so typing, undo and IME input are not interrupted. */\n private typing(): boolean {\n const active = this.shadow.activeElement;\n return this.composing || active instanceof HTMLTextAreaElement || active instanceof HTMLInputElement;\n }\n private applyQueuedSnapshot = (): void => {\n if (this.destroyed || !this.queuedSnapshot || this.saving || this.loading || this.typing()) return;\n const next = this.queuedSnapshot; this.queuedSnapshot = null; this.apply(next);\n };\n private announce(message: string): void { this.live.textContent = message; }\n private report(error: unknown): void {\n const failure = error instanceof Error ? error : new Error('Could not save your changes.');\n this.error = failure.message;\n this.announce(failure.message);\n try { this.config.onError?.(failure); } catch { /* Host callbacks cannot break widget cleanup or state. */ }\n }\n private changed(): void {\n try { this.config.onChange?.(this.getAllComments()); } catch { /* Isolate host callbacks. */ }\n this.host.dispatchEvent(new CustomEvent('comments-changed', { detail: this.getAllComments(), bubbles: true, composed: true }));\n }\n private receiveSnapshot = (comments: Comment[]): void => {\n if (this.destroyed) return;\n try {\n const normalized = normalizeComments(comments);\n if (this.saving || this.loading || this.typing()) this.queuedSnapshot = normalized;\n else this.apply(normalized);\n } catch (error) { this.report(error); this.render(); }\n };\n /** Shows a background snapshot. An unchanged snapshot does not touch the DOM, so polling never makes the overlay flash. */\n private apply(comments: Comment[]): void {\n if (sameComments(comments, this.comments)) return;\n this.comments = comments; this.changed(); this.noticeActivity(); this.render();\n }\n /** Shows a short notification for each comment or reply that someone else added since the last load. */\n private noticeActivity(): void {\n const key = `${this.user.id}\\n${this.currentPage()}`;\n if (key !== this.seenKey) {\n // A new account or page starts from what is already there. Only later changes are news.\n this.seenKey = key; this.seen.clear(); newActivity(this.comments, this.seen, this.user.id); return;\n }\n if (!this.settings.notifications) { newActivity(this.comments, this.seen, this.user.id); return; }\n const found = newActivity(this.pageComments(), this.seen, this.user.id);\n newActivity(this.comments, this.seen, this.user.id);\n if (found.length > 3) this.toast({ kind: 'comment', commentId: '', author: `${found.length} new comments`, text: 'Open the comments panel to read them.' }, true);\n else for (const item of found) this.toast(item);\n }\n private toast(item: Activity, summary = false): void {\n const toast = element('div', 'toast');\n const body = element('div', 'toast-body');\n const title = element('p', 'toast-title');\n title.append(element('strong', '', item.author));\n if (!summary) {\n title.append(document.createTextNode(item.kind === 'reply' ? ' replied' : ' commented'));\n const number = this.pageComments().findIndex(c => c.id === item.commentId) + 1;\n if (number) title.append(element('span', 'toast-number', `#${number}`));\n }\n body.append(title, element('p', 'toast-text', item.text));\n if (summary) { const mark = element('span', 'avatar toast-icon'); mark.append(icon('comment')); toast.append(mark); }\n else toast.append(avatar(item.author, item.avatarUrl));\n toast.append(body);\n while (this.toasts.childElementCount >= 3) this.toasts.firstElementChild?.remove();\n this.toasts.append(toast);\n const later = (ms: number, run: () => void) => {\n const timer = setTimeout(() => { this.toastTimers.delete(timer); run(); }, ms); this.toastTimers.add(timer);\n };\n // Seven seconds is enough to read a short note. The exit fade runs before the toast is removed.\n later(7000, () => { toast.classList.add('leaving'); later(this.reducedMotion() ? 0 : 200, () => toast.remove()); });\n }\n\n async refresh(): Promise<void> {\n if (this.destroyed || this.saving) return;\n const version = ++this.loadVersion;\n this.loading = true; this.render();\n try {\n const comments = normalizeComments(await this.storage.loadComments());\n if (this.destroyed || version !== this.loadVersion) return;\n const next = this.queuedSnapshot ?? comments;\n const changed = !this.loaded || !sameComments(next, this.comments);\n this.comments = next; this.queuedSnapshot = null; this.loadFailed = false; this.error = ''; this.loaded = true;\n if (changed) { this.changed(); this.noticeActivity(); }\n } catch (error) {\n if (this.destroyed || version !== this.loadVersion) return;\n this.loadFailed = true; this.report(error);\n } finally {\n if (!this.destroyed && version === this.loadVersion) { this.loading = false; this.render(); if (this.loaded) this.openPending(); }\n }\n }\n getAllComments(): Comment[] { return copyComments(this.comments); }\n getUser(): CommentUser { return { ...this.user }; }\n private hostedSession(user?: CommentUser): void {\n if (this.destroyed) return;\n this.comments = []; this.queuedSnapshot = null; this.loaded = false; this.user = user ?? { id: 'signed-out', name: 'Sign in' };\n this.managedUser = true; this.draft = null; this.text = ''; this.replyText = ''; this.placing = false; this.activeId = null;\n this.changed(); this.render();\n }\n async signIn(): Promise<void> {\n if (!(this.storage instanceof HostedAdapter)) return;\n try { await this.storage.signIn(); await this.refresh(); } catch (error) { if (!this.destroyed) { this.report(error); this.render(); } }\n }\n async signOut(): Promise<void> {\n if (!(this.storage instanceof HostedAdapter) || this.saving) return;\n try { await this.storage.signOut(); await this.refresh(); } catch (error) { this.report(error); this.render(); }\n }\n setUser(user?: CommentUser): void {\n if (this.storage instanceof HostedAdapter) throw new Error('Hosted mode manages the signed-in account. Use signIn or signOut.');\n if (this.destroyed) return;\n if (this.saving) throw new Error('Wait until the current comment is saved before changing users.');\n this.user = user ? validateUser(user) : guestIdentity(this.identityKey).user;\n this.managedUser = !!user; this.editing = null;\n // Never submit a draft written under another identity.\n this.draft = null; this.text = ''; this.replyText = ''; this.placing = false;\n this.render();\n }\n show(): void {\n if (this.destroyed) return;\n if (!this.visible) this.returnFocus = document.activeElement;\n this.visible = true; this.render(); this.trackLayoutMotion();\n this.shadow.querySelector<HTMLElement>('.panel button, .launcher')?.focus();\n this.checkForUpdate();\n }\n hide(): void {\n if (this.destroyed) return;\n this.visible = false; this.placing = false; this.draft = null; this.activeId = null;\n this.editing = null; this.text = ''; this.replyText = ''; this.render();\n if (this.returnFocus instanceof HTMLElement && this.returnFocus.isConnected) this.returnFocus.focus();\n else this.shadow.querySelector<HTMLElement>('.launcher')?.focus();\n }\n startComment(position?: CommentPosition): void {\n if (this.storage instanceof HostedAdapter && !this.storage.signedIn) { void this.signIn(); return; }\n if (this.destroyed || this.initialLoad() || this.loadFailed || this.saving) return;\n this.visible = true; this.activeId = null; this.editing = null; this.text = '';\n if (position) {\n if (!Number.isFinite(position.x) || !Number.isFinite(position.y)) throw new Error('Comment coordinates must be finite.');\n const x = position.x - window.scrollX, y = position.y - window.scrollY;\n const target = document.elementFromPoint(x, y);\n if (this.config.container && (!target || !this.config.container.contains(target))) {\n throw new Error('Choose a position inside the configured container.');\n }\n this.draft = this.makeDraft(position, target); this.placing = false;\n } else { this.placing = true; this.draft = null; }\n this.render();\n this.announce(position ? 'Write your comment.' : 'Click a place on the page, or Tab to an element and press Enter. Press Escape to cancel.');\n this.shadow.querySelector<HTMLTextAreaElement>('textarea')?.focus();\n }\n navigateToComment(id: string): void {\n if (this.destroyed) return;\n const comment = this.comments.find(c => c.id === id);\n if (!comment) return;\n try {\n const url = safePageUrl(comment.pageUrl, location.href);\n if (!this.onCurrentPage(comment.pageUrl)) {\n // The next page load (or route change) opens this comment. See openPending().\n try { sessionStorage.setItem(this.openKey, id); } catch { /* The page still opens, without the comment. */ }\n location.assign(url.href); return;\n }\n this.visible = true; this.placing = false; this.draft = null; this.editing = null; this.activeId = id;\n this.replyText = ''; this.replyId = newId(); this.flash(id); this.render();\n const state = comment.selector ? this.elementState(comment) : 'shown';\n if (state === 'hidden' || (state === 'removed' && this.canReveal(comment))) void this.reveal(comment);\n else this.scrollToComment(comment);\n // Focus the thread itself, so screen readers start at the comment and no button shows a focus ring.\n this.shadow.querySelector<HTMLElement>('.detail')?.focus({ preventScroll: true });\n } catch (error) { this.report(error); this.visible = true; this.render(); }\n }\n private scrollToComment(comment: Comment): void {\n const behavior = this.reducedMotion() ? 'instant' : 'smooth';\n const target = this.anchorElement(comment);\n if (target && !this.detached(comment)) target.scrollIntoView({ block: 'center', behavior });\n // A note without a component, or one whose component is gone: go to where it was left.\n else window.scrollTo({ top: Math.max(0, comment.y - window.innerHeight / 2), behavior });\n }\n private detached(comment: Pick<Comment, 'selector'>): boolean { return isDetached(comment, this.config.container); }\n /**\n * Many menus (Radix, Headless UI, MUI, Vue) take a closed menu's items out of the page. A note that saved how its menu\n * was opened counts as hidden while the button that opens the menu is on the page; it counts as removed only when that\n * button is gone too, or opening the menu did not bring the element back.\n */\n private elementState(comment: Comment): ElementState {\n const state = elementState(comment, this.config.container);\n if (state !== 'removed' || this.revealed?.id === comment.id && !this.revealed.result.shown) return state;\n const opener = this.config.autoReveal !== false ? comment.element?.reveal?.[0]?.target : undefined;\n return opener && findTarget(opener) ? 'hidden' : state;\n }\n /** The saved name of the note's element. Older notes have none; their element is named from the page while it exists. */\n private elementInfo(comment: Comment): ElementInfo | undefined {\n if (comment.element) return comment.element;\n const target = this.anchorElement(comment) ?? (comment.selector ? (() => { try { return document.querySelector(comment.selector!); } catch { return null; } })() : null);\n return target ? describeElement(target) : undefined;\n }\n /**\n * Tells people who did not write the note what happened to its element and where to look: \"Element hidden\" with the\n * menu or section it is in, or \"Element removed\" when nothing on the page matches it now.\n */\n private anchorStatus(comment: Comment, state: ElementState): HTMLElement {\n const box = element('div', `anchor-status ${state}`); box.dataset.anchorStatus = state; box.hidden = state === 'shown';\n if (state === 'shown') return box;\n const info = this.elementInfo(comment);\n const hidden = state === 'hidden';\n const head = element('div', 'anchor-head'); const mark = element('span', 'anchor-icon'); mark.append(icon(hidden ? 'eyeOff' : 'unlink'));\n const titles = element('div', 'anchor-titles'); titles.append(element('strong', '', hidden ? 'Element hidden' : 'Element removed'));\n if (info) titles.append(element('span', 'anchor-target', info.place ? `${info.label} in ${info.place}` : info.label));\n head.append(mark, titles); box.append(head);\n const failed = this.revealed?.id === comment.id ? this.revealed.result.failed?.target.name : undefined;\n const opener = failed ?? info?.place;\n const where = hidden || failed\n ? opener ? `Open “${opener}” to see it.` : 'It is on this page, but not shown now. It can be in a closed menu, tab or filter.'\n : 'Nothing on this page matches it now. It was deleted, or it shows only after an action.';\n box.append(element('p', '', `${where} The dashed pin shows where the note was left.${this.canMove(comment) ? ' Drag the pin to attach it again.' : ''}`));\n if (hidden || this.canReveal(comment)) box.append(button('Show Element', 'quiet anchor-action', () => { void this.reveal(comment); }, 'eye'));\n return box;\n }\n /** A note on a removed element can still be shown when the site has a hook or the note saved how its menu was opened. */\n private canReveal(comment: Comment): boolean {\n return !!this.config.revealComponent || (this.config.autoReveal !== false && !!comment.element?.reveal?.length);\n }\n /**\n * Shows a component that is hidden: first the site's revealComponent hook (a map can zoom to a marker), then the\n * steps saved with the note (the menu, drawer or tab that was open), then closed details, popovers, menus,\n * accordions and tabs found from the page's ARIA. Frameworks render after a click, so each step waits for the next.\n */\n private async reveal(comment: Comment): Promise<void> {\n let handled = false;\n try { handled = !!(await this.config.revealComponent?.(copyComments([comment])[0], this.anchorElement(comment))); }\n catch (error) { this.report(error); }\n const steps = comment.element?.reveal;\n if (!handled && this.config.autoReveal !== false && steps?.length) {\n this.endReveal();\n this.replaying = true;\n let result: RevealResult;\n try { result = await replay(steps, () => this.anchorElement(comment)); } finally { this.replaying = false; }\n if (this.destroyed || this.activeId !== comment.id) { clearReveal(); return; }\n this.revealed = { id: comment.id, result };\n handled = result.shown;\n }\n if (!handled && this.config.autoReveal !== false) {\n const target = this.anchorElement(comment);\n if (target && revealElement(target)) { handled = true; await new Promise(done => setTimeout(done, 250)); }\n }\n if (this.destroyed || this.activeId !== comment.id) return;\n this.scrollToComment(comment); this.render();\n const state = this.elementState(comment);\n this.announce(state === 'shown' ? 'Showing the comment’s element.' : state === 'hidden'\n ? 'The comment’s element is still hidden. A dashed pin shows where it was.' : 'The comment’s element was removed. A dashed pin shows where it was.');\n }\n /**\n * A modal <dialog> makes the rest of the page inert, and a press outside an open popover closes it. While the note\n * being written or read is on an element in one of these top-layer parts, the widget moves inside it.\n */\n private syncLayer(): void {\n const active = this.activeId ? this.comments.find(c => c.id === this.activeId) : null;\n const target = this.draft ? this.anchorElement(this.draft) : active ? this.anchorElement(active) : null;\n const layers = target ? [...matchAll('dialog:modal'), ...matchAll(':popover-open')].filter(el => el.contains(target)) : [];\n // The innermost one: the others contain it.\n const parent = layers.find(el => layers.every(other => other.contains(el))) ?? document.body;\n if (this.host.parentElement !== parent) parent.append(this.host);\n }\n /** The note that Show Element opened a menu for has closed: end the CSS hover states it set. */\n private endReveal(): void {\n if (!this.revealed) return;\n this.revealed = null; clearReveal();\n }\n private shieldPress = (event: Event): void => {\n if (!event.isTrusted || !event.composedPath().includes(this.host)) return;\n event.stopImmediatePropagation();\n const inner = event.composedPath()[0];\n if (event.type === 'touchstart' || !(inner instanceof Element) || inner.getRootNode() !== this.shadow) return;\n if (!event.composedPath().some(el => el instanceof Element && el.matches('[role=menu],[aria-haspopup=menu]'))) this.closeMenus();\n const Copy = event.constructor as new (type: string, init: object) => Event;\n inner.dispatchEvent(new Copy(event.type, Object.assign({}, eventInit(event), { bubbles: true, cancelable: true, composed: false })));\n };\n /** Opens the comment that a click in \"All comments\" on another page asked for. */\n private openPending(): void {\n const linkId = new URL(location.href).searchParams.get('cw_comment');\n const linked = linkId ? this.comments.find(c => c.id === linkId && this.onCurrentPage(c.pageUrl)) : null;\n if (linked) {\n const url = new URL(location.href); url.search = withoutCommentLink(url.search); history.replaceState(history.state, '', url.href);\n this.navigateToComment(linked.id); return;\n }\n let id: string | null = null;\n try { id = sessionStorage.getItem(this.openKey); sessionStorage.removeItem(this.openKey); } catch { return; }\n const comment = id ? this.comments.find(c => c.id === id) : null;\n if (comment && this.onCurrentPage(comment.pageUrl)) this.navigateToComment(comment.id);\n }\n /** Pulses the pin and outlines its element while the pointer or focus is on its card in the list. */\n private hoverNote(id: string | null): void {\n if (this.hoverId === id) return;\n this.hoverId = id;\n for (const pin of this.pins.querySelectorAll<HTMLElement>('.pin[data-id]')) pin.classList.toggle('hovered', pin.dataset.id === id);\n this.positionPins();\n }\n /** Makes the pin pulse for a moment, so the eye finds it after a jump. */\n private flash(id: string): void {\n this.highlightId = id; clearTimeout(this.highlightTimer);\n this.highlightTimer = setTimeout(() => {\n this.highlightId = null; this.pins.querySelector('.highlight')?.classList.remove('highlight');\n }, 2400);\n }\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true; ++this.loadVersion; clearTimeout(this.highlightTimer); clearTimeout(this.searchTimer);\n if (this.storage instanceof HostedAdapter) this.storage.destroy();\n this.events.abort(); this.resizeObserver.disconnect(); this.mutationObserver.disconnect();\n this.anchorObserver.disconnect(); this.observedAnchors.clear();\n clearInterval(this.routeTimer); cancelAnimationFrame(this.frame); cancelAnimationFrame(this.motionFrame);\n for (const timer of this.toastTimers) clearTimeout(timer); this.toastTimers.clear();\n this.sidebarOpen = false; this.pushPage(); clearReveal();\n try { this.unsubscribe?.(); } finally { this.host.remove(); }\n }\n /** The first load for this page and account. Only then does the list show a loading state. */\n private initialLoad(): boolean { return this.loading && !this.loaded; }\n private reducedMotion(): boolean { return window.matchMedia('(prefers-reduced-motion: reduce)').matches; }\n private onRouteChange = (): void => {\n if (this.destroyed) return;\n const next = this.currentPage();\n if (next !== this.pageId) {\n this.pageId = next; this.activeId = null; this.draft = null; this.placing = false;\n this.text = ''; this.replyText = '';\n // All pages are already loaded, so the list changes at once. Hosted mode also checks for news.\n this.noticeActivity(); this.render();\n if (this.storage instanceof HostedAdapter) void this.refresh(); else this.openPending();\n }\n };\n private onKeyDown = (event: KeyboardEvent): void => {\n if (event.defaultPrevented || event.isComposing) return;\n const opener = event.key === 'Escape' ? this.closeMenus() : null;\n if (opener) { event.preventDefault(); opener.focus(); return; }\n if (event.key === 'Escape' && this.visible) {\n event.preventDefault();\n if (this.draft || this.placing || this.activeId || this.editing) this.closePopup();\n else this.hide();\n return;\n }\n const target = event.composedPath()[0];\n if (this.placing && event.key === 'Enter' && !event.composedPath().includes(this.host)) {\n const el = target instanceof Element && target !== document.body ? target : this.config.container ?? document.documentElement;\n if (this.config.container && !this.config.container.contains(el) && el !== this.config.container) return;\n const rect = el.getBoundingClientRect();\n const x = Math.max(16, Math.min(innerWidth - 16, rect.left + rect.width / 2));\n const y = Math.max(48, Math.min(innerHeight - 48, rect.top + Math.min(rect.height / 2, innerHeight / 2)));\n event.preventDefault(); this.choosePoint({ x: x + scrollX, y: y + scrollY }, el); return;\n }\n if (target instanceof Element && (target.closest('input,textarea,select,[contenteditable]:not([contenteditable=false])') || target.closest('[role=textbox]'))) return;\n if (!event.repeat && this.settings.shortcut && this.shortcut && matchesShortcut(event, this.shortcut)) {\n event.preventDefault(); if (this.visible) this.hide(); else this.show();\n }\n };\n private onPageClick = (event: MouseEvent): void => {\n if (event.composedPath().includes(this.host)) return;\n if (!this.placing) {\n // A click on the page closes the popup next to a pin, unless it holds unsent text. Clicks from scripts, such as\n // Show Element opening a menu, keep it open.\n if (!event.isTrusted || this.replaying) return;\n const open = this.activeId ? !this.replyText.trim() : this.draft ? !this.text.trim() : false;\n if (this.visible && open && !this.docked && !this.saving) this.closePopup(false);\n return;\n }\n if (event.ctrlKey || event.metaKey || event.altKey) return;\n const target = event.target;\n if (!(target instanceof Element) || (this.config.container && !this.config.container.contains(target))) return;\n event.preventDefault(); event.stopPropagation();\n this.choosePoint({ x: event.clientX + scrollX, y: event.clientY + scrollY }, target);\n };\n private choosePoint(position: CommentPosition, target: Element): void {\n let draft: Draft;\n try { draft = this.makeDraft(position, target); }\n catch (error) { this.report(error); this.render(); return; }\n this.placing = false;\n this.draft = draft; this.render(); this.shadow.querySelector<HTMLTextAreaElement>('textarea')?.focus();\n }\n /** Drag a pin to a new place. A press without movement still opens the comment. */\n private startPinDrag(event: PointerEvent, comment: Comment): void {\n this.suppressPinClick = false;\n if (event.button !== 0 || !event.isPrimary || this.saving || this.pinDrag) return;\n const pin = event.currentTarget as HTMLElement;\n // Keep the grab point under the pointer, so the pin does not jump.\n const dx = event.clientX - parseFloat(pin.style.left), dy = event.clientY - parseFloat(pin.style.top);\n const startX = event.clientX, startY = event.clientY;\n const stop = new AbortController(); const options = { signal: stop.signal };\n this.events.signal.addEventListener('abort', () => stop.abort(), options);\n let moved = false;\n window.addEventListener('pointermove', move => {\n if (move.pointerId !== event.pointerId || (!moved && Math.hypot(move.clientX - startX, move.clientY - startY) < 5)) return;\n moved = true;\n // The pin stays on screen and out of the sidebar, so it can always be seen and dropped back.\n const [minX, maxX] = this.pinBounds();\n this.pinDrag = { id: comment.id, x: clamp(move.clientX - dx, minX, maxX), y: clamp(move.clientY - dy, PIN_HEIGHT + 10, innerHeight - 6) };\n // Like placing a new note: outline the component the pin will attach to.\n const under = document.elementFromPoint(this.pinDrag.x, this.pinDrag.y);\n const component = under && under !== this.host ? componentTarget(under, this.config.container) : null;\n this.pickTarget = component === document.body || component === document.documentElement ? null : component;\n this.positionPins();\n }, options);\n const end = (up: PointerEvent) => {\n if (up.pointerId !== event.pointerId) return;\n stop.abort(); this.pickTarget = null;\n if (!moved) return;\n this.suppressPinClick = true;\n const drop = this.pinDrag;\n if (up.type === 'pointercancel' || !drop) { this.pinDrag = null; this.positionPins(); return; }\n void this.movePin(comment.id, drop).finally(() => { this.pinDrag = null; this.positionPins(); });\n };\n // Capture phase: the widget host stops pointerup from bubbling (see the menu shields), and a drag that never ends\n // opens the sidebar or leaves the pin stuck.\n window.addEventListener('pointerup', end, { ...options, capture: true });\n window.addEventListener('pointercancel', end, { ...options, capture: true });\n }\n /** The horizontal range where a pin stays fully visible: inside the screen and outside the open sidebar. */\n private pinBounds(): [number, number] {\n const side = this.sidebarOpen && innerWidth > 600 ? SIDEBAR : 0, onLeft = !!this.config.position?.endsWith('left');\n return [PIN_HALF + 2 + (onLeft ? side : 0), innerWidth - PIN_HALF - 2 - (onLeft ? 0 : side)];\n }\n private async movePin(id: string, drop: { x: number; y: number }): Promise<void> {\n const comment = this.comments.find(c => c.id === id);\n // The open sidebar and other widget parts are not a place for a pin. elementFromPoint returns our host for them.\n const target = document.elementFromPoint(drop.x, drop.y);\n if (!comment || !target || target === this.host || (this.config.container && !this.config.container.contains(target))) {\n this.announce('Drop the pin on the page to move it.'); return;\n }\n const position = { x: drop.x + scrollX, y: drop.y + scrollY };\n let draft: Draft;\n try { draft = this.makeDraft(position, target); }\n catch (error) { this.report(error); this.render(); return; }\n // A menu that Show Element opened came from script presses, which are not recorded. Keep the saved steps.\n if (draft.element && !draft.element.reveal && this.revealed?.id === id && comment.element?.reveal) draft.element.reveal = comment.element.reveal;\n const updated: Comment = { ...comment, x: position.x, y: position.y, selector: draft.selector, anchor: draft.anchor, element: draft.element, pageTitle: pageTitle() ?? comment.pageTitle };\n const next = this.getAllComments().map(c => c.id === id ? updated : c);\n this.activeId = id;\n await this.mutate(next, () => this.storage.upsertComment ? this.storage.upsertComment(updated) : this.storage.saveComments(next), () => {});\n }\n private onPointerMove = (event: PointerEvent): void => {\n const preview = this.pins.querySelector<HTMLElement>('.preview');\n if (!preview) return;\n const target = event.target;\n const inside = !this.config.container || (target instanceof Node && this.config.container.contains(target));\n preview.hidden = event.composedPath().includes(this.host) || !inside;\n preview.style.left = `${event.clientX}px`; preview.style.top = `${event.clientY}px`;\n // Outline the component the click will attach to, so the pick is never a surprise.\n const component = !preview.hidden && target instanceof Element ? componentTarget(target, this.config.container) : null;\n this.pickTarget = component === document.body || component === document.documentElement ? null : component;\n this.placePickRing();\n };\n private placePickRing(): void {\n const ring = this.pins.querySelector<HTMLElement>('.pick-ring');\n if (!ring) return;\n const rect = (this.placing || this.pinDrag) && this.pickTarget?.isConnected ? this.pickTarget.getBoundingClientRect() : null;\n ring.hidden = !rect || !rect.width || !rect.height;\n if (rect) Object.assign(ring.style, { left: `${rect.left - 3}px`, top: `${rect.top - 3}px`, width: `${rect.width + 6}px`, height: `${rect.height + 6}px` });\n };\n /** Places the open comment or the new comment form next to its pin, inside the free part of the screen. */\n private placePopover(): void {\n const pop = this.surface.querySelector<HTMLElement>('.popover');\n if (!pop) return;\n const sheet = innerWidth <= 600;\n pop.classList.toggle('sheet', sheet);\n if (sheet) { pop.style.left = ''; pop.style.top = ''; return; }\n const comment = this.draft ? null : this.comments.find(c => c.id === this.activeId);\n const dragging = !!comment && this.pinDrag?.id === comment.id;\n // The card would cover the page while its pin moves. It comes back next to the pin after the drop.\n pop.classList.toggle('moving', dragging);\n if (dragging) return;\n const pos = dragging ? this.pinDrag\n : this.draft ? this.position({ ...this.draft, ...this.draft.position })\n : comment ? this.position(comment) ?? (this.detached(comment) ? { x: comment.x - scrollX, y: comment.y - scrollY } : null) : null;\n const target = dragging ? null : this.draft ? this.anchorElement(this.draft) : comment ? this.anchorElement(comment) : null;\n const width = pop.offsetWidth, height = pop.offsetHeight;\n const side = this.sidebarOpen ? SIDEBAR : 0, onLeft = !!this.config.position?.endsWith('left');\n const minX = EDGE + (onLeft ? side : 0), maxX = innerWidth - EDGE - (onLeft ? 0 : side) - width;\n let x = maxX, y = 72;\n if (pos && pos.x >= 0 && pos.y >= 0 && pos.x <= innerWidth && pos.y <= innerHeight) {\n // Beside the component, so the card never hides what the note is about. A wide component leaves\n // no room beside it; then the card sits next to the pin. The top lines up with the pin head.\n const rect = target?.getBoundingClientRect();\n if (rect && rect.right + 12 <= maxX) x = rect.right + 12;\n else if (rect && rect.left - 12 - width >= minX) x = rect.left - 12 - width;\n else x = pos.x + 24 <= maxX ? pos.x + 24 : pos.x - 24 - width;\n y = pos.y - 40;\n }\n pop.style.left = `${clamp(x, minX, maxX)}px`; pop.style.top = `${clamp(y, EDGE, innerHeight - EDGE - height)}px`;\n }\n private makeDraft(position: CommentPosition, target: Element | null): Draft {\n const draft: Draft = { id: newId(), timestamp: new Date(), position, pageUrl: this.currentPage() };\n target = target ? componentTarget(target, this.config.container) : null;\n if (target && !this.host.contains(target)) {\n const rect = target.getBoundingClientRect();\n if (rect.width && rect.height) {\n draft.selector = componentSelector(target, this.config.container);\n draft.element = describeElement(target);\n const reveal = this.config.autoReveal !== false ? this.recorder.capture(target) : [];\n if (reveal.length) draft.element.reveal = reveal;\n draft.anchor = { x: Math.max(0, Math.min(1, (position.x - scrollX - rect.left) / rect.width)),\n y: Math.max(0, Math.min(1, (position.y - scrollY - rect.top) / rect.height)) };\n }\n }\n if (!draft.selector || !draft.anchor) throw new Error('Choose a visible page element to attach this note.');\n return draft;\n }\n private anchorElement(comment: Pick<Comment, 'selector'>): Element | null {\n return comment.selector ? resolveComponent(comment.selector, this.config.container) : null;\n }\n private position(comment: Pick<Comment, 'selector' | 'anchor' | 'x' | 'y'>): CommentPosition | null {\n return componentPosition(comment, this.config.container);\n }\n private observeAnchors(): void {\n const targets = new Set<Element>();\n for (const note of this.pageComments()) {\n const target = this.anchorElement(note); if (target) targets.add(target);\n }\n if (this.draft?.selector) {\n const target = this.anchorElement(this.draft); if (target) targets.add(target);\n }\n for (const target of this.observedAnchors) if (!targets.has(target)) this.anchorObserver.unobserve(target);\n for (const target of targets) if (!this.observedAnchors.has(target)) this.anchorObserver.observe(target);\n this.observedAnchors = targets;\n }\n private trackLayoutMotion = (): void => {\n if (this.motionFrame || !this.visible || this.destroyed) return;\n const tick = () => {\n this.motionFrame = 0;\n if (!this.visible || this.destroyed) return;\n this.positionPins();\n if (document.getAnimations().some(animation => animation.playState === 'running')) {\n this.motionFrame = requestAnimationFrame(tick);\n }\n };\n this.motionFrame = requestAnimationFrame(tick);\n };\n private schedulePosition = (): void => {\n if (this.frame || this.destroyed || !this.visible) return;\n this.frame = requestAnimationFrame(() => { this.frame = 0; this.positionPins(); });\n };\n private positionPins(): void {\n this.observeAnchors();\n // The dialog or popover the widget moved into has closed.\n const layer = this.host.parentElement;\n if (layer && layer !== document.body && ![...matchAll('dialog[open]'), ...matchAll(':popover-open')].includes(layer)) document.body.append(this.host);\n for (const pin of this.pins.querySelectorAll<HTMLElement>('[data-id]')) {\n const comment = this.comments.find(c => c.id === pin.dataset.id);\n if (!comment) continue;\n const dragging = this.pinDrag?.id === comment.id;\n pin.classList.toggle('dragging', dragging);\n // The open comment's component may be gone or hidden. A dashed pin then marks where the note was left.\n const lost = !dragging && comment.id === this.activeId && this.detached(comment);\n pin.classList.toggle('detached', lost);\n const pos = dragging ? this.pinDrag : lost ? { x: comment.x - scrollX, y: comment.y - scrollY } : this.position(comment);\n if (!pos) { pin.hidden = true; continue; }\n // Near the top the pin points up from below its spot, and near a side it slides in, so it never leaves the screen.\n const [minX, maxX] = this.pinBounds();\n pin.style.left = `${clamp(pos.x, minX, maxX)}px`; pin.style.top = `${pos.y}px`;\n pin.classList.toggle('below', pos.y < PIN_HEIGHT + 4);\n pin.hidden = pos.x < 0 || pos.y < 0 || pos.x > innerWidth || pos.y > innerHeight;\n if (this.config.container) {\n const rect = this.config.container.getBoundingClientRect();\n pin.hidden ||= pos.x < rect.left || pos.x > rect.right || pos.y < rect.top || pos.y > rect.bottom;\n }\n }\n const active = this.comments.find(c => c.id === this.activeId);\n const ring = this.pins.querySelector<HTMLElement>('.focus-ring');\n if (ring) {\n // Outlines the component the open comment is about.\n const rect = active ? this.anchorElement(active)?.getBoundingClientRect() : undefined;\n ring.hidden = !rect || !rect.width || !rect.height || this.pinDrag?.id === active?.id;\n if (rect) Object.assign(ring.style, { left: `${rect.left - 4}px`, top: `${rect.top - 4}px`, width: `${rect.width + 8}px`, height: `${rect.height + 8}px` });\n }\n const hoverRing = this.pins.querySelector<HTMLElement>('.hover-ring');\n if (hoverRing) {\n const hovered = this.hoverId ? this.comments.find(c => c.id === this.hoverId) : undefined;\n const rect = hovered && hovered.id !== this.activeId ? this.anchorElement(hovered)?.getBoundingClientRect() : undefined;\n hoverRing.hidden = !rect || !rect.width || !rect.height;\n if (rect) Object.assign(hoverRing.style, { left: `${rect.left - 4}px`, top: `${rect.top - 4}px`, width: `${rect.width + 8}px`, height: `${rect.height + 8}px` });\n }\n this.placePickRing(); this.placePopover();\n // The element can open, close or come back while the note is open.\n const status = this.surface.querySelector<HTMLElement>('[data-anchor-status]');\n if (status && active) { const state = this.elementState(active); if (status.dataset.anchorStatus !== state) status.replaceWith(this.anchorStatus(active, state)); }\n }\n /**\n * The open sidebar pushes the page aside instead of covering it, so every part of the page can still get a comment.\n * It adds a margin to <html> on the sidebar's side and restores the page's own value when it closes.\n * Phones keep the full-screen sidebar. Set pushContent: false to keep the sidebar above the page.\n */\n private pushPage = (): void => {\n const root = document.documentElement;\n const want = this.sidebarOpen && this.settings.pushContent && innerWidth > 600;\n const property = this.config.position?.endsWith('left') ? 'margin-left' : 'margin-right';\n if (want && !this.pushed) {\n this.pushed = { property, value: root.style.getPropertyValue(property), priority: root.style.getPropertyPriority(property) };\n root.style.setProperty(property, `${SIDEBAR}px`, 'important');\n } else if (!want && this.pushed) {\n const { property, value, priority } = this.pushed; this.pushed = null;\n if (value) root.style.setProperty(property, value, priority); else root.style.removeProperty(property);\n }\n };\n /**\n * Looks once for a newer npm release. A browser cannot update the site's code, so the notice copies the update command.\n * Only development hosts check by default: that is where the person reading the notice can run npm.\n */\n private checkForUpdate(): void {\n if (this.updateChecked || !(this.config.updateNotice ?? developmentHost(location.hostname))) return;\n this.updateChecked = true;\n void latestVersion().then(latest => {\n if (this.destroyed || !latest || !isNewer(latest, VERSION)) return;\n try { if (localStorage.getItem(UPDATE_DISMISSED) === latest) return; } catch { /* Show it. */ }\n this.update = latest; this.render();\n });\n }\n private async copyUpdate(): Promise<void> {\n let copied = false;\n try { await navigator.clipboard.writeText(UPDATE_COMMAND); copied = true; } catch { /* Show the command instead. */ }\n this.toast({ kind: 'comment', commentId: '', author: copied ? `Update command copied` : 'Run this to update',\n text: copied ? `Run it in your project, then reload: ${UPDATE_COMMAND}` : UPDATE_COMMAND }, true);\n this.announce(copied ? 'Update command copied.' : `Run ${UPDATE_COMMAND} to update.`);\n }\n /** \"Later\" hides the notice until the next version comes out. */\n private dismissUpdate(): void {\n try { localStorage.setItem(UPDATE_DISMISSED, this.update ?? ''); } catch { /* It shows again next time. */ }\n this.update = null; this.render();\n }\n /** Keeps a dragged launcher inside the viewport when the window size changes. */\n private placeLauncher = (): void => {\n const launcher = this.shadow.querySelector<HTMLElement>('.launcher');\n if (!launcher || !this.launcherSpot) return;\n const left = clamp(this.launcherSpot.x * innerWidth - LAUNCHER / 2, EDGE, innerWidth - LAUNCHER - EDGE);\n const top = clamp(this.launcherSpot.y * innerHeight - LAUNCHER / 2, EDGE, innerHeight - LAUNCHER - EDGE);\n Object.assign(launcher.style, { left: `${left}px`, top: `${top}px`, right: 'auto', bottom: 'auto' });\n };\n /** Drags the launcher anywhere on the screen. A press without movement stays a click. */\n private startDrag(event: PointerEvent): void {\n this.suppressClick = false;\n if (event.button !== 0 || !event.isPrimary) return;\n const launcher = event.currentTarget as HTMLElement;\n const rect = launcher.getBoundingClientRect();\n const offsetX = event.clientX - rect.left, offsetY = event.clientY - rect.top;\n const startX = event.clientX, startY = event.clientY;\n const stop = new AbortController();\n const options = { signal: stop.signal };\n this.events.signal.addEventListener('abort', () => stop.abort(), { signal: stop.signal });\n window.addEventListener('pointermove', move => {\n if (move.pointerId !== event.pointerId) return;\n if (!this.dragging && Math.hypot(move.clientX - startX, move.clientY - startY) < 5) return;\n this.dragging = true;\n const left = clamp(move.clientX - offsetX, EDGE, innerWidth - LAUNCHER - EDGE);\n const top = clamp(move.clientY - offsetY, EDGE, innerHeight - LAUNCHER - EDGE);\n this.launcherSpot = { x: (left + LAUNCHER / 2) / innerWidth, y: (top + LAUNCHER / 2) / innerHeight };\n this.shadow.querySelector('.launcher')?.classList.add('dragging');\n this.placeLauncher();\n }, options);\n const end = (up: PointerEvent) => {\n if (up.pointerId !== event.pointerId) return;\n stop.abort();\n if (!this.dragging) return;\n this.dragging = false; this.suppressClick = true;\n this.shadow.querySelector('.launcher')?.classList.remove('dragging');\n try { localStorage.setItem(this.launcherKey, JSON.stringify(this.launcherSpot)); } catch { /* The place lasts for this page view. */ }\n };\n // Capture phase: the widget host stops pointerup from bubbling (see the menu shields), and a drag that never ends\n // opens the sidebar or leaves the pin stuck.\n window.addEventListener('pointerup', end, { ...options, capture: true });\n window.addEventListener('pointercancel', end, { ...options, capture: true });\n }\n private pageComments(): Comment[] {\n return this.comments.filter(c => this.onCurrentPage(c.pageUrl))\n .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime() || a.id.localeCompare(b.id));\n }\n private closePopup(focus = true): void {\n this.draft = null; this.activeId = null; this.placing = false; this.editing = null;\n this.text = ''; this.replyText = ''; this.render();\n if (focus) this.shadow.querySelector<HTMLElement>('.panel .primary, .launcher')?.focus();\n }\n private setDocked(docked: boolean): void {\n this.docked = docked;\n try { localStorage.setItem(this.dockKey, docked ? '1' : '0'); } catch { /* The choice lasts for this page view. */ }\n this.render(); this.shadow.querySelector<HTMLElement>('.detail')?.focus({ preventScroll: true });\n }\n /** Comments for the chosen view: this page, or every page of the project. */\n private scopeComments(): Comment[] {\n if (this.scope === 'page') return this.pageComments();\n return [...this.comments].sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime() || a.id.localeCompare(b.id));\n }\n /** Note numbers count per page, in the order the notes were made. */\n private noteNumbers(): Map<string, number> {\n const counters = new Map<string, number>(), numbers = new Map<string, number>();\n for (const comment of [...this.comments].sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime() || a.id.localeCompare(b.id))) {\n const page = this.onCurrentPage(comment.pageUrl) ? '' : comment.pageUrl;\n const next = (counters.get(page) ?? 0) + 1; counters.set(page, next); numbers.set(comment.id, next);\n }\n return numbers;\n }\n private async mutate(next: Comment[], write: () => Promise<void>, done: () => void): Promise<void> {\n if (this.saving || this.initialLoad() || this.loadFailed || this.destroyed) return;\n // A background refresh would overwrite this change with older data, so it is cancelled.\n if (this.loading) { ++this.loadVersion; this.loading = false; }\n this.saving = true; this.error = ''; this.render();\n try {\n await write();\n if (this.destroyed) return;\n this.comments = next;\n // Reload after individual mutations to pick up other users' changes.\n try { this.comments = normalizeComments(await this.storage.loadComments()); }\n catch { this.error = 'Saved. Could not refresh other comments. Use Refresh to try again.'; }\n if (this.destroyed) return;\n this.queuedSnapshot = null; done(); this.changed(); this.noticeActivity();\n this.announce(this.error || 'Changes saved.');\n } catch (error) { if (!this.destroyed) this.report(error); }\n finally { if (!this.destroyed) { this.saving = false; this.render(); } }\n }\n private submitComment = (): void => {\n if (!this.draft || !this.text.trim()) return;\n const draft = this.draft;\n const comment: Comment = { id: draft.id, x: draft.position.x, y: draft.position.y, text: this.text.trim(),\n author: this.user.name, authorId: this.user.id, avatarUrl: this.user.avatarUrl, timestamp: draft.timestamp, replies: [],\n resolved: false, pageUrl: draft.pageUrl, pageTitle: pageTitle(), selector: draft.selector, anchor: draft.anchor, element: draft.element };\n const next = [...this.getAllComments(), comment];\n void this.mutate(next, () => this.storage.upsertComment ? this.storage.upsertComment(comment) : this.storage.saveComments(next), () => {\n this.draft = null; this.text = ''; this.activeId = comment.id;\n });\n };\n private submitReply = (): void => {\n const comment = this.comments.find(c => c.id === this.activeId);\n if (!comment || !this.replyText.trim()) return;\n const reply: Reply = { id: this.replyId, text: this.replyText.trim(), author: this.user.name, authorId: this.user.id,\n avatarUrl: this.user.avatarUrl, timestamp: new Date(), commentId: comment.id };\n const updated = { ...comment, replies: [...comment.replies, reply] };\n const next = this.getAllComments().map(c => c.id === comment.id ? updated : c);\n void this.mutate(next, () => this.storage.addReply ? this.storage.addReply(comment.id, reply) :\n this.storage.upsertComment ? this.storage.upsertComment(updated) : this.storage.saveComments(next), () => { this.replyText = ''; this.replyId = newId(); });\n };\n private toggleResolved(comment: Comment): void {\n const updated = { ...comment, resolved: !comment.resolved };\n const next = this.getAllComments().map(c => c.id === comment.id ? updated : c);\n void this.mutate(next, () => this.storage.setResolved ? this.storage.setResolved(comment.id, updated.resolved) :\n this.storage.upsertComment ? this.storage.upsertComment(updated) : this.storage.saveComments(next), () => {});\n }\n private deleteNote(comment: Comment): void {\n const next = this.getAllComments().filter(c => c.id !== comment.id);\n void this.mutate(next, () => this.storage.deleteComment ? this.storage.deleteComment(comment.id) : this.storage.saveComments(next), () => { this.activeId = null; });\n }\n private render(): void {\n if (this.destroyed) return;\n if (this.composing) { this.renderDeferred = true; return; }\n if (this.revealed && this.activeId !== this.revealed.id) this.endReveal();\n this.syncLayer();\n // The list is gone once the sidebar closes or a thread opens, so no card can be under the pointer.\n if (!this.sidebarOpen || this.activeId || this.draft) this.hoverId = null;\n const active = this.shadow.activeElement;\n const focusKey = active instanceof HTMLElement ? active.dataset.focus : undefined;\n const selection = active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement ? [active.selectionStart, active.selectionEnd] : null;\n const scroll = this.shadow.querySelector('.list')?.scrollTop ?? 0;\n const threadScroll = this.shadow.querySelector('.thread-body')?.scrollTop ?? 0;\n const hadPanel = !!this.surface.querySelector('.panel');\n this.host.dataset.theme = this.settings.theme;\n this.surface.replaceChildren(); this.pins.replaceChildren();\n const detail = this.visible ? this.detail() : null;\n // The guest name form lives in the sidebar. A comment opens next to its pin unless the person docked it.\n const docked = !!detail && (this.docked || !!this.editing);\n const sidebar = this.visible && (docked || !this.config.hideSidebar);\n // The open sidebar replaces the launcher, so the button never covers the comment field.\n if (!this.config.hideButton && !sidebar) this.surface.append(this.launcher());\n if (this.visible) {\n if (sidebar) this.surface.append(this.sidebar(docked ? detail : null));\n if (detail && !docked) {\n const popover = element('div', 'popover'); popover.append(detail); this.surface.append(popover);\n // On a phone the card is a bottom sheet over the page, so the full-screen list steps back.\n this.surface.querySelector('.panel')?.classList.add('behind');\n }\n this.renderPins();\n if (this.placing) {\n const notice = element('div', `notice${sidebar ? ' beside-panel' : ''}${this.config.position?.endsWith('left') ? ' left' : ''}`);\n notice.append(icon('pin'), element('span', '', `Click anywhere to leave a note, or Tab to an element and press Enter.`));\n const escape = element('kbd', '', 'Esc'); notice.append(escape, button('Cancel placement', 'icon-button', () => this.closePopup(), 'close'));\n this.surface.append(notice);\n }\n }\n // Rebuilt elements play their entry animation only when they first open. A re-render keeps them still.\n this.surface.querySelector('.panel')?.classList.toggle('entering', !hadPanel);\n const detailKey = !detail ? '' : this.editing ? this.editing : this.draft ? `draft:${this.draft.id}` : `thread:${this.activeId}`;\n detail?.classList.toggle('entering', (hadPanel || !docked) && detailKey !== this.detailKey); this.detailKey = detailKey;\n this.toasts.classList.toggle('beside-panel', sidebar);\n this.sidebarOpen = sidebar; this.pushPage();\n this.toasts.classList.toggle('left', !!this.config.position?.endsWith('left'));\n this.toasts.classList.toggle('top', !!this.config.position?.startsWith('top'));\n const list = this.shadow.querySelector('.list'); if (list) list.scrollTop = scroll;\n const body = this.shadow.querySelector('.thread-body'); if (body) body.scrollTop = threadScroll;\n if (focusKey) {\n const focus = Array.from(this.shadow.querySelectorAll<HTMLElement>('[data-focus]')).find(el => el.dataset.focus === focusKey);\n focus?.focus({ preventScroll: true });\n if (selection && (focus instanceof HTMLInputElement || focus instanceof HTMLTextAreaElement)) {\n focus.setSelectionRange(selection[0], selection[1]);\n }\n }\n this.positionPins();\n }\n private launcher(): HTMLElement {\n const launcher = button('Comments', `launcher${this.dragging ? ' dragging' : ''}`, () => {\n if (this.suppressClick) { this.suppressClick = false; return; }\n if (this.visible) this.hide(); else this.show();\n }, 'comment');\n launcher.replaceChildren(icon('comment')); this.paintLauncher(launcher);\n launcher.dataset.focus = 'launcher'; launcher.setAttribute('aria-expanded', String(this.visible));\n launcher.title = 'Comments. Drag to move.';\n launcher.addEventListener('pointerdown', event => this.startDrag(event));\n const count = this.pageComments().filter(c => !c.resolved).length;\n launcher.setAttribute('aria-label', count ? `Comments, ${count} open` : 'Comments');\n if (count) launcher.append(element('span', 'badge', String(count)));\n const position = this.config.position ?? 'bottom-right';\n if (position.endsWith('left')) { launcher.style.left = '24px'; launcher.style.right = 'auto'; }\n if (position.startsWith('top')) { launcher.style.top = '24px'; launcher.style.bottom = 'auto'; }\n // A place the person dragged it to wins over the configured corner.\n if (this.launcherSpot) queueMicrotask(this.placeLauncher);\n return launcher;\n }\n private heading(title: string, subtitle: string): HTMLElement {\n const head = element('div', 'head');\n const brand = element('span', 'brand-icon'); brand.append(icon('comment'));\n const heading = element('div', 'heading'); heading.append(element('h2', '', title));\n if (subtitle) heading.append(element('p', 'subtext', subtitle));\n // Settings and the account sit at the top, next to close, like the menus of a desktop app.\n const actions = element('div', 'head-actions');\n const settings = button('Settings', 'icon-button', () => this.openSettings(), 'settings'); settings.dataset.focus = 'settings';\n actions.append(settings, this.userMenu(), button('Close comments', 'icon-button', () => this.hide(), 'close'));\n head.append(brand, heading, actions); return head;\n }\n private menuItem(label: string, iconName: Parameters<typeof icon>[0], run: () => void, cls = ''): HTMLButtonElement {\n const entry = button(label, `menu-item ${cls}`, run, iconName); entry.setAttribute('role', 'menuitem'); return entry;\n }\n /** A button that opens a menu below it. A click outside or Escape closes the menu. */\n private menuToggle(toggle: HTMLButtonElement, menu: HTMLElement): void {\n menu.hidden = true; menu.setAttribute('role', 'menu');\n toggle.setAttribute('aria-haspopup', 'menu'); toggle.setAttribute('aria-expanded', 'false');\n toggle.addEventListener('click', () => {\n const open = menu.hidden; this.closeMenus(); menu.hidden = !open; toggle.setAttribute('aria-expanded', String(open));\n if (open) menu.querySelector<HTMLElement>('button:not(:disabled)')?.focus();\n });\n }\n /** Closes every open menu. Returns the button of the menu that was open, so Escape can put focus back on it. */\n private closeMenus(): HTMLElement | null {\n let opener: HTMLElement | null = null;\n for (const menu of this.shadow.querySelectorAll<HTMLElement>('[role=menu]')) menu.hidden = true;\n for (const toggle of this.shadow.querySelectorAll<HTMLElement>('[aria-haspopup=menu]')) {\n if (toggle.getAttribute('aria-expanded') === 'true') opener = toggle;\n toggle.setAttribute('aria-expanded', 'false');\n }\n return opener;\n }\n /** The account button: the person's picture, and a menu with their name, settings and sign-out. */\n private userMenu(): HTMLElement {\n const hosted = this.storage instanceof HostedAdapter ? this.storage : null;\n if (hosted && !hosted.signedIn) {\n const signIn = button('Sign In', 'quiet sign-in', () => { void this.signIn(); }, 'signin');\n signIn.title = 'Sign in to join this project'; return signIn;\n }\n const wrap = element('div', 'menu-wrap');\n const toggle = element('button', 'user-button'); toggle.type = 'button'; toggle.dataset.focus = 'user';\n toggle.setAttribute('aria-label', `Account: ${this.user.name}`); toggle.title = this.user.name;\n toggle.append(avatar(this.user.name, this.user.avatarUrl));\n const menu = element('div', 'pop-menu user-menu');\n const card = element('div', 'menu-user'); const about = element('div', 'menu-user-text');\n about.append(element('strong', '', this.user.name), element('small', '', hosted ? 'Signed in to this project' : this.managedUser ? 'Your project account'\n : this.persistentGuest ? 'Guest in this browser' : 'Guest for this page view'));\n card.append(avatar(this.user.name, this.user.avatarUrl), about); menu.append(card);\n if (!hosted && !this.managedUser) menu.append(this.menuItem('Edit Your Name', 'edit', () => {\n this.editing = 'identity'; this.draft = null; this.activeId = null; this.placing = false; this.render();\n this.shadow.querySelector<HTMLInputElement>('#guest-name')?.focus();\n }));\n menu.append(this.menuItem('Settings', 'settings', () => this.openSettings()));\n if (hosted) { const out = this.menuItem('Sign Out', 'signout', () => { void this.signOut(); }); out.disabled = this.saving; menu.append(out); }\n const note = element('p', 'menu-note'); note.append(element('span', 'storage-dot'),\n element('span', '', hosted ? 'Comments sync with your team' : this.storage instanceof LocalStorageAdapter ? 'Comments are saved in this browser' : 'Comments use connected storage'));\n menu.append(note); this.menuToggle(toggle, menu);\n wrap.append(toggle, menu); return wrap;\n }\n private openSettings(): void {\n this.editing = 'settings'; this.draft = null; this.activeId = null; this.placing = false; this.render();\n this.shadow.querySelector<HTMLElement>('.detail')?.focus({ preventScroll: true });\n }\n /** Header of a detail view: a back link and close on one bar, then the title. It reads as a step inside the list. */\n private detailHeading(title: string, subtitle: string, extra?: HTMLElement): HTMLElement {\n const wrap = element('div', 'detail-head');\n const bar = element('div', 'detail-bar');\n const back = button('Back to comments', 'back-link', () => this.closePopup(), 'back');\n back.querySelector('span')!.textContent = 'Comments';\n bar.append(back, button('Close comments', 'icon-button', () => this.hide(), 'close'));\n const titleRow = element('div', 'detail-title'); titleRow.append(element('h2', '', title));\n if (extra) titleRow.append(extra);\n wrap.append(bar, titleRow);\n if (subtitle) wrap.append(element('p', 'subtext', subtitle));\n return wrap;\n }\n /** Header of a comment card: icon, title, status line, a menu for less frequent actions, and close. */\n private cardHeading(title: string, subtitle: string, name: 'comment' | 'plus', hint = '', remove?: () => void): HTMLElement {\n const wrap = element('div', 'card-head');\n if (this.docked) {\n const bar = element('div', 'detail-bar');\n const back = button('Back to comments', 'back-link', () => this.closePopup(), 'back');\n back.querySelector('span')!.textContent = 'Comments';\n bar.append(back, button('Close comments', 'icon-button', () => this.hide(), 'close')); wrap.append(bar);\n }\n const head = element('div', 'pop-head'); if (hint) head.title = hint;\n const tile = element('span', 'pop-icon'); tile.append(icon(name));\n const text = element('div', 'pop-title'); text.append(element('h2', '', title), element('p', 'pop-sub', subtitle));\n const menu = element('div', 'pop-menu');\n const item = this.menuItem.bind(this);\n // Where a comment opens (next to its pin or in the sidebar) is a Settings choice; the menu only deletes.\n if (remove) {\n const del = item('Delete Comment', 'trash', () => {\n if (del.dataset.confirm) { remove(); return; }\n del.dataset.confirm = '1'; del.querySelector('span')!.textContent = 'Click Again to Delete';\n }, 'danger');\n del.disabled = this.saving; menu.append(del);\n }\n head.append(tile, text);\n if (menu.childElementCount) { const more = button('More actions', 'icon-button more', () => {}, 'more'); this.menuToggle(more, menu); head.append(more); }\n if (!this.docked) head.append(button('Close', 'icon-button', () => this.closePopup(), 'close'));\n if (menu.childElementCount) head.append(menu);\n wrap.append(head); return wrap;\n }\n private errorBox(): HTMLElement {\n // report() announces errors once in the live region. A role=alert box would repeat on every render.\n const error = element('div', 'error', this.error);\n if (this.loadFailed || this.error.startsWith('Saved.')) error.append(button('Try Again', 'quiet', () => { void this.refresh(); }));\n return error;\n }\n /** The open comment, the new comment form, or the guest name form. Each fills the sidebar. */\n private detail(): HTMLElement | null {\n if (this.editing === 'settings') return this.settingsView();\n if (this.editing === 'identity') return this.identityForm();\n if (this.draft) return this.newCommentForm();\n const comment = this.comments.find(c => c.id === this.activeId && this.onCurrentPage(c.pageUrl));\n return comment ? this.thread(comment) : null;\n }\n private sidebar(detail: HTMLElement | null): HTMLElement {\n const panel = element('section', `panel${this.config.position?.endsWith('left') ? ' left' : ''}${this.placing ? ' placing' : ''}`);\n panel.setAttribute('aria-label', 'Comments');\n if (detail) { panel.append(detail); return panel; }\n panel.append(this.heading('Comments', ''));\n const toolbar = element('div', 'toolbar');\n const add = button('Add Comment', 'primary', () => this.startComment(), 'plus');\n add.disabled = this.initialLoad() || this.loadFailed || this.saving;\n const refresh = button('Refresh comments', `icon-button outlined${this.loading ? ' busy' : ''}`, () => { void this.refresh(); }, 'refresh');\n refresh.disabled = this.loading || this.saving;\n toolbar.append(add, refresh); panel.append(toolbar);\n panel.append(this.scopeBar());\n const comments = this.scopeComments();\n if (comments.length) panel.append(this.searchField(), this.peopleBar());\n panel.append(this.statusTabs());\n if (this.error) panel.append(this.errorBox());\n panel.append(this.commentList(comments));\n const footer = this.footer(); if (footer) panel.append(footer);\n // \"/\" moves to the search field while focus is in the panel, as in many apps.\n panel.addEventListener('keydown', event => {\n const target = event.composedPath()[0];\n if (event.key !== '/' || event.ctrlKey || event.metaKey || event.altKey || event.isComposing) return;\n if (target instanceof Element && target.closest('input,textarea,select')) return;\n const field = this.shadow.querySelector<HTMLInputElement>('.search input');\n if (field) { event.preventDefault(); field.focus(); field.select(); }\n });\n return panel;\n }\n /** Search, the Open/Resolved tabs and the author choices for the notes list. */\n private filterContext(scope: Scope = this.scope): FilterContext {\n // A note on another page cannot be named from this page, so only its saved name counts.\n return { userId: this.user.id, includePage: scope === 'all', elementOf: c => this.onCurrentPage(c.pageUrl) ? this.elementInfo(c) : c.element };\n }\n private restoreFilters(): void {\n try {\n const saved = JSON.parse(sessionStorage.getItem(this.filterKey) || 'null');\n if (!saved) return;\n this.filters = readFilters(saved); this.scope = saved.scope === 'all' ? 'all' : 'page';\n } catch { /* The defaults. */ }\n }\n private saveFilters(): void {\n try { sessionStorage.setItem(this.filterKey, JSON.stringify({ ...this.filters, scope: this.scope })); } catch { /* They last for this page view. */ }\n }\n /** Changes the filters, keeps them for this tab and says how many notes are shown. */\n private setFilters(patch: Partial<NoteFilters>, scope?: Scope): void {\n this.filters = { ...this.filters, ...patch }; if (scope) this.scope = scope;\n this.saveFilters(); this.render(); this.announceResults();\n }\n private announceResults(): void {\n const all = this.scopeComments();\n if (!this.sidebarOpen || !all.length) return;\n const shown = filterNotes(all, this.filters, this.filterContext()).length;\n this.announce(shown ? `${shown} ${shown === 1 ? 'note' : 'notes'} shown.` : 'No notes match.');\n }\n /** Rebuilds the counts, the list and the pins, not the search field, so typing keeps its undo history and IME state. */\n private refreshResults(): void {\n const comments = this.scopeComments();\n const swap = (selector: string, next: HTMLElement) => this.shadow.querySelector(selector)?.replaceWith(next);\n swap('.scope', this.scopeBar()); swap('.people', this.peopleBar()); swap('.tabs', this.statusTabs()); swap('.list', this.commentList(comments));\n this.pins.replaceChildren(); this.renderPins(); this.positionPins();\n }\n /** Only the search, Mine and author apply to these counts: each count is what that view shows. */\n private scopeBar(): HTMLElement {\n const scopes = element('div', 'scope'); scopes.setAttribute('role', 'group'); scopes.setAttribute('aria-label', 'Show comments from');\n const people = { ...this.filters, status: 'all' as const };\n for (const [scope, label] of [['page', 'This Page'], ['all', 'All Pages']] as const) {\n const notes = scope === 'page' ? this.pageComments() : this.comments;\n const count = filterNotes(notes, people, this.filterContext(scope)).length;\n const option = button(label, 'scope-option', () => this.setFilters({}, scope));\n option.setAttribute('aria-label', `${label}, ${count} ${count === 1 ? 'note' : 'notes'}`);\n option.setAttribute('aria-pressed', String(this.scope === scope)); option.dataset.focus = `scope-${scope}`;\n option.append(element('span', 'count', String(count))); scopes.append(option);\n }\n return scopes;\n }\n private searchField(): HTMLElement {\n const search = element('div', 'search'); search.setAttribute('role', 'search');\n const input = element('input'); input.type = 'search'; input.placeholder = 'Search notes, replies, people…';\n input.setAttribute('aria-label', 'Search comments'); input.value = this.filters.query; input.dataset.focus = 'search';\n input.maxLength = 200; input.setAttribute('aria-keyshortcuts', '/'); input.autocomplete = 'off'; input.spellcheck = false;\n const clear = button('Clear search', 'icon-button search-clear', () => { input.value = ''; apply(true); input.focus(); }, 'close');\n clear.hidden = !input.value;\n const apply = (now: boolean) => {\n clearTimeout(this.searchTimer); clear.hidden = !input.value;\n const run = () => {\n if (this.destroyed || this.filters.query === input.value) return;\n this.filters = { ...this.filters, query: input.value }; this.saveFilters(); this.refreshResults(); this.announceResults();\n };\n // A short pause after the last key, so the list does not jump on every letter.\n if (now) run(); else this.searchTimer = setTimeout(run, 180);\n };\n input.addEventListener('input', () => apply(false));\n input.addEventListener('keydown', event => {\n // Escape clears the search first. With an empty field, it closes the panel as before.\n if (event.key === 'Escape' && input.value && !event.isComposing) { event.preventDefault(); input.value = ''; apply(true); }\n else if (event.key === 'Enter' && !event.isComposing) { event.preventDefault(); apply(true); }\n });\n search.append(icon('search'), input, clear); return search;\n }\n /** Mine, the author list and Clear Filters. */\n private peopleBar(): HTMLElement {\n const bar = element('div', 'people'); bar.setAttribute('role', 'group'); bar.setAttribute('aria-label', 'Filter by person');\n const counts = filterCounts(this.scopeComments(), this.filters, this.filterContext());\n const hosted = this.storage instanceof HostedAdapter ? this.storage : null;\n if (!hosted || hosted.signedIn) {\n const mine = button('Mine', 'filter-chip', () => this.setFilters({ mine: !this.filters.mine, author: '' }));\n mine.title = 'Only notes you started'; mine.dataset.focus = 'filter-mine';\n mine.setAttribute('aria-label', `Mine, ${counts.mine} ${counts.mine === 1 ? 'note' : 'notes'}`);\n mine.setAttribute('aria-pressed', String(this.filters.mine)); mine.append(element('span', 'count', String(counts.mine)));\n bar.append(mine);\n }\n const authors = counts.authors;\n if (this.filters.author && !authors.some(a => a.key === this.filters.author)) authors.push({ key: this.filters.author, name: 'Earlier author', count: 0 });\n if (authors.length > 1 || this.filters.author) {\n const wrap = element('span', `select${this.filters.author ? ' chosen' : ''}`);\n const select = element('select'); select.setAttribute('aria-label', 'Author'); select.dataset.focus = 'filter-author';\n select.append(new Option('All Authors', ''));\n for (const author of authors) select.append(new Option(`${author.name} (${author.count})`, author.key));\n select.value = this.filters.author;\n select.addEventListener('change', () => this.setFilters({ author: select.value, mine: false }));\n wrap.append(select); bar.append(wrap);\n }\n if (filtersActive(this.filters)) {\n const clear = button('Clear Filters', 'link-button', () => this.clearAllFilters()); clear.dataset.focus = 'filter-clear'; bar.append(clear);\n }\n bar.hidden = !bar.childElementCount;\n return bar;\n }\n private statusTabs(): HTMLElement {\n const tabs = element('div', 'tabs'); tabs.setAttribute('role', 'group'); tabs.setAttribute('aria-label', 'Filter by status');\n const counts = filterCounts(this.scopeComments(), this.filters, this.filterContext());\n for (const [status, label] of [['open', 'Open'], ['resolved', 'Resolved'], ['all', 'All']] as const) {\n const tab = button(label, 'tab', () => this.setFilters({ status }));\n tab.setAttribute('aria-label', `${label}, ${counts[status]} ${counts[status] === 1 ? 'note' : 'notes'}`);\n tab.setAttribute('aria-pressed', String(this.filters.status === status)); tab.dataset.focus = `tab-${status}`;\n tab.append(element('span', 'count', String(counts[status]))); tabs.append(tab);\n }\n return tabs;\n }\n private clearAllFilters(): void {\n this.setFilters(clearFilters(this.scopeComments()));\n this.shadow.querySelector<HTMLElement>('.search input, .panel .primary')?.focus();\n }\n private commentList(comments: Comment[]): HTMLElement {\n const list = element('div', 'list'); list.setAttribute('aria-busy', String(this.loading));\n const filtered = filterNotes(comments, this.filters, this.filterContext());\n const pageScope = this.scope === 'page';\n if (this.initialLoad()) list.append(this.empty('Loading your notes', 'Your comments will appear here in a moment.'));\n else if (this.loadFailed) list.append(this.empty('Could not load comments', 'Your stored notes have not been changed. Try loading them again.'));\n else if (!comments.length) {\n list.append(this.empty('Good ideas start here', pageScope ? 'Pin a thought to any part of this page. Keep the conversation in context.' : 'Comments from every page of this site appear here.',\n pageScope ? button('Leave the First Note', 'quiet', () => this.startComment()) : undefined));\n } else if (!filtered.length) {\n const query = this.filters.query.trim();\n const why = query ? `Nothing ${pageScope ? 'on this page' : 'on any page'} matches “${query.length > 60 ? `${query.slice(0, 60)}…` : query}”.`\n : filtersActive(this.filters) ? 'No notes fit these filters.'\n : this.filters.status === 'open' ? 'Every note here is resolved.' : 'No note here is resolved yet.';\n list.append(this.empty('No notes match', why, button('Clear Filters', 'quiet', () => this.clearAllFilters())));\n } else {\n const numbers = this.noteNumbers();\n // Group by page. This page comes first, then the pages with the newest notes.\n const groups = new Map<string, Comment[]>();\n for (const comment of [...filtered].sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())) {\n const key = this.onCurrentPage(comment.pageUrl) ? '' : comment.pageUrl;\n groups.set(key, [...groups.get(key) ?? [], comment]);\n }\n const ordered = [...groups].sort(([a], [b]) => Number(a !== '') - Number(b !== ''));\n for (const [page, notes] of ordered) {\n const title = element('div', 'list-title');\n if (pageScope) title.textContent = 'On this page';\n else {\n const path = pageLabel(page || this.currentPage());\n // The newest note carries the freshest title. Older notes have none, so the path stays the fallback.\n const name = (page ? notes.find(c => c.pageTitle)?.pageTitle : pageTitle()) ?? path;\n const label = element('span', name === path ? 'page-path' : 'page-name', name); label.title = path;\n title.append(label);\n // The path tells two pages with the same title apart.\n if (name !== path) { const where = element('span', 'page-path sub', path); where.title = path; title.append(where); }\n if (!page) title.append(element('span', 'here', 'This page'));\n }\n list.append(title);\n for (const comment of notes) list.append(this.noteRow(comment, numbers.get(comment.id) ?? 0, !!page));\n }\n }\n return list;\n }\n private noteRow(comment: Comment, number: number, elsewhere: boolean): HTMLElement {\n const page = comment.pageTitle || pageLabel(comment.pageUrl);\n const label = elsewhere ? `Open comment by ${comment.author} on ${page}` : `Open comment by ${comment.author}`;\n const note = button(label, `note${this.activeId === comment.id ? ' current' : ''}`, () => this.navigateToComment(comment.id));\n note.replaceChildren();\n const words = parseQuery(this.filters.query);\n // Two columns: the message on the left; the number with the status under it on the right, so every card lines up.\n const main = element('div', 'note-main');\n main.append(this.messageHeader(comment.author, comment.timestamp, comment.avatarUrl, comment.via, words), marked(element('p', 'note-text'), comment.text, words));\n // The words are in a reply or the element's name: show where, so the match is not a mystery.\n const match = words.length ? matchNote(comment, words, this.filterContext()) : null;\n const where = match?.reply ? [`${match.reply.author}: `, match.reply.text] : match?.element ? ['Element: ', match.element] : null;\n if (where) {\n const line = element('p', 'note-match'); line.append(icon(match?.reply ? 'comment' : 'pin'), element('span', 'note-match-label', where[0]));\n line.append(marked(element('span', 'note-match-text'), excerpt(where[1], words), words)); main.append(line);\n }\n const state = elsewhere ? 'shown' : this.elementState(comment);\n if (comment.replies.length || elsewhere || state !== 'shown') {\n const footer = element('div', 'note-footer');\n if (comment.replies.length) footer.append(icon('comment'), element('span', '', `${comment.replies.length} ${comment.replies.length === 1 ? 'reply' : 'replies'}`));\n if (state !== 'shown') {\n const info = this.elementInfo(comment);\n const flag = element('span', `hidden-flag ${state}`, state === 'removed' ? 'Element removed' : info?.place ? `Hidden in ${info.place}` : 'Element hidden');\n flag.prepend(icon(state === 'removed' ? 'unlink' : 'eyeOff'));\n flag.title = info ? `${info.label}${info.place ? ` in ${info.place}` : ''}. Open the comment to see where it was.` : 'Open the comment to see where it was.';\n footer.append(flag);\n }\n if (elsewhere) { const go = element('span', 'go', 'Go to Page'); go.append(icon('open')); footer.append(go); }\n main.append(footer);\n }\n const meta = element('span', 'note-meta');\n const status = element('span', `status${comment.resolved ? ' resolved' : ''}`, comment.resolved ? 'Resolved' : 'Open');\n if (comment.resolved) status.prepend(icon('check')); else status.prepend(element('span', 'status-dot'));\n meta.append(element('span', 'note-number', `#${number}`), status);\n note.append(main, meta);\n if (!elsewhere) {\n // Hover or keyboard focus shows where the comment is on the page.\n note.addEventListener('pointerenter', () => this.hoverNote(comment.id));\n note.addEventListener('pointerleave', () => this.hoverNote(null));\n note.addEventListener('focus', () => this.hoverNote(comment.id));\n note.addEventListener('blur', () => this.hoverNote(null));\n }\n return note;\n }\n private empty(title: string, text: string, action?: HTMLElement): HTMLElement {\n const empty = element('div', 'empty'); const wrap = element('div');\n const mark = element('div', 'empty-icon'); mark.append(icon(title === 'No notes match' ? 'search' : 'comment'));\n wrap.append(mark, element('h3', '', title), element('p', '', text));\n if (action) wrap.append(action);\n empty.append(wrap); return empty;\n }\n /** A new npm version is the one thing left at the bottom. The account and settings live in the header. */\n private footer(): HTMLElement | null {\n if (!this.update) return null;\n const footer = element('div', 'footer update-bar'); footer.setAttribute('role', 'status');\n const mark = element('span', 'update-icon'); mark.append(icon('refresh'));\n const text = element('div', 'update-text');\n text.append(element('strong', '', `Version ${this.update} is available`), element('span', '', `You have ${VERSION}. Update the package, then reload.`));\n const command = element('div', 'update-command'); const code = element('code', '', UPDATE_COMMAND); code.title = UPDATE_COMMAND;\n const copy = button(`Copy the command to update to version ${this.update}`, 'quiet update', () => { void this.copyUpdate(); });\n copy.querySelector('span')!.textContent = 'Copy';\n command.append(code, copy);\n footer.append(mark, text, button('Hide until the next version', 'icon-button', () => this.dismissUpdate(), 'close'), command);\n return footer;\n }\n private messageHeader(name: string, timestamp: Date, url?: string, via?: string, words: string[] = []): HTMLElement {\n const head = element('div', 'note-header');\n const time = element('time', 'time', relativeTime(timestamp)); time.dateTime = timestamp.toISOString(); time.title = timestamp.toLocaleString();\n head.append(avatar(name, url), marked(element('span', 'name'), name, words));\n if (via) { const source = element('span', 'via', `via ${via}`); source.title = `Posted through MCP by ${via}`; head.append(source); }\n head.append(time); return head;\n }\n private view(title: string, className = ''): HTMLElement {\n const view = element('div', `detail ${className}`); view.setAttribute('role', 'group'); view.setAttribute('aria-label', title); view.tabIndex = -1;\n return view;\n }\n private composer(isReply: boolean): HTMLElement {\n const form = element('form', 'compose'); const textarea = element('textarea');\n textarea.setAttribute('aria-label', isReply ? 'Reply' : 'Comment'); textarea.placeholder = isReply ? 'Keep the conversation going…' : 'What’s on your mind?';\n textarea.maxLength = 10000; textarea.required = true; textarea.value = isReply ? this.replyText : this.text;\n textarea.dataset.focus = isReply ? 'reply' : 'comment'; textarea.disabled = this.saving;\n const bar = element('div', 'compose-bar');\n const hint = element('span', 'compose-hint', '⌘ / Ctrl + Enter to send');\n const submit = button(this.saving ? 'Saving…' : isReply ? 'Send Reply' : 'Post Comment', 'primary', () => {}, 'arrow'); submit.type = 'submit';\n submit.disabled = this.saving || !textarea.value.trim();\n textarea.addEventListener('input', () => {\n if (isReply) this.replyText = textarea.value; else this.text = textarea.value;\n submit.disabled = this.saving || !textarea.value.trim();\n });\n textarea.addEventListener('keydown', event => {\n if ((event.ctrlKey || event.metaKey) && event.key === 'Enter' && !event.isComposing) { event.preventDefault(); if (!submit.disabled) form.requestSubmit(); }\n });\n form.addEventListener('submit', event => { event.preventDefault(); if (!this.saving) { if (isReply) this.submitReply(); else this.submitComment(); } });\n bar.append(hint, submit); form.append(textarea, bar); return form;\n }\n private newCommentForm(): HTMLElement {\n const view = this.view('New comment', 'new-comment');\n view.append(this.cardHeading('New comment', `Commenting as ${this.user.name}`, 'plus'));\n if (this.error) view.append(this.errorBox());\n view.append(this.composer(false)); return view;\n }\n private thread(comment: Comment): HTMLElement {\n const view = this.view('Comment thread', `thread${comment.resolved ? ' is-resolved' : ''}`);\n const canDelete = this.config.canDelete?.(comment, this.getUser()) ?? this.manages(comment);\n view.append(this.cardHeading(`Note #${this.pageComments().indexOf(comment) + 1}`,\n comment.resolved ? 'Resolved conversation' : 'Open conversation', 'comment',\n this.canMove(comment) ? 'Drag its pin to move it.' : '', canDelete ? () => this.deleteNote(comment) : undefined));\n if (this.error) view.append(this.errorBox());\n if (comment.selector) view.append(this.anchorStatus(comment, this.elementState(comment)));\n const body = element('div', 'thread-body');\n for (const message of [comment, ...comment.replies]) {\n const row = element('div', 'message'); row.append(this.messageHeader(message.author, message.timestamp, message.avatarUrl, message.via), element('p', 'message-text', message.text));\n body.append(row);\n }\n view.append(body);\n const actions = element('div', 'thread-actions');\n if (comment.resolved) {\n const status = element('span', 'status resolved', 'Resolved'); status.prepend(icon('check'));\n const reopen = button('Reopen Conversation', 'quiet reopen', () => this.toggleResolved(comment)); reopen.disabled = this.saving;\n actions.append(status, reopen);\n } else actions.append(...this.replyBar(comment));\n view.append(actions); return view;\n }\n /** One line to reply. The button resolves the conversation, or sends the reply once there is text. */\n private replyBar(comment: Comment): HTMLElement[] {\n const form = element('form', 'reply-bar'); const field = element('textarea');\n field.rows = 1; field.placeholder = 'Reply…'; field.setAttribute('aria-label', 'Reply'); field.maxLength = 10000;\n field.value = this.replyText; field.dataset.focus = 'reply'; field.disabled = this.saving;\n const send = button(this.saving ? 'Saving…' : 'Send Reply', 'primary send', () => {}, 'arrow'); send.type = 'submit';\n const resolve = button('Mark as Resolved', 'primary resolve', () => this.toggleResolved(comment), 'check');\n resolve.querySelector('span')!.textContent = 'Resolve'; resolve.disabled = this.saving; send.disabled = this.saving;\n const sync = () => {\n const typed = !!field.value.trim(); send.hidden = !typed; resolve.hidden = typed;\n field.style.height = 'auto'; field.style.height = `${Math.min(field.scrollHeight, 120)}px`;\n };\n field.addEventListener('input', () => { this.replyText = field.value; sync(); });\n field.addEventListener('keydown', event => {\n // Enter sends, Shift+Enter starts a new line.\n if (event.key === 'Enter' && !event.shiftKey && !event.isComposing) { event.preventDefault(); if (field.value.trim()) form.requestSubmit(); }\n });\n form.addEventListener('submit', event => { event.preventDefault(); if (!this.saving) this.submitReply(); });\n form.append(field, send); queueMicrotask(sync);\n return [form, resolve];\n }\n /** Authors manage their own comments. The project owner and admins manage every comment. */\n private manages(comment: Comment): boolean { return comment.authorId === this.user.id || this.user.role === 'owner' || this.user.role === 'admin'; }\n private canMove(comment: Comment): boolean {\n return this.config.canMove?.(comment, this.getUser()) ?? this.manages(comment);\n }\n /** Display choices for this project. Each person has their own, saved in this browser. */\n private settingsView(): HTMLElement {\n const view = this.view('Settings', 'settings');\n view.append(this.detailHeading('Settings', 'Your choices for this project. Other people keep their own.'));\n const current = this.settings, body = element('div', 'settings-body');\n const section = (title: string) => { const group = element('section', 'setting-group'); group.append(element('h3', '', title)); body.append(group); return group; };\n const row = (group: HTMLElement, label: string, hint: string, control: HTMLElement) => {\n const line = element('div', 'setting'); const text = element('div', 'setting-text');\n text.append(element('strong', '', label)); if (hint) text.append(element('small', '', hint));\n line.append(text, control); group.append(line); return line;\n };\n const choice = <K extends keyof Settings>(name: K, label: string, options: [Settings[K], string][]) => {\n const group = element('div', 'segmented'); group.setAttribute('role', 'group'); group.setAttribute('aria-label', label);\n for (const [value, text] of options) {\n const option = button(text, 'segment', () => this.setSetting(name, value));\n option.setAttribute('aria-pressed', String(current[name] === value)); option.dataset.focus = `set-${name}-${value}`; group.append(option);\n }\n return group;\n };\n const toggle = <K extends keyof Settings>(name: K, label: string, disabled = false) => {\n const on = current[name] === true;\n const control = element('button', 'switch'); control.type = 'button'; control.setAttribute('role', 'switch');\n control.setAttribute('aria-checked', String(on)); control.setAttribute('aria-label', label); control.dataset.focus = `set-${name}`;\n control.disabled = disabled; control.addEventListener('click', () => this.setSetting(name, !on as Settings[K])); return control;\n };\n\n const look = section('Appearance');\n row(look, 'Theme', current.theme === 'system' ? 'Follows your device' : '', choice('theme', 'Theme', [['light', 'Light'], ['dark', 'Dark'], ['system', 'System']]));\n\n const pins = section('Pins');\n // A live sample: one open and one resolved pin in the chosen style.\n const sample = element('div', `pin-sample${current.pinSize === 'small' ? ' small' : ''}${current.resolvedPins === 'gray' ? ' resolved-gray' : ''}`);\n sample.setAttribute('aria-hidden', 'true'); sample.style.setProperty('--cw-accent', this.pinColor());\n const label = (n: number) => current.pinLabel === 'initials' ? initials(this.user.name) : String(n);\n sample.append(element('span', 'pin', label(1)), element('span', 'pin resolved', label(2)), element('span', 'pin-sample-text', 'Open and resolved'));\n pins.append(sample);\n const swatches = element('div', 'swatches'); swatches.setAttribute('role', 'group'); swatches.setAttribute('aria-label', 'Pin color');\n const site = this.config.primaryColor!.toLowerCase();\n // A palette color that equals the site color would look like a second \"site\" swatch, so it is left out.\n const palette = Object.entries(PIN_COLORS).filter(([key, c]) => c.color !== site || current.pinColor === key);\n for (const [value, name, color] of [['site', 'Site color', site], ...palette.map(([key, c]) => [key, c.label, c.color])] as [Settings['pinColor'], string, string][]) {\n const swatch = button(name, 'swatch', () => this.setSetting('pinColor', value)); swatch.replaceChildren();\n swatch.style.setProperty('--swatch', color); swatch.setAttribute('aria-pressed', String(current.pinColor === value));\n swatch.dataset.focus = `set-pinColor-${value}`; swatches.append(swatch);\n }\n row(pins, 'Color', current.pinColor === 'site' ? 'The color of this site' : PIN_COLORS[current.pinColor].label, swatches).classList.add('wide');\n row(pins, 'Resolved pins', '', choice('resolvedPins', 'Resolved pins', [['green', 'Green'], ['gray', 'Gray']]));\n row(pins, 'Size', '', choice('pinSize', 'Pin size', [['regular', 'Regular'], ['small', 'Small']]));\n row(pins, 'Label', '', choice('pinLabel', 'Pin label', [['number', 'Number'], ['initials', 'Initials']]));\n\n const floating = section('Comments button');\n // A live sample of the floating button, because the open sidebar hides the real one.\n const buttonSample = element('div', 'launcher-sample'); buttonSample.setAttribute('aria-hidden', 'true');\n const mini = element('span', 'launcher-mini'); mini.append(icon('comment'), element('span', 'badge', '3')); this.paintLauncher(mini);\n buttonSample.append(mini, element('span', 'pin-sample-text', 'On the page'));\n floating.append(buttonSample);\n const buttonSwatches = element('div', 'swatches'); buttonSwatches.setAttribute('role', 'group'); buttonSwatches.setAttribute('aria-label', 'Button color');\n // Graphite is the default button, so it is not offered twice. A palette color equal to the site color is left out too.\n const buttonPalette = Object.entries(PIN_COLORS).filter(([key, c]) => key !== 'graphite' && (c.color !== site || current.buttonColor === key));\n for (const [value, name, color] of [['default', 'Default', 'var(--cw-inverse)'], ['site', 'Site color', site], ...buttonPalette.map(([key, c]) => [key, c.label, c.color])] as [Settings['buttonColor'], string, string][]) {\n const swatch = button(name, 'swatch', () => this.setSetting('buttonColor', value)); swatch.replaceChildren();\n swatch.style.setProperty('--swatch', color); swatch.setAttribute('aria-pressed', String(current.buttonColor === value));\n swatch.dataset.focus = `set-buttonColor-${value}`; buttonSwatches.append(swatch);\n }\n const buttonHint = current.buttonColor === 'default' ? 'Dark. Takes the site color while open.' : current.buttonColor === 'site' ? 'The color of this site' : PIN_COLORS[current.buttonColor].label;\n row(floating, 'Color', buttonHint, buttonSwatches).classList.add('wide');\n\n const panel = section('Panel');\n const open = element('div', 'segmented'); open.setAttribute('role', 'group'); open.setAttribute('aria-label', 'Open comments');\n for (const [docked, text] of [[false, 'Next to Pin'], [true, 'In Sidebar']] as const) {\n const option = button(text, 'segment', () => { if (this.docked !== docked) this.setDocked(docked); });\n option.setAttribute('aria-pressed', String(this.docked === docked)); option.dataset.focus = `set-docked-${docked}`; open.append(option);\n }\n row(panel, 'Open comments', '', open);\n row(panel, 'Push the page aside', 'The open panel does not cover the page.', toggle('pushContent', 'Push the page aside'));\n\n const alerts = section('Notifications and keys');\n row(alerts, 'New activity', 'Show a short notice when others comment or reply.', toggle('notifications', 'Show new activity'));\n const keys = this.config.keyboardShortcut?.split('+').map(key => key.length === 1 ? key.toUpperCase() : key[0].toUpperCase() + key.slice(1)).join(' + ') ?? '';\n row(alerts, 'Keyboard shortcut', this.shortcut ? `${keys} opens and closes comments.` : 'This site has no shortcut.', toggle('shortcut', 'Keyboard shortcut', !this.shortcut));\n\n const foot = element('div', 'settings-foot');\n foot.append(element('span', '', 'Saved in this browser'), button('Reset to Defaults', 'quiet', () => this.resetSettings()));\n view.append(body, foot); return view;\n }\n /** Colors the floating button with the person's choice. The default button keeps its own dark and open styles. */\n private paintLauncher(launcher: HTMLElement): void {\n const choice = this.settings.buttonColor;\n if (choice === 'default') return;\n launcher.classList.add('colored');\n launcher.style.setProperty('--cw-launcher', choice === 'site' ? this.config.primaryColor! : PIN_COLORS[choice].color);\n }\n /** The pin color the person chose, or the site's own color. */\n private pinColor(): string {\n const choice = this.settings.pinColor;\n return choice === 'site' ? this.config.primaryColor! : PIN_COLORS[choice].color;\n }\n private identityForm(): HTMLElement {\n const view = this.view('Your guest profile'); view.append(this.detailHeading('Your name', 'A name to put to your notes.'));\n const form = element('form', 'identity-form'); const label = element('label', '', 'Display name'); label.htmlFor = 'guest-name';\n const input = element('input'); input.id = 'guest-name'; input.value = this.user.name === 'Guest' ? '' : this.user.name;\n input.placeholder = 'Your name'; input.maxLength = 80; input.required = true; input.setAttribute('autocomplete', 'nickname'); input.dataset.focus = 'guest-name';\n const explanation = element('p', '', this.persistentGuest ? 'Your name and guest ID stay in this browser. No account or email is needed. You can change your name without changing your ID.' : 'Browser storage is unavailable. This guest profile lasts for this session.');\n const submit = button('Save Name', 'primary', () => {}); submit.type = 'submit';\n form.addEventListener('submit', event => {\n event.preventDefault(); if (!input.value.trim()) return;\n this.user = { ...this.user, name: input.value.trim() }; this.persistentGuest = saveGuest(this.identityKey, this.user);\n this.editing = null; this.render(); this.announce('Guest name saved.');\n });\n form.append(label, input, explanation, submit); view.append(form); return view;\n }\n private renderPins(): void {\n // An open comment keeps full color. Other pins fade, so the eye finds the one you are reading.\n this.pins.classList.toggle('focused', !!this.activeId && !this.draft);\n const settings = this.settings;\n this.pins.classList.toggle('small', settings.pinSize === 'small');\n this.pins.classList.toggle('resolved-gray', settings.resolvedPins === 'gray');\n this.pins.style.setProperty('--cw-accent', this.pinColor());\n if (this.activeId) { const ring = element('div', 'focus-ring'); ring.hidden = true; this.pins.append(ring); }\n const hoverRing = element('div', 'focus-ring hover-ring'); hoverRing.hidden = true; this.pins.append(hoverRing);\n const comments = this.pageComments();\n // Pins follow the list's filters. Without a sidebar there is no way to change them, so only the status applies.\n const filters = this.config.hideSidebar ? { ...DEFAULT_FILTERS, status: this.filters.status } : this.filters;\n const shown = new Set(filterNotes(comments, filters, this.filterContext('page')).map(c => c.id));\n for (const [index, comment] of comments.entries()) {\n if (comment.id !== this.activeId && !shown.has(comment.id)) continue;\n const movable = !this.saving && this.canMove(comment);\n const pin = button(`Comment ${index + 1} by ${comment.author}: ${comment.text.slice(0, 100)}`, `pin${comment.resolved ? ' resolved' : ''}${this.highlightId === comment.id ? ' highlight' : ''}${this.hoverId === comment.id ? ' hovered' : ''}${movable ? ' movable' : ''}`, () => {\n if (this.suppressPinClick) { this.suppressPinClick = false; return; }\n this.navigateToComment(comment.id);\n });\n if (movable) { pin.title += '. Drag to move.'; pin.addEventListener('pointerdown', event => this.startPinDrag(event, comment)); }\n pin.replaceChildren(document.createTextNode(settings.pinLabel === 'initials' ? initials(comment.author) : String(index + 1))); pin.dataset.id = comment.id;\n pin.setAttribute('aria-pressed', String(this.activeId === comment.id)); this.pins.append(pin);\n }\n const pickRing = element('div', 'focus-ring pick-ring'); pickRing.hidden = true; this.pins.append(pickRing);\n if (this.placing) { const preview = element('span', 'pin preview', '+'); preview.hidden = true; this.pins.append(preview); }\n if (this.draft) {\n const preview = element('span', 'pin', '+'); const pos = this.position({ ...this.draft, ...this.draft.position });\n if (pos) { preview.style.left = `${pos.x}px`; preview.style.top = `${pos.y}px`; }\n else preview.hidden = true;\n this.pins.append(preview);\n }\n }\n}\n","import type { StorageAdapter } from './StorageAdapter';\nimport type { Comment, Reply } from '../core/types';\nimport { normalizeComments } from '../core/data';\nexport interface APIAdapterConfig {\n baseUrl: string;\n /** Called per request, allowing refreshed authentication tokens. */\n headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);\n credentials?: RequestCredentials;\n projectId?: string;\n endpoints?: { load?: string; save?: string };\n}\n/** A REST contract, not a hosted service. See README for server routes. */\nexport class APIAdapter implements StorageAdapter {\n constructor(private config: APIAdapterConfig) {}\n private async request(path: string, method = 'GET', body?: unknown): Promise<unknown> {\n const headers = typeof this.config.headers === 'function' ? await this.config.headers() : this.config.headers;\n const url = new URL(`${this.config.baseUrl.replace(/\\/$/, '')}${path}`, window.location.href);\n if (this.config.projectId) url.searchParams.set('projectId', this.config.projectId);\n const response = await fetch(url, { method, credentials: this.config.credentials ?? 'same-origin',\n headers: { ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}), ...headers },\n body: body !== undefined ? JSON.stringify(body) : undefined });\n if (!response.ok) throw new Error(`Could not ${method === 'GET' ? 'load' : 'save'} comments (${response.status}).`);\n if (method !== 'GET' || response.status === 204) return undefined;\n return response.json();\n }\n async loadComments(): Promise<Comment[]> {\n return normalizeComments(await this.request(this.config.endpoints?.load ?? '/comments'));\n }\n async saveComments(comments: Comment[]): Promise<void> {\n await this.request(this.config.endpoints?.save ?? '/comments', 'POST', comments);\n }\n async upsertComment(comment: Comment): Promise<void> {\n await this.request(`${this.config.endpoints?.save ?? '/comments'}/${encodeURIComponent(comment.id)}`, 'PUT', comment);\n }\n async deleteComment(id: string): Promise<void> {\n await this.request(`${this.config.endpoints?.save ?? '/comments'}/${encodeURIComponent(id)}`, 'DELETE');\n }\n async addReply(id: string, reply: Reply): Promise<void> {\n await this.request(`${this.config.endpoints?.save ?? '/comments'}/${encodeURIComponent(id)}/replies`, 'POST', reply);\n }\n async setResolved(id: string, resolved: boolean): Promise<void> {\n await this.request(`${this.config.endpoints?.save ?? '/comments'}/${encodeURIComponent(id)}`, 'PATCH', { resolved });\n }\n}\n","import { Overlay } from './widget/Overlay';\nimport type { OverplayConfig } from './config';\nimport type { OverplayAPI } from './widget/Overlay';\nexport type { OverplayConfig, OverplayAPI };\nexport type { Comment, Reply, CommentUser, CommentPosition, ElementInfo } from './core/types';\nexport type { StorageAdapter } from './storage/StorageAdapter';\nexport { LocalStorageAdapter } from './storage/LocalStorageAdapter';\nexport { HostedAdapter } from './storage/HostedAdapter';\nexport { APIAdapter } from './storage/APIAdapter';\nexport type { APIAdapterConfig } from './storage/APIAdapter';\n/** Call after the document body exists, or in your framework's mount effect. */\nexport function initOverplay(config: OverplayConfig = {}): OverplayAPI {\n if (typeof document === 'undefined' || !document.body) throw new Error('Initialize Overplay in the browser after the page has mounted.');\n return new Overlay(config);\n}\nexport const init = initOverplay;\n"],"names":["value","location","reply","key","words","date","clean","nameOf","_a","CONTROL","record","press","pseudo","init","el","element","property","version","label"],"mappings":"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"}