@ashlr/hub 3.5.1 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +3 -0
  3. package/dist/build-identity.json +2 -2
  4. package/dist/cli/activation.d.ts +41 -0
  5. package/dist/cli/activation.js +485 -0
  6. package/dist/cli/activation.js.map +1 -0
  7. package/dist/core/daemon/cutoff-checkpoint-scheduler.js +7 -0
  8. package/dist/core/daemon/cutoff-checkpoint-scheduler.js.map +1 -1
  9. package/dist/core/daemon/loop.d.ts +19 -0
  10. package/dist/core/daemon/loop.js +235 -5
  11. package/dist/core/daemon/loop.js.map +1 -1
  12. package/dist/core/daemon/overnight-status.d.ts +152 -0
  13. package/dist/core/daemon/overnight-status.js +275 -0
  14. package/dist/core/daemon/overnight-status.js.map +1 -0
  15. package/dist/core/daemon/post-merge-halt.d.ts +212 -0
  16. package/dist/core/daemon/post-merge-halt.js +503 -0
  17. package/dist/core/daemon/post-merge-halt.js.map +1 -0
  18. package/dist/core/daemon/run-window.d.ts +218 -0
  19. package/dist/core/daemon/run-window.js +420 -0
  20. package/dist/core/daemon/run-window.js.map +1 -0
  21. package/dist/core/fleet/generated-repair-resolution.d.ts +36 -0
  22. package/dist/core/fleet/generated-repair-resolution.js +245 -0
  23. package/dist/core/fleet/generated-repair-resolution.js.map +1 -0
  24. package/dist/core/local-runtime/llama/port.d.ts +17 -0
  25. package/dist/core/local-runtime/llama/port.js +47 -0
  26. package/dist/core/local-runtime/llama/port.js.map +1 -0
  27. package/dist/core/local-runtime/llama/proxy-host.d.ts +54 -0
  28. package/dist/core/local-runtime/llama/proxy-host.js +159 -0
  29. package/dist/core/local-runtime/llama/proxy-host.js.map +1 -0
  30. package/dist/core/local-runtime/llama/proxy-process.d.ts +148 -0
  31. package/dist/core/local-runtime/llama/proxy-process.js +250 -0
  32. package/dist/core/local-runtime/llama/proxy-process.js.map +1 -0
  33. package/dist/core/local-runtime/llama/proxy-record.d.ts +40 -0
  34. package/dist/core/local-runtime/llama/proxy-record.js +133 -0
  35. package/dist/core/local-runtime/llama/proxy-record.js.map +1 -0
  36. package/dist/core/local-runtime/llama/proxy-supervisor.d.ts +118 -0
  37. package/dist/core/local-runtime/llama/proxy-supervisor.js +511 -0
  38. package/dist/core/local-runtime/llama/proxy-supervisor.js.map +1 -0
  39. package/dist/core/web/public/next/assets/{App-BbVoUCIi.js → App-vtaHB9mp.js} +2 -2
  40. package/dist/core/web/public/next/assets/{App-BbVoUCIi.js.map → App-vtaHB9mp.js.map} +1 -1
  41. package/dist/core/web/public/next/assets/{ApprovalsSection-BW9iVjUa.js → ApprovalsSection-B-bFJ0I9.js} +2 -2
  42. package/dist/core/web/public/next/assets/{ApprovalsSection-BW9iVjUa.js.map → ApprovalsSection-B-bFJ0I9.js.map} +1 -1
  43. package/dist/core/web/public/next/assets/{AutonomySection-Cpk_oEhc.css → AutonomySection-CHjxJt2z.css} +1 -1
  44. package/dist/core/web/public/next/assets/AutonomySection-DoqmsCjw.js +2 -0
  45. package/dist/core/web/public/next/assets/AutonomySection-DoqmsCjw.js.map +1 -0
  46. package/dist/core/web/public/next/assets/ChatSection-BfnLe5dT.css +1 -0
  47. package/dist/core/web/public/next/assets/ChatSection-vNPIJffd.js +80 -0
  48. package/dist/core/web/public/next/assets/ChatSection-vNPIJffd.js.map +1 -0
  49. package/dist/core/web/public/next/assets/{ConfirmDialog-CXevY3Au.js → ConfirmDialog-Dd2APQhB.js} +2 -2
  50. package/dist/core/web/public/next/assets/{ConfirmDialog-CXevY3Au.js.map → ConfirmDialog-Dd2APQhB.js.map} +1 -1
  51. package/dist/core/web/public/next/assets/{Dialog-Bn0CgEGz.js → Dialog-CPM9JxBc.js} +2 -2
  52. package/dist/core/web/public/next/assets/{Dialog-Bn0CgEGz.js.map → Dialog-CPM9JxBc.js.map} +1 -1
  53. package/dist/core/web/public/next/assets/{DiffViewer-QKyisN2L.js → DiffViewer-B84qVef9.js} +2 -2
  54. package/dist/core/web/public/next/assets/{DiffViewer-QKyisN2L.js.map → DiffViewer-B84qVef9.js.map} +1 -1
  55. package/dist/core/web/public/next/assets/McpSection-CEUpV_5X.js +2 -0
  56. package/dist/core/web/public/next/assets/McpSection-CEUpV_5X.js.map +1 -0
  57. package/dist/core/web/public/next/assets/McpSection-D88QlDpG.css +1 -0
  58. package/dist/core/web/public/next/assets/Meter--h3MmZS-.js +2 -0
  59. package/dist/core/web/public/next/assets/Meter--h3MmZS-.js.map +1 -0
  60. package/dist/core/web/public/next/assets/Meter-CLcr-4wS.css +1 -0
  61. package/dist/core/web/public/next/assets/{MutationTokenDialog-DbSHPy3w.js → MutationTokenDialog-DA8t97XT.js} +2 -2
  62. package/dist/core/web/public/next/assets/{MutationTokenDialog-DbSHPy3w.js.map → MutationTokenDialog-DA8t97XT.js.map} +1 -1
  63. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-C-PCgCzo.js → ResourcePoolConsoleApp-Bq7Vyud0.js} +2 -2
  64. package/dist/core/web/public/next/assets/{ResourcePoolConsoleApp-C-PCgCzo.js.map → ResourcePoolConsoleApp-Bq7Vyud0.js.map} +1 -1
  65. package/dist/core/web/public/next/assets/{RouteErrorBoundary-Dw8ZjmkS.js → RouteErrorBoundary-Badio_uO.js} +2 -2
  66. package/dist/core/web/public/next/assets/{RouteErrorBoundary-Dw8ZjmkS.js.map → RouteErrorBoundary-Badio_uO.js.map} +1 -1
  67. package/dist/core/web/public/next/assets/SettingsSection-BwrpQlpP.js +2 -0
  68. package/dist/core/web/public/next/assets/SettingsSection-BwrpQlpP.js.map +1 -0
  69. package/dist/core/web/public/next/assets/{UniverseConsoleApp-Bk5HipM0.js → UniverseConsoleApp-_FSohAdN.js} +2 -2
  70. package/dist/core/web/public/next/assets/{UniverseConsoleApp-Bk5HipM0.js.map → UniverseConsoleApp-_FSohAdN.js.map} +1 -1
  71. package/dist/core/web/public/next/assets/{UniverseView-D8k9q0ce.js → UniverseView-DqcXbed4.js} +2 -2
  72. package/dist/core/web/public/next/assets/{UniverseView-D8k9q0ce.js.map → UniverseView-DqcXbed4.js.map} +1 -1
  73. package/dist/core/web/public/next/assets/{UsageSection-B2E06ZH1.js → UsageSection-Bq6Daaby.js} +2 -2
  74. package/dist/core/web/public/next/assets/{UsageSection-B2E06ZH1.js.map → UsageSection-Bq6Daaby.js.map} +1 -1
  75. package/dist/core/web/public/next/assets/VerseConsoleApp-CMkCizvL.css +1 -0
  76. package/dist/core/web/public/next/assets/VerseConsoleApp-CsIQv9id.js +3 -0
  77. package/dist/core/web/public/next/assets/VerseConsoleApp-CsIQv9id.js.map +1 -0
  78. package/dist/core/web/public/next/assets/{charts-DSUpczxG.js → charts-CTZJ-JrH.js} +2 -2
  79. package/dist/core/web/public/next/assets/{charts-DSUpczxG.js.map → charts-CTZJ-JrH.js.map} +1 -1
  80. package/dist/core/web/public/next/assets/global-D6bTxIRn.js +2 -0
  81. package/dist/core/web/public/next/assets/global-D6bTxIRn.js.map +1 -0
  82. package/dist/core/web/public/next/assets/global-z-JfD3ow.css +1 -0
  83. package/dist/core/web/public/next/assets/{icons-BxOX8-XB.js → icons-D9vlf85u.js} +2 -2
  84. package/dist/core/web/public/next/assets/{icons-BxOX8-XB.js.map → icons-D9vlf85u.js.map} +1 -1
  85. package/dist/core/web/public/next/assets/{index-BMRIET7F.js → index-CZamKRUg.js} +3 -3
  86. package/dist/core/web/public/next/assets/{index-BMRIET7F.js.map → index-CZamKRUg.js.map} +1 -1
  87. package/dist/core/web/public/next/assets/{queries-AxnVa02h.js → queries-B8eBnFox.js} +2 -2
  88. package/dist/core/web/public/next/assets/{queries-AxnVa02h.js.map → queries-B8eBnFox.js.map} +1 -1
  89. package/dist/core/web/public/next/assets/{use-guarded-action-BO6c94Wp.js → use-guarded-action-bzrVVAYq.js} +2 -2
  90. package/dist/core/web/public/next/assets/{use-guarded-action-BO6c94Wp.js.map → use-guarded-action-bzrVVAYq.js.map} +1 -1
  91. package/dist/core/web/public/next/assets/workspace-model-v0a1gl-C.js +2 -0
  92. package/dist/core/web/public/next/assets/workspace-model-v0a1gl-C.js.map +1 -0
  93. package/dist/core/web/public/next/index.html +1 -1
  94. package/dist/release-dependency-inventory.json +1 -1
  95. package/package.json +1 -1
  96. package/dist/core/web/public/next/assets/AutonomySection-CRqHUhED.js +0 -2
  97. package/dist/core/web/public/next/assets/AutonomySection-CRqHUhED.js.map +0 -1
  98. package/dist/core/web/public/next/assets/ChatSection-5irrh6Jw.js +0 -80
  99. package/dist/core/web/public/next/assets/ChatSection-5irrh6Jw.js.map +0 -1
  100. package/dist/core/web/public/next/assets/ChatSection-LQiAn6Eu.css +0 -1
  101. package/dist/core/web/public/next/assets/SettingsSection-CWxtTNlD.js +0 -2
  102. package/dist/core/web/public/next/assets/SettingsSection-CWxtTNlD.js.map +0 -1
  103. package/dist/core/web/public/next/assets/VerseConsoleApp-CRfZUV-T.js +0 -3
  104. package/dist/core/web/public/next/assets/VerseConsoleApp-CRfZUV-T.js.map +0 -1
  105. package/dist/core/web/public/next/assets/VerseConsoleApp-D2E3mU9a.css +0 -1
  106. package/dist/core/web/public/next/assets/global-C4jfYHrj.js +0 -2
  107. package/dist/core/web/public/next/assets/global-C4jfYHrj.js.map +0 -1
  108. package/dist/core/web/public/next/assets/global-D463gG1X.css +0 -1
  109. package/dist/core/web/public/next/assets/workspace-model-cE4LkKpE.js +0 -2
  110. package/dist/core/web/public/next/assets/workspace-model-cE4LkKpE.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatSection-vNPIJffd.js","names":[],"sources":["../../../../../../src/web-ui/routes/verse/seat-subscription.ts","../../../../../../src/web-ui/routes/verse/SeatCapacity.module.css","../../../../../../src/web-ui/routes/verse/SeatCapacity.tsx","../../../../../../src/web-ui/routes/verse/Composer.module.css","../../../../../../src/web-ui/routes/verse/SeatSelector.tsx","../../../../../../src/web-ui/routes/verse/folder-picker.ts","../../../../../../src/web-ui/routes/verse/NewChatDialog.module.css","../../../../../../src/web-ui/routes/verse/NewChatDialog.tsx","../../../../../../src/web-ui/routes/verse/QuickSwitcher.module.css","../../../../../../src/web-ui/routes/verse/QuickSwitcher.tsx","../../../../../../src/web-ui/routes/verse/SessionRoots.module.css","../../../../../../src/web-ui/routes/verse/SessionRoots.tsx","../../../../../../src/web-ui/routes/verse/resources-collapse.ts","../../../../../../src/web-ui/routes/verse/verse-store.ts","../../../../../../src/web-ui/routes/verse/ResourcesPanel.module.css","../../../../../../src/web-ui/routes/verse/ResourcesPanel.tsx","../../../../../../src/web-ui/routes/verse/workspaces/SavedProjectDialog.module.css","../../../../../../src/web-ui/routes/verse/workspaces/SavedProjectDialog.tsx","../../../../../../src/web-ui/routes/verse/workspaces/SavedProjects.module.css","../../../../../../src/web-ui/routes/verse/workspaces/SavedProjects.tsx","../../../../../../src/web-ui/routes/verse/Sidebar.module.css","../../../../../../src/web-ui/routes/verse/Sidebar.tsx","../../../../../../src/web-ui/routes/verse/verse-events.ts","../../../../../../src/web-ui/routes/verse/useVerseSession.ts","../../../../../../src/web-ui/routes/verse/chat-panel-sizing.ts","../../../../../../src/web-ui/routes/verse/ChatResizer.tsx","../../../../../../src/web-ui/routes/verse/Workspace.module.css","../../../../../../src/web-ui/routes/verse/ContextMeter.tsx","../../../../../../src/web-ui/routes/verse/DictationButton.tsx","../../../../../../src/web-ui/routes/verse/Composer.tsx","../../../../../../src/web-ui/routes/verse/chat/line-diff.ts","../../../../../../src/web-ui/routes/verse/chat/tool-semantics.ts","../../../../../../src/web-ui/routes/verse/chat/turn-model.ts","../../../../../../src/web-ui/routes/verse/chat/chat.module.css","../../../../../../src/web-ui/routes/verse/chat/FileActivity.tsx","../../../../../../src/web-ui/routes/verse/chat/TranscriptNav.tsx","../../../../../../node_modules/dompurify/dist/purify.es.mjs","../../../../../../node_modules/marked/lib/marked.esm.js","../../../../../../src/web-ui/routes/verse/Transcript.module.css","../../../../../../src/web-ui/routes/verse/MessageMarkdown.tsx","../../../../../../src/web-ui/routes/verse/chat/ansi.ts","../../../../../../src/web-ui/routes/verse/chat/CommandOutput.tsx","../../../../../../src/web-ui/routes/verse/chat/DiffBlock.tsx","../../../../../../src/web-ui/routes/verse/ToolUseCard.tsx","../../../../../../src/web-ui/routes/verse/Transcript.tsx","../../../../../../src/web-ui/routes/verse/useSeatsRefresh.ts","../../../../../../src/web-ui/routes/verse/Workspace.tsx","../../../../../../src/web-ui/routes/verse/sections/ChatSection.module.css","../../../../../../src/web-ui/routes/verse/sections/ChatSection.tsx"],"sourcesContent":["/**\n * routes/verse/seat-subscription.ts — \"what subscription is behind this seat,\n * and how much of it is left\", projected ONCE for every chat surface that\n * shows a seat: the resources panel, the seat selector, the new-chat dialog,\n * the sidebar and the chat header.\n *\n * WHY THIS MODULE EXISTS\n *\n * The resources panel showed a bare \"unknown\" pill for every account — the\n * most-looked-at surface in the app. Measured against a live server,\n * `GET /api/verse/accounts` had all four accounts observed, Claude with three\n * windows and Grok with one, while `bootstrap.seats[].health` was `unknown`\n * forever for Claude and Grok: seat health came from a shared-evidence file\n * scoped `codex-native-metadata`, which structurally cannot carry those two\n * providers. The live data existed and was discarded at the last hop.\n *\n * Owner S's V2.1 contract fixes the supply side — `VerseSeat.capacity`\n * (core/verse/types.ts) now carries the plan, the binding window, the full\n * window list, credits, a usability verdict, the evidence source and the\n * provider's own notes. This module is the single place the chat surfaces\n * read it, so they cannot describe one seat four different ways.\n *\n * TWO SOURCES, ONE VIEW. `capacity` is `undefined` for local seats (an Ollama\n * tag has no subscription) and for a native seat the server could not build a\n * record for. The V1 `health.windows` shape is still read as the fallback, and\n * on that path the verdict is delegated WHOLESALE to\n * `verse-model.seatCapacity` — the seat selector and the composer's seat menu\n * already render those exact words, and two implementations of one rule is\n * how the picker and the panel would drift apart again.\n *\n * HONESTY RULES (docs/VERSE-TELEMETRY-V2.md, closing section) — every one is a\n * place where the obvious projection would lie:\n *\n * 1. THE BINDING WINDOW LEADS. An account is blocked by its WORST window, not\n * its first and not its average. Claude's weekly per-model window sat at\n * 100% while all-models read 58%; leading with 58% is a lie of emphasis.\n * 2. NO SIGNAL IS NOT ZERO. An unread window gets no meter at all. An empty\n * bar reads \"plenty left\" and a full one reads \"exhausted\"; both are false\n * when nothing was measured.\n * 3. THE SENTINEL 100 IS A FLAG. Codex writes `rateLimitReachedType` upstream\n * as the value 100. `measured: false` marks it; it renders as \"limit\n * reached\", never as \"100% used\", and carries no percentage.\n * 4. CREDITS ARE NOT THE WINDOW. A Codex account at 100% of its weekly window\n * with a spendable balance is still usable. The server already encodes\n * that in `usability: 'tight'`; this module reports both facts and never\n * collapses them into one.\n * 5. ONLY A MACHINE-READABLE INSTANT MAY BE FORMATTED. Claude's `resetsAt` is\n * structurally always null and its reset is provider prose; prose is\n * rendered VERBATIM, never parsed and never turned into a countdown.\n *\n * Pure: no React, no I/O.\n */\nimport type { VerseEngine, VerseSeat } from '../../data/api-types.js';\nimport {\n SEAT_CAPACITY_WORD,\n seatCapacity,\n seatUnavailableReason,\n seatWindowLabel,\n type SeatCapacityClass,\n} from './verse-model.js';\n\nexport type { SeatCapacityClass };\n\n/**\n * Owner S's shapes, reached through `VerseSeat` rather than imported by name.\n *\n * This is the drift guard, and it costs nothing: rename or reshape\n * `VerseSeatCapacity` in core/verse/types.ts and every read below stops\n * compiling HERE, at the seam, instead of silently degrading the panel back to\n * the \"unknown\" it was built to fix.\n */\ntype SeatCapacityRecord = NonNullable<VerseSeat['capacity']>;\ntype SeatCapacityWindow = SeatCapacityRecord['windows'][number];\n\n/** One quota window, in the shape every chat surface renders. */\nexport interface SeatWindowView {\n id: string;\n /** Human label, derived from the provider's id. */\n label: string;\n /**\n * 0–100, or null. Null means \"no reading\" OR \"the figure is a sentinel\".\n * NEVER a substituted zero, and a view must not draw a meter for it.\n */\n usedPercent: number | null;\n /** The provider flagged the limit instead of measuring it. */\n limitReached: boolean;\n /**\n * Reset text, ready to render: provider prose VERBATIM when that is what the\n * provider published, a formatted local time when — and only when — it gave\n * a machine-readable instant, null when it gave neither.\n */\n resetText: string | null;\n /**\n * The machine-readable reset instant (ISO), when there was one. The only\n * field a countdown could ever legitimately be derived from; nothing in the\n * chat surfaces derives one today.\n */\n resetsAt: string | null;\n}\n\nexport interface SeatSubscriptionView {\n /**\n * Local seats have no subscription, no quota and no bill — only a readiness\n * — and must not be dressed in meters that imply otherwise.\n */\n kind: 'subscription' | 'local';\n /** Plan tier as the provider names it: \"max\", \"pro\", \"SuperGrok\". */\n plan: string | null;\n cls: SeatCapacityClass;\n /** The class as a word. State is never communicated by colour alone. */\n word: string;\n /**\n * One short phrase for an option label, a pill title or a menu row —\n * \"92% of weekly fable window used\", \"primary window limit reached\".\n */\n summary: string;\n /** The window that actually constrains work. Null when nothing was read. */\n binding: SeatWindowView | null;\n /** Every other window, in provider order. */\n others: SeatWindowView[];\n /** Codex credits as a rendered phrase. Independent of the window. */\n credits: string | null;\n /** The provider's raw balance string, kept verbatim for a title attribute. */\n creditsTitle: string | null;\n /**\n * The provider's own plain-language facts. Owner S's contract says these\n * must be SHOWN rather than left to imply a fault, so they travel here and\n * the panel prints them.\n */\n notes: string[];\n /**\n * Where the windows came from, so nothing implies freshness it lacks.\n * Null on the V1 fallback path, which has no provenance to report.\n */\n evidenceSource: SeatCapacityRecord['evidenceSource'] | null;\n /** When the reading was taken, ISO. Null when nothing was observed. */\n observedAt: string | null;\n /** True when the seat carried owner S's `capacity` record. */\n extended: boolean;\n}\n\n/**\n * S's five-state verdict, mapped onto the four words this app already uses.\n *\n * `signed-out` is BLOCKED-by-action, not unread: we know exactly why there is\n * no capacity and what to do about it. `unknown` is the only genuinely unread\n * state — nobody told us anything, and calling that blocked would assert an\n * outage we never observed.\n *\n * Typed as a total map over S's union, so adding a verdict upstream fails the\n * build here rather than falling through to a silent default.\n */\nconst USABILITY_CLASS: Record<SeatCapacityRecord['usability'], SeatCapacityClass> = {\n ready: 'ready',\n tight: 'tight',\n exhausted: 'blocked',\n 'signed-out': 'blocked',\n unknown: 'unread',\n};\n\n/**\n * A machine-readable instant, formatted. Prose resets never reach this — they\n * are passed through untouched, because the provider's sentence already\n * carries the timezone it means and reformatting it would be a guess.\n */\nexport function formatResetInstant(iso: string): string | null {\n const at = new Date(iso);\n if (Number.isNaN(at.getTime())) return null;\n const clock = at.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });\n if (new Date().toDateString() === at.toDateString()) return `resets ${clock}`;\n return `resets ${at.toLocaleDateString([], { month: 'short', day: 'numeric' })} at ${clock}`;\n}\n\n/**\n * Window ids arrive provider-prefixed and sometimes doubly so\n * (`codex_codex_primary`, `grok_unified_weekly`). Strip the engine's own name\n * off the front before handing the rest to the shared labeller, so the panel\n * reads \"primary window\" rather than \"codex codex primary window\".\n *\n * Only the `capacity` path uses this. The V1 fallback goes through\n * `seatWindowLabel` unaltered, because the seat selector's wording is pinned\n * to it by test.\n */\nexport function seatCapacityWindowLabel(engine: VerseEngine, id: string): string {\n const prefix = `${engine}_`;\n let rest = id;\n while (rest.startsWith(prefix) && rest.length > prefix.length) rest = rest.slice(prefix.length);\n return seatWindowLabel(rest);\n}\n\nfunction toWindowView(engine: VerseEngine, w: SeatCapacityWindow): SeatWindowView {\n const reset = w.resetDescription ?? (w.resetsAt === null ? null : formatResetInstant(w.resetsAt));\n return {\n id: w.id,\n label: seatCapacityWindowLabel(engine, w.id),\n // A flagged limit, and any unmeasured figure, is a sentinel — not a reading.\n usedPercent: w.limitReached || !w.measured ? null : w.usedPercent,\n limitReached: w.limitReached,\n resetText: reset,\n resetsAt: w.resetsAt,\n };\n}\n\n/** The V1 `health.windows` shape, for a seat with no `capacity` record. */\nfunction legacyWindowView(w: VerseSeat['health']['windows'][number]): SeatWindowView {\n const used = typeof w.usedPercent === 'number' && Number.isFinite(w.usedPercent)\n ? Math.max(0, Math.min(100, w.usedPercent))\n : null;\n // Upstream writes a denial as 100, so on this shape a bare 100 cannot be\n // told apart from a measured 100 — and the safe reading of both is \"spent\".\n const flagged = used !== null && used >= 100;\n return {\n id: w.id,\n label: seatWindowLabel(w.id),\n usedPercent: flagged ? null : used,\n limitReached: flagged,\n resetText: w.resetsAt === null ? null : formatResetInstant(w.resetsAt),\n resetsAt: w.resetsAt,\n };\n}\n\nfunction creditsPhrase(credits: SeatCapacityRecord['credits']): { phrase: string | null; title: string | null } {\n if (credits === null) return { phrase: null, title: null };\n if (credits.unlimited) return { phrase: 'credits unlimited', title: null };\n if (!credits.hasCredits) return { phrase: null, title: null };\n if (credits.balance === null) return { phrase: 'credits available', title: null };\n const parsed = Number.parseFloat(credits.balance);\n if (!Number.isFinite(parsed)) return { phrase: 'credits available', title: credits.balance };\n // The provider publishes a long decimal (\"2048.4196250000\"). Two places is a\n // rendering choice, not a new number — the raw string rides in the title.\n return { phrase: `${parsed.toFixed(2)} credits left`, title: credits.balance };\n}\n\nfunction localView(seat: VerseSeat): SeatSubscriptionView {\n const unavailable = seatUnavailableReason(seat);\n const ready = seat.health.state === 'ready';\n const cls: SeatCapacityClass = unavailable !== null ? 'blocked' : ready ? 'ready' : 'unread';\n return {\n kind: 'local',\n plan: null,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary: unavailable ?? (ready ? 'runs on this machine' : 'readiness not reported'),\n binding: null,\n others: [],\n credits: null,\n creditsTitle: null,\n notes: seat.health.summary === null ? [] : [seat.health.summary],\n evidenceSource: null,\n observedAt: seat.health.observedAt,\n extended: false,\n };\n}\n\n/** The V1 path: no `capacity` record, so the V1 rule decides, unchanged. */\nfunction fallbackView(seat: VerseSeat): SeatSubscriptionView {\n const legacy = seatCapacity(seat);\n const windows = seat.health.windows.map(legacyWindowView);\n const flagged = windows.find((w) => w.limitReached) ?? null;\n const measured = windows.filter((w) => w.usedPercent !== null);\n const worst = measured.length === 0\n ? null\n : measured.reduce((a, b) => ((b.usedPercent ?? 0) > (a.usedPercent ?? 0) ? b : a));\n const binding = flagged ?? worst;\n const unavailable = seatUnavailableReason(seat);\n const cls = unavailable !== null ? 'blocked' : legacy.cls;\n return {\n kind: 'subscription',\n plan: null,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary: unavailable ?? legacy.text,\n binding,\n others: binding === null ? windows : windows.filter((w) => w.id !== binding.id),\n credits: null,\n creditsTitle: null,\n notes: [],\n evidenceSource: null,\n observedAt: seat.health.observedAt,\n extended: false,\n };\n}\n\n/**\n * The whole projection. Local seats short-circuit: they have no subscription,\n * so everything below the readiness line is deliberately empty rather than\n * zeroed.\n */\nexport function seatSubscription(seat: VerseSeat): SeatSubscriptionView {\n if (seat.engine === 'local') return localView(seat);\n const capacity = seat.capacity;\n if (capacity === undefined) return fallbackView(seat);\n\n const windows = capacity.windows.map((w) => toWindowView(seat.engine, w));\n // Resolve the server's CHOICE of binding window back to this seat's own\n // view of it, so the two can never disagree about a reset or a label.\n const served = capacity.binding;\n const binding = served === null\n ? null\n : (windows.find((w) => w.id === served.id) ?? toWindowView(seat.engine, served));\n const others = binding === null ? windows : windows.filter((w) => w.id !== binding.id);\n const credits = creditsPhrase(capacity.credits);\n\n const unavailable = seatUnavailableReason(seat);\n const cls: SeatCapacityClass = unavailable !== null ? 'blocked' : USABILITY_CLASS[capacity.usability];\n\n let summary: string;\n // Signed out is checked FIRST, before the generic unavailable reason: owner\n // S maps `signed-out` onto `health.state: 'unavailable'` (it is the one\n // account state worth a red dot, because it has a remedy), and the generic\n // reason there is a bare \"seat unavailable\" that says nothing about the fix.\n // A signed-out account has no measurement at all — it is an action, never a\n // 0% meter and never a bare \"unknown\".\n if (capacity.usability === 'signed-out') {\n summary = 'signed out — reconnect this account';\n } else if (unavailable !== null) {\n summary = unavailable;\n } else if (binding === null) {\n summary = 'no capacity reading';\n } else if (binding.limitReached) {\n // The server already weighed credits against the spent window; `tight`\n // there means \"spent, but there is still something to spend\".\n summary = capacity.usability === 'tight' && credits.phrase !== null\n ? `${binding.label} limit reached · credits still spendable`\n : `${binding.label} limit reached`;\n } else if (binding.usedPercent === null) {\n summary = 'no capacity reading';\n } else {\n summary = `${Math.round(binding.usedPercent)}% of ${binding.label} used`;\n }\n\n return {\n kind: 'subscription',\n plan: capacity.planType,\n cls,\n word: SEAT_CAPACITY_WORD[cls],\n summary,\n binding,\n others,\n credits: credits.phrase,\n creditsTitle: credits.title,\n notes: [...capacity.notes],\n evidenceSource: capacity.evidenceSource,\n observedAt: capacity.observedAt ?? seat.health.observedAt,\n extended: true,\n };\n}\n\n/**\n * How much of a freshness claim the evidence supports. A reading served from\n * another process's shared file, or from an operator-seeded baseline, is not\n * a live probe and must not be presented as one.\n */\nexport function evidenceNote(source: SeatSubscriptionView['evidenceSource']): string | null {\n switch (source) {\n case 'collector':\n return null;\n case 'shared-evidence':\n return 'read from another collector’s shared evidence, not probed here';\n case 'baseline':\n return 'operator-seeded baseline, not a live reading';\n case 'none':\n return 'no evidence source — nothing here was measured';\n default:\n return null;\n }\n}\n\n/**\n * One sentence for a `title` attribute or a screen-reader name: the seat, its\n * plan, its verdict and the evidence behind it.\n */\nexport function seatSubscriptionSentence(seat: VerseSeat, view: SeatSubscriptionView): string {\n const parts = [seat.label];\n if (view.plan !== null) parts.push(view.plan);\n parts.push(view.word);\n parts.push(view.summary);\n if (view.credits !== null) parts.push(view.credits);\n if (view.binding?.resetText != null) parts.push(view.binding.resetText);\n return parts.join(' · ');\n}\n\n/** Tight and blocked are worth surfacing outside the panel; the rest is noise. */\nexport function worthFlagging(cls: SeatCapacityClass): boolean {\n return cls === 'tight' || cls === 'blocked';\n}\n","/* Shared capacity rendering: the verdict chip, one quota window, and the\n single-seat note. Hairlines and whitespace only — no nested boxes.\n\n Every colour here is paired with a word and a glyph (DESIGN-V2 §6), and\n every `--status-*-fg` token is defined on bare :root AND retuned for dark,\n so both themes hold the 4.5:1 floor without a rule of their own. */\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n flex: none;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n font-weight: var(--font-weight-medium);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--status-unknown-fg);\n white-space: nowrap;\n}\n.chipGlyph {\n font-family: var(--font-ui);\n font-size: 10px;\n line-height: 1;\n letter-spacing: 0;\n}\n.chip[data-capacity='ready'] { color: var(--status-success-fg); }\n.chip[data-capacity='tight'] { color: var(--status-warning-fg); }\n.chip[data-capacity='blocked'] { color: var(--status-danger-fg); }\n.chip[data-capacity='unread'] { color: var(--status-unknown-fg); }\n\n/* ---- one quota window -------------------------------------------------- */\n\n.window,\n.windowLead {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n/* The binding constraint leads: same meter, one step more present. */\n.windowLead .windowLabel { color: var(--text-primary); }\n.windowLead .pct { color: var(--text-primary); }\n\n.windowLabel {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n color: var(--text-secondary);\n}\n.pct {\n font-variant-numeric: tabular-nums;\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n color: var(--text-secondary);\n}\n.flag {\n font-family: var(--font-ui);\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n font-weight: var(--font-weight-medium);\n color: var(--status-danger-fg);\n white-space: nowrap;\n}\n\n.unknownHead {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-2);\n min-width: 0;\n}\n.unknownValue {\n flex: none;\n font-family: var(--font-ui);\n font-style: italic;\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n color: var(--status-unknown-fg);\n}\n/* Absence drawn as absence — a dashed rule, never a 0% bar. */\n.unknownRule {\n width: 100%;\n height: 0;\n margin: 3px 0 0;\n border: 0;\n border-top: 1px dashed var(--border-strong);\n}\n\n.reset {\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n color: var(--text-tertiary);\n}\n\n/* ---- single-seat note -------------------------------------------------- */\n\n.note {\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n min-width: 0;\n}\n.noteHead {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-1) var(--space-2);\n min-width: 0;\n}\n.plan {\n flex: none;\n padding: 0 var(--space-1);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-xs);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.noteSummary {\n flex: 1 1 100%;\n min-width: 0;\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n color: var(--text-secondary);\n}\n.credits {\n margin: 0;\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n color: var(--text-tertiary);\n}\n","/**\n * routes/verse/SeatCapacity.tsx — the shared rendering of a seat's\n * subscription capacity, so the resources panel, the new-chat dialog and the\n * chat header cannot describe the same seat three different ways.\n *\n * Three pieces, each one a rule from docs/VERSE-DESIGN-V2.md §6 and\n * docs/VERSE-TELEMETRY-V2.md made concrete:\n *\n * <CapacityChip> the four-word verdict. Always the WORD, never colour\n * alone; the dot is decoration on top of the word.\n * <SeatWindowMeter> one quota window. A measured window gets a real\n * <Meter>; a flagged limit gets a full danger meter\n * labelled \"limit reached\" and NO percentage, because\n * the sentinel 100 upstream is a flag rather than a\n * reading; an unread window gets a dashed rule and a\n * sentence, never a bar — an empty bar reads \"plenty\n * left\" and a full one reads \"exhausted\", and both are\n * lies when nothing was measured.\n * <SeatCapacityNote> plan · verdict · binding meter · reset · credits, for\n * the surfaces that show one seat at a time.\n *\n * Reset text is rendered VERBATIM. Claude publishes a sentence\n * (\"resets Sep 25 at 7pm (America/New_York)\") and `resetsAt` is structurally\n * null for it, so nothing here parses a reset or turns one into a countdown.\n */\nimport type { ReactNode } from 'react';\nimport type { VerseSeat } from '../../data/api-types.js';\nimport { Meter } from '../../components/primitives/Meter.js';\nimport {\n seatSubscription,\n type SeatCapacityClass,\n type SeatSubscriptionView,\n type SeatWindowView,\n} from './seat-subscription.js';\nimport styles from './SeatCapacity.module.css';\n\n/**\n * A glyph per class so the state survives greyscale, a colour-blind reader\n * and a screenshot: check (usable), half (tight), bar (blocked), query\n * (no reading). Paired with the word, never standing in for it.\n */\nconst CLASS_GLYPH: Record<SeatCapacityClass, string> = {\n ready: '✓',\n tight: '◑',\n blocked: '▮',\n unread: '?',\n};\n\nexport function CapacityChip({\n view,\n title,\n}: {\n view: SeatSubscriptionView;\n title?: string;\n}): ReactNode {\n return (\n <span className={styles.chip} data-capacity={view.cls} title={title ?? view.summary}>\n <span className={styles.chipGlyph} aria-hidden=\"true\">{CLASS_GLYPH[view.cls]}</span>\n {view.word}\n </span>\n );\n}\n\nexport function SeatWindowMeter({\n windowView,\n ariaPrefix,\n prominent = false,\n}: {\n windowView: SeatWindowView;\n /** Seat label, so every meter on the page has a unique accessible name. */\n ariaPrefix: string;\n /** The binding window — the one that actually constrains work. */\n prominent?: boolean;\n}): ReactNode {\n const name = `${ariaPrefix} ${windowView.label}`;\n\n if (windowView.limitReached) {\n return (\n <div className={prominent ? styles.windowLead : styles.window}>\n <Meter\n value={100}\n max={100}\n tone=\"danger\"\n label={<span className={styles.windowLabel}>{windowView.label}</span>}\n valueText={<span className={styles.flag}>limit reached</span>}\n aria-label={`${name}: the provider flagged this window as rate-limited, so no percentage was measured`}\n />\n {windowView.resetText === null ? null : <p className={styles.reset}>{windowView.resetText}</p>}\n </div>\n );\n }\n\n if (windowView.usedPercent === null) {\n return (\n <div className={prominent ? styles.windowLead : styles.window}>\n <div className={styles.unknownHead}>\n <span className={styles.windowLabel}>{windowView.label}</span>\n <span className={styles.unknownValue}>no reading</span>\n </div>\n {/* Absence, drawn as absence. Never a 0% bar. */}\n <hr className={styles.unknownRule} aria-hidden=\"true\" />\n {windowView.resetText === null ? null : <p className={styles.reset}>{windowView.resetText}</p>}\n </div>\n );\n }\n\n const pct = Math.round(windowView.usedPercent);\n return (\n <div className={prominent ? styles.windowLead : styles.window}>\n <Meter\n value={pct}\n max={100}\n label={<span className={styles.windowLabel}>{windowView.label}</span>}\n valueText={<span className={styles.pct}>{pct}%</span>}\n aria-label={`${name} used`}\n />\n {windowView.resetText === null ? null : <p className={styles.reset}>{windowView.resetText}</p>}\n </div>\n );\n}\n\n/**\n * One seat's capacity in a few lines, for the surfaces that show a single\n * seat: the new-chat dialog under the picker, and anywhere else a choice is\n * about to be made. Local seats say so instead of being given meters.\n */\nexport function SeatCapacityNote({ seat, className }: { seat: VerseSeat; className?: string }): ReactNode {\n const view = seatSubscription(seat);\n return (\n <div className={`${styles.note} ${className ?? ''}`} data-capacity={view.cls}>\n <div className={styles.noteHead}>\n <CapacityChip view={view} />\n {view.plan === null ? null : <span className={styles.plan}>{view.plan}</span>}\n <span className={styles.noteSummary}>{view.summary}</span>\n </div>\n {view.binding === null ? null : (\n <SeatWindowMeter windowView={view.binding} ariaPrefix={seat.label} prominent />\n )}\n {view.credits === null ? null : (\n <p className={styles.credits} title={view.creditsTitle ?? undefined}>\n {view.credits} — credits are independent of the window\n </p>\n )}\n </div>\n );\n}\n","/**\n * The composer: one measure with the transcript (720px), a hairline that\n * takes the accent on focus, and a single control row. No inner card.\n */\n.composer {\n flex-shrink: 0;\n padding: 0 var(--space-6) var(--space-4);\n background: var(--bg-surface);\n}\n.box {\n width: 100%;\n max-width: var(--measure-read);\n margin: 0 auto;\n border: 1px solid var(--border-default);\n border-radius: var(--radius-md);\n background: var(--bg-input);\n transition: border-color var(--duration-fast) var(--ease-standard);\n}\n/* The accent edge replaces the global focus ring FOR THE TEXTAREA, which\n suppresses its own (a ring inside the box would double up).\n `:has(> .textarea:focus)` rather than `:focus-within`, because the box also\n contains the seat pill, the mic and Send/Stop: with `:focus-within`, tabbing\n to Send lit the whole composer — saying \"you are typing here\", which is\n false — and painted the global focus ring on the button inside it, giving\n two concentric accent rings. It also fired on mouse-down on those buttons,\n where `:focus-visible` deliberately would not. */\n.box:has(> .textarea:focus) { border-color: var(--accent-500); box-shadow: 0 0 0 1px var(--accent-500); }\n.boxListening { border-color: var(--status-running-solid); }\n\n.textarea {\n display: block;\n width: 100%;\n min-height: calc(var(--control-h) + var(--space-2));\n max-height: 40vh;\n resize: none;\n padding: var(--space-3) var(--space-3) var(--space-1);\n border: 0;\n background: transparent;\n color: var(--text-primary);\n font-size: var(--text-base-size);\n line-height: var(--text-base-line-relaxed);\n}\n.textarea::placeholder { color: var(--text-tertiary); }\n.textarea:focus-visible { box-shadow: none; outline: none; }\n.textarea:disabled { color: var(--text-secondary); cursor: not-allowed; }\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--space-1);\n padding: var(--space-1) var(--space-2) var(--space-2) var(--space-2);\n}\n.spacer { flex: 1; }\n\n/* ---- engine identity --------------------------------------------------- */\n.engine-claude { --verse-engine: var(--engine-claude, #c96442); }\n.engine-codex { --verse-engine: var(--engine-codex, #10a37f); }\n.engine-grok { --verse-engine: var(--engine-grok, #6b7280); }\n.engine-local { --verse-engine: var(--engine-local, #7c5cff); }\n.engineDot {\n flex-shrink: 0;\n width: 5px;\n height: 5px;\n border-radius: var(--radius-full);\n background: var(--verse-engine, var(--text-tertiary));\n}\n\n/* ---- seat selector (new-chat dialog) ----------------------------------- */\n.seatField { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }\n.seatFieldCompact { flex-direction: row; align-items: center; max-width: 320px; }\n.fieldLabel { font-size: var(--text-sm-size); font-weight: var(--font-weight-medium); color: var(--text-primary); }\n.seatSelect {\n width: 100%;\n min-height: var(--control-h);\n max-width: 100%;\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-input);\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n text-overflow: ellipsis;\n}\n.seatSelect:hover:not(:disabled) { border-color: var(--border-strong); }\n.seatSelect:disabled { opacity: 0.6; cursor: not-allowed; }\n.seatFieldCompact .seatSelect { min-height: var(--control-h-sm); font-size: var(--text-xs-size); border-color: transparent; background: transparent; }\n\n/* ---- seat pill (read-only) + menu -------------------------------------- */\n.seatPillWrap { position: relative; display: inline-flex; min-width: 0; }\n.seatPill {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n max-width: 34ch;\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border-radius: var(--radius-xs);\n color: var(--text-secondary);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-medium);\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.seatPill:hover:not(:disabled),\n.seatPill[aria-expanded='true'] { background: var(--bg-hover); color: var(--text-primary); }\n.seatPill:active:not(:disabled) { background: var(--bg-active); }\n.seatPill:disabled { opacity: 0.6; cursor: not-allowed; }\n.seatPillText { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.seatMenu {\n position: absolute;\n bottom: calc(100% + var(--space-2));\n left: 0;\n z-index: var(--z-dropdown);\n min-width: 260px;\n max-width: 360px;\n padding: var(--space-1);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-surface-raised);\n color: var(--text-primary);\n box-shadow: var(--shadow-menu, var(--shadow-md));\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.seatMenuHeading {\n margin: 0 0 var(--space-1);\n padding: var(--space-2) var(--space-2) var(--space-2);\n border-bottom: 1px solid var(--border-subtle);\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n.seatMenuHeading strong { color: var(--text-primary); font-weight: var(--font-weight-medium); }\n.seatMenuEmpty { margin: 0; padding: var(--space-2); font-size: var(--text-xs-size); color: var(--text-tertiary); }\n.seatMenuItem {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n width: 100%;\n padding: var(--space-2);\n border-radius: var(--radius-xs);\n text-align: left;\n color: var(--text-primary);\n}\n.seatMenuItem:hover,\n.seatMenuItem:focus-visible { background: var(--bg-hover); }\n.seatMenuItem:active { background: var(--bg-active); }\n.seatMenuText { display: flex; flex-direction: column; gap: 1px; min-width: 0; }\n.seatMenuPrimary { font-size: var(--text-sm-size); }\n.seatMenuSecondary { font-size: var(--text-2xs-size, 11px); color: var(--text-tertiary); }\n\n/* The seat's capacity, at the point the seat is chosen. The WORD carries the\n state and the tint is a second channel, never the only one (DESIGN-V2 §6);\n `blocked` is marked, not disabled, because a spent window can still have\n credits behind it (docs/VERSE-TELEMETRY-V2.md). */\n.seatMenuCapacity {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n.seatMenuItem[data-capacity='tight'] .seatMenuCapacity { color: var(--status-warning-fg); }\n.seatMenuItem[data-capacity='blocked'] .seatMenuCapacity { color: var(--status-danger-fg); }\n\n/* ---- dictation --------------------------------------------------------- */\n.dictationWrap { position: relative; display: inline-flex; align-items: center; }\n.dictation {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--control-h-sm);\n height: var(--control-h-sm);\n border-radius: var(--radius-xs);\n color: var(--text-tertiary);\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.dictation:hover:not(:disabled) { background: var(--bg-hover); color: var(--text-primary); }\n.dictation:active:not(:disabled) { background: var(--bg-active); }\n.dictation:disabled { opacity: 0.45; cursor: not-allowed; }\n.dictationLive { color: var(--status-running-fg); background: var(--status-running-bg); }\n.dictationPulse {\n position: absolute;\n inset: -2px;\n border-radius: var(--radius-sm);\n border: 1px solid var(--status-running-solid);\n animation: verse-ring 1.4s ease-out infinite;\n pointer-events: none;\n}\n/* `.dictationHint` lived here: a hand-rolled tooltip that sat in the DOM\n permanently at opacity 0, anchored to a wrapper that is itself inside the\n composer's overflow, and revealed by a :hover rule. It is gone — the\n Tooltip primitive carries the hint now, mounted only while open, so it can\n neither be clipped by an ancestor nor left painted over the panel beside\n it. */\n.dictationError { margin-left: var(--space-2); font-size: var(--text-xs-size); color: var(--status-danger-fg); }\n\n/* ---- send / stop ------------------------------------------------------- */\n.send,\n.stop {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid transparent;\n border-radius: var(--radius-sm);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);\n}\n.send { background: var(--accent-600); color: var(--accent-contrast); }\n.send:hover:not(:disabled) { background: var(--accent-700); }\n.send:active:not(:disabled) { background: var(--accent-700); border-color: var(--accent-700); }\n.send:disabled { opacity: 0.4; cursor: not-allowed; }\n.stop { border-color: var(--border-default); color: var(--text-primary); }\n.stop:hover { border-color: var(--status-danger-solid); color: var(--status-danger-fg); }\n.stop:active { background: var(--status-danger-bg); }\n.stopIcon { width: 8px; height: 8px; border-radius: 1px; background: currentColor; }\n\n/* ---- hint row ---------------------------------------------------------- */\n.help {\n max-width: var(--measure-read);\n margin: var(--space-2) auto 0;\n min-height: var(--text-2xs-line);\n font-size: var(--text-2xs-size, 11px);\n line-height: 1.4;\n color: var(--text-tertiary);\n}\n.helpQuiet { min-height: 0; margin-top: 0; }\n.help kbd {\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size, 11px);\n padding: 0 3px;\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n color: var(--text-secondary);\n}\n.helpError { color: var(--status-danger-fg); }\n\n@keyframes verse-ring {\n 0% { opacity: 0.9; transform: scale(0.94); }\n 100% { opacity: 0; transform: scale(1.35); }\n}\n/* Two triggers, the same pattern as the duration tokens in tokens.css and the\n shimmer in global.css: the OS preference applies unless Settings explicitly\n asked for full motion, and data-motion=\"reduce\" forces it on for an operator\n whose OS says nothing. A persistent `animation` has a hardcoded duration, so\n collapsing --duration-* does NOT reach it — it needs both rules by name. */\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .dictationPulse { animation: none; }\n}\n:root[data-motion=\"reduce\"] .dictationPulse { animation: none; }\n@media (max-width: 900px) {\n .composer { padding: 0 var(--space-4) var(--space-3); }\n}\n@media (max-width: 640px) {\n .row { flex-wrap: wrap; }\n .seatPill { max-width: 100%; }\n .textarea { font-size: 16px; }\n}\n\n/* ---- pre-send cost hint ------------------------------------------------- */\n/* Only rendered once the session is past the ContextMeter's warn threshold,\n so a normal message shows nothing at all. The figure is an ESTIMATE and\n says so: `≈` in the number, the full caveat in the accessible text. */\n.cost {\n max-width: var(--measure-read);\n margin: var(--space-2) auto 0;\n padding-left: var(--space-3);\n border-left: 2px solid var(--status-warning-solid);\n color: var(--text-secondary);\n /* Prose, not a micro-label: tokens.css sets the body floor at 12px and\n reserves --text-2xs for uppercase labels and keyboard hints. */\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n.cost[data-tone='danger'] { border-left-color: var(--status-danger-solid); }\n.costFigure {\n font-family: var(--font-display);\n font-variant-numeric: tabular-nums;\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n}\n","/**\n * routes/verse/SeatSelector.tsx — grouped seat/model picker. A native\n * <select> with one <optgroup> per engine (Claude · Codex · Grok · Local)\n * and one option per seat×model; seats whose health is `unavailable` are\n * disabled with the reason in the label (and `title`), so the operator sees\n * why rather than just a greyed row. Value is `[seatId, modelId]` JSON so\n * ids containing ':' or '/' can never collide.\n *\n * Every option also carries its seat's CAPACITY (`seat-subscription.ts`).\n * Without it an exhausted seat was indistinguishable from a fresh one here:\n * the only annotation was `seatUnavailableReason`, which fires solely on\n * `health.state === 'unavailable'`, and Claude's health is `unknown` BY\n * CONSTRUCTION (docs/VERSE-TELEMETRY-V2.md). A Claude seat whose binding\n * weekly window read 100% used therefore appeared as an ordinary, enabled,\n * unannotated choice, and the exhaustion was discovered at turn time — the\n * exact failure the Usage section exists to prevent.\n *\n * The annotation reads `plan · word · binding phrase` — the plan tier only\n * when the provider published one, so nothing is invented for a seat whose\n * subscription was never read.\n *\n * A `blocked` seat is MARKED but stays selectable: a used-up window can\n * coexist with a spendable credit balance, so refusing the choice would be a\n * stronger claim than the data supports.\n */\nimport { useId } from 'react';\nimport type { VerseSeat } from '../../data/api-types.js';\nimport { seatSubscription } from './seat-subscription.js';\nimport { ENGINE_LABEL, groupSeats, seatUnavailableReason } from './verse-model.js';\nimport styles from './Composer.module.css';\n\nexport interface SeatChoice {\n seatId: string;\n model: string;\n}\n\nexport interface SeatSelectorProps {\n seats: readonly VerseSeat[];\n value: SeatChoice | null;\n onChange: (choice: SeatChoice) => void;\n disabled?: boolean;\n label?: string;\n id?: string;\n compact?: boolean;\n}\n\nexport function encodeSeatChoice(choice: SeatChoice): string {\n return JSON.stringify([choice.seatId, choice.model]);\n}\n\nexport function decodeSeatChoice(value: string): SeatChoice | null {\n try {\n const parsed = JSON.parse(value) as unknown;\n if (!Array.isArray(parsed) || parsed.length !== 2) return null;\n const [seatId, model] = parsed as [unknown, unknown];\n if (typeof seatId !== 'string' || typeof model !== 'string') return null;\n return { seatId, model };\n } catch {\n return null;\n }\n}\n\n/** First selectable seat (ready/degraded/unknown) with its default model. */\nexport function defaultSeatChoice(seats: readonly VerseSeat[]): SeatChoice | null {\n for (const group of groupSeats(seats)) {\n for (const seat of group.seats) {\n if (seat.health.state === 'unavailable' || seat.models.length === 0) continue;\n return { seatId: seat.id, model: seat.models[0]!.id };\n }\n }\n return null;\n}\n\nexport function SeatSelector({ seats, value, onChange, disabled = false, label = 'Seat and model', id, compact = false }: SeatSelectorProps) {\n const generated = useId();\n const selectId = id ?? generated;\n const groups = groupSeats(seats);\n const current = value ? encodeSeatChoice(value) : '';\n const known = value && seats.some((s) => s.id === value.seatId && s.models.some((m) => m.id === value.model));\n return (\n <label className={`${styles.seatField} ${compact ? styles.seatFieldCompact : ''}`} htmlFor={selectId}>\n <span className={compact ? 'visually-hidden' : styles.fieldLabel}>{label}</span>\n <select id={selectId} className={styles.seatSelect} value={known ? current : ''} disabled={disabled || groups.length === 0}\n aria-label={compact ? label : undefined}\n onChange={(event) => {\n const choice = decodeSeatChoice(event.target.value);\n if (choice) onChange(choice);\n }}>\n {!known ? <option value=\"\" disabled>{groups.length === 0 ? 'No seats discovered' : 'Choose a seat…'}</option> : null}\n {groups.map((group) => (\n <optgroup key={group.engine} label={ENGINE_LABEL[group.engine]}>\n {group.seats.flatMap((seat) => {\n const reason = seatUnavailableReason(seat);\n const capacity = seatSubscription(seat);\n // `unread` is left unsaid: \"no reading\" on every Claude row\n // would be noise, and the absent figure already says it. A local\n // seat is left unsaid too — it has no subscription to report,\n // and its readiness is already carried by the disabled state.\n const note =\n reason !== null\n ? `unavailable: ${reason}`\n : capacity.cls === 'unread' || capacity.kind === 'local'\n ? null\n : `${capacity.plan === null ? '' : `${capacity.plan} · `}${capacity.word} · ${capacity.summary}`;\n // The label reads inline after the model name, so it stays\n // lowercase; the tooltip stands alone, so it is sentence case.\n const title = note === null ? undefined : note.charAt(0).toUpperCase() + note.slice(1);\n return seat.models.map((model) => (\n <option key={encodeSeatChoice({ seatId: seat.id, model: model.id })} value={encodeSeatChoice({ seatId: seat.id, model: model.id })}\n disabled={reason !== null} title={title}>\n {seat.label} — {model.label}{note ? ` (${note})` : ''}\n </option>\n ));\n })}\n </optgroup>\n ))}\n </select>\n </label>\n );\n}\n","/**\n * routes/verse/folder-picker.ts — the native \"choose a folder\" door.\n *\n * WHY THIS EXISTS. Until now the only way to start a chat in a folder that is\n * not already enrolled was to *type* an absolute path into a text input\n * (NewChatDialog). Every comparable desktop app opens a real directory\n * chooser. This module is that chooser, and nothing else: it resolves to an\n * absolute path or to `null`, and the caller decides what to do with either.\n *\n * WHY IT IS FEATURE-PROBED AND NOT BUILD-FLAGGED. The very same JS bundle is\n * served two ways:\n *\n * 1. Inside the Tauri shell (desktop/), where the Verse window points at\n * http://127.0.0.1:7777/verse/ and Tauri injects its IPC bridge.\n * 2. By `ashlr verse` in a plain browser, where there is no shell at all.\n *\n * A build-time constant cannot tell those apart — it is one artifact. So the\n * shell is detected at *call* time by probing the injected global, exactly the\n * way desktop/src-tauri/src/shell_contract.js already does. In a browser the\n * probe simply finds nothing: `nativePickerAvailable()` is false and\n * `pickDirectory()` resolves `null` without throwing, so the caller keeps its\n * text input.\n *\n * WHY WE CALL THE IPC COMMAND DIRECTLY. The web UI does not depend on\n * `@tauri-apps/api` (it is not in package.json, and adding it would pull a\n * desktop-only SDK into the browser bundle). `plugin:dialog|open` is the same\n * command `@tauri-apps/plugin-dialog`'s `open()` invokes; going straight to it\n * keeps the browser build free of Tauri code.\n *\n * NATIVE SIDE. The command only answers if all three of these are true:\n * - `tauri-plugin-dialog` is in desktop/src-tauri/Cargo.toml,\n * - it is registered in main.rs (`tauri_plugin_dialog::init()`), and\n * - `dialog:allow-open` is granted to the *remote* Verse origin, in\n * desktop/src-tauri/capabilities/verse-remote.json — the Verse page is a\n * remote URL, so a capability without a `remote` block does not reach it.\n * A missing permission is rejected at the IPC boundary, which is why every\n * failure here is caught and reported as `null` rather than thrown.\n *\n * Pure aside from the one IPC call. No React.\n */\n\n/** The IPC command `@tauri-apps/plugin-dialog`'s `open()` invokes. */\nconst DIALOG_OPEN_COMMAND = 'plugin:dialog|open';\n\n/** Shown as the chooser's window title on platforms that use one. */\nconst DIALOG_TITLE = 'Choose a project folder';\n\n/**\n * Tauri 2 injects this into every webview it owns, remote origins included.\n * Only the one method we need is modelled; the real object has far more.\n */\ntype TauriInvoke = (command: string, args?: unknown) => unknown;\n\ninterface TauriBridge {\n invoke: TauriInvoke;\n}\n\ninterface TauriGlobals {\n /** Always present inside a Tauri 2 webview. */\n __TAURI_INTERNALS__?: { invoke?: unknown };\n /** Present only when `app.withGlobalTauri` is on. Probed as a fallback. */\n __TAURI__?: { core?: { invoke?: unknown } };\n}\n\n/**\n * The live IPC bridge, or `null` when this code is not running inside the\n * Tauri shell. Re-read on every call on purpose: the global is injected by an\n * initialization script, and nothing guarantees this module was evaluated\n * after it.\n */\nfunction tauriBridge(): TauriBridge | null {\n // `globalThis` rather than `window` so this is also safe under a non-DOM\n // module graph (SSR, a node-environment test) instead of throwing.\n const globals = globalThis as unknown as TauriGlobals;\n\n const internal = globals.__TAURI_INTERNALS__?.invoke;\n if (typeof internal === 'function') return { invoke: internal as TauriInvoke };\n\n const global = globals.__TAURI__?.core?.invoke;\n if (typeof global === 'function') return { invoke: global as TauriInvoke };\n\n return null;\n}\n\n/** True when a native directory picker is reachable (i.e. running inside the Tauri shell). */\nexport function nativePickerAvailable(): boolean {\n return tauriBridge() !== null;\n}\n\n/** Opens the native directory chooser. Resolves to an absolute path, or null if the user cancelled. */\nexport async function pickDirectory(): Promise<string | null> {\n const bridge = tauriBridge();\n if (!bridge) return null;\n\n try {\n // Arg shape mirrors @tauri-apps/plugin-dialog: the Rust command takes a\n // single `options` parameter. `multiple: false` keeps the answer a scalar,\n // though normalisePickedPath does not rely on that.\n const raw = await bridge.invoke(DIALOG_OPEN_COMMAND, {\n options: {\n directory: true,\n multiple: false,\n recursive: false,\n title: DIALOG_TITLE,\n },\n });\n return normalisePickedPath(raw);\n } catch {\n // A rejected IPC call means the shell said no — the permission is not\n // granted, the plugin is not registered, or the dialog failed to open.\n // None of those are the caller's problem: it falls back to typing a path.\n return null;\n }\n}\n\n/** Depth cap for the unwrapping below, so a self-referential reply cannot spin. */\nconst MAX_UNWRAP_DEPTH = 4;\n\n/**\n * Reduce whatever the dialog plugin returned to one plain absolute path.\n *\n * The shapes seen across plugin versions and platforms:\n * - `\"/Users/me/project\"` — the common case\n * - `null` / `undefined` — the user cancelled\n * - `[\"/Users/me/project\"]` — an array even for multiple:false\n * - `{ path: \"/Users/me/project\" }` — the FileResponse-style wrapper\n * - `\"file:///Users/me/my%20project\"` — a URL-ish value needing decoding\n * Anything else — a number, an empty array, a relative path — is malformed and\n * becomes `null`. A half-understood path is worse than no path: the caller\n * would hand it to the backend as a session root.\n */\nfunction normalisePickedPath(value: unknown, depth = 0): string | null {\n if (depth > MAX_UNWRAP_DEPTH) return null;\n\n if (Array.isArray(value)) {\n return value.length > 0 ? normalisePickedPath(value[0], depth + 1) : null;\n }\n\n if (value !== null && typeof value === 'object') {\n const path = (value as { path?: unknown }).path;\n return typeof path === 'string' ? normalisePickedPath(path, depth + 1) : null;\n }\n\n if (typeof value !== 'string') return null;\n\n const decoded = decodeFileUrl(value.trim());\n if (!decoded) return null;\n // A NUL cannot occur in a real path and would truncate it in any C API it\n // eventually reaches.\n if (decoded.includes('\\0')) return null;\n return isAbsolutePath(decoded) ? decoded : null;\n}\n\n/**\n * Turn `file:///Users/me/my%20project` into `/Users/me/my project`, and leave\n * a plain path untouched. Any other scheme (http:, data:, …) is not a local\n * folder and is rejected.\n */\nfunction decodeFileUrl(value: string): string | null {\n if (value === '') return null;\n // No scheme marker at all: already a plain path, hand it back untouched.\n if (!/^[A-Za-z][A-Za-z0-9+.-]*:/.test(value)) return value;\n // `C:\\Users\\me` also matches the scheme shape (one letter, then a colon), so\n // the drive-letter case is rescued here before anything is rejected.\n if (/^[A-Za-z]:[\\\\/]/.test(value)) return value;\n if (!/^file:\\/\\//i.test(value)) return null;\n\n let pathname: string;\n try {\n pathname = new URL(value).pathname;\n } catch {\n return null;\n }\n let decoded: string;\n try {\n decoded = decodeURIComponent(pathname);\n } catch {\n return null; // A malformed percent-escape.\n }\n // `file:///C:/Users/me` decodes to `/C:/Users/me`; drop the leading slash so\n // the result is the real Windows path.\n return /^\\/[A-Za-z]:[\\\\/]/.test(decoded) ? decoded.slice(1) : decoded;\n}\n\n/** POSIX root, a Windows drive, or a UNC share. Nothing else is usable as a session root. */\nfunction isAbsolutePath(value: string): boolean {\n if (value.startsWith('\\\\\\\\')) return true; // \\\\server\\share\n if (value.startsWith('/')) return true;\n return /^[A-Za-z]:[\\\\/]/.test(value);\n}\n",".width { width: min(520px, calc(100vw - 32px)); }\n\n.form { display: grid; gap: var(--space-4); }\n.field { display: grid; gap: var(--space-1); min-width: 0; }\n.label {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n.optional { font-weight: var(--font-weight-regular); letter-spacing: 0; text-transform: none; opacity: 0.8; }\n\n.select,\n.input {\n width: 100%;\n min-height: var(--control-h);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-input);\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n text-overflow: ellipsis;\n}\n.input::placeholder { color: var(--text-tertiary); }\n.select,\n.input {\n transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);\n}\n.select:hover:not(:disabled),\n.input:hover:not(:disabled) { border-color: var(--border-strong); }\n/* Same focus treatment as the Input/Select primitives: accent edge plus the\n system ring, so a field in this dialog and a field in Settings read\n identically — and both are actually visible (see Input.module.css). */\n.select:focus-visible,\n.input:focus-visible { border-color: var(--border-focus); box-shadow: var(--shadow-focus-ring); }\n\n.hint { font-size: var(--text-xs-size); line-height: var(--text-xs-line); color: var(--text-tertiary); }\n.error {\n padding-left: var(--space-3);\n border-left: 2px solid var(--status-danger-solid);\n color: var(--status-danger-fg);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n\n.actions { display: flex; justify-content: flex-end; gap: var(--space-2); }\n.cancel,\n.create {\n min-height: var(--control-h);\n padding: 0 var(--space-4);\n border: 1px solid transparent;\n border-radius: var(--radius-sm);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-medium);\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.cancel { color: var(--text-secondary); }\n.cancel:hover { background: var(--bg-hover); color: var(--text-primary); }\n.cancel:active { background: var(--bg-active); }\n.create { background: var(--accent-600); color: var(--accent-contrast); }\n.create:hover:not(:disabled) { background: var(--accent-700); }\n.create:active:not(:disabled) { background: var(--accent-700); }\n.create:disabled { opacity: 0.4; cursor: not-allowed; }\n\n/* The chosen seat's capacity, directly under the picker: this is where the\n choice is made, so the cost of making it belongs here and not one section\n away. Indented on the engine-neutral hairline the error state also uses, so\n it reads as commentary on the field above rather than a new field. */\n.capacity {\n padding-left: var(--space-3);\n border-left: 1px solid var(--border-default);\n}\n\n/* Extra workspace folders: one row per folder, with its own Remove. */\n.rootRow {\n display: flex;\n gap: var(--space-2);\n align-items: center;\n margin-top: var(--space-2);\n}\n\n.rootRow .input { flex: 1 1 auto; min-width: 0; }\n\n.removeRoot,\n.addRoot {\n flex: none;\n padding: var(--space-1) var(--space-2);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n background: var(--surface-raised);\n color: var(--text-default);\n font-size: var(--text-xs);\n cursor: pointer;\n}\n\n.addRoot { margin-top: var(--space-2); align-self: flex-start; }\n\n.removeRoot:hover,\n.addRoot:hover { border-color: var(--border-strong, var(--border-subtle)); }\n","/**\n * routes/verse/NewChatDialog.tsx — start a chat: pick a project (saved\n * projects + enrolled repos + any project a previous chat used, or \"Other\n * folder…\" with an absolute path), pick a seat + model, optionally title it.\n * Built on the shared Dialog primitive so focus trap / Escape / return-focus\n * come free.\n *\n * A folder typed here can be KEPT: \"Save as a project\" writes it to the\n * workspace registry and it is in this picker from then on. Before that\n * button existed the only folders that came back were ones a chat had already\n * been created on (core/verse/projects.ts remembers those), so a folder\n * opened and not chatted on was gone by the next launch.\n *\n * The native directory chooser is offered ALONGSIDE the text input, never\n * instead of it — the same console runs in a plain browser, where there is no\n * chooser at all.\n *\n * The seat list is where the choice actually GETS MADE, so the picked seat's\n * capacity is shown here too, under the picker: plan, the binding window as a\n * meter, its reset verbatim, and any credit balance — the same projection the\n * resources panel renders, so the two can never describe one seat differently.\n *\n * Opening the dialog also re-reads the roster. `bootstrap` has no SSE\n * invalidation and the account collector needs ~75s to warm, so a dialog\n * opened early in a session would otherwise show the cold, empty reading\n * taken at mount and present it as the state of the world.\n */\nimport { useEffect, useId, useMemo, useRef, useState, type FormEvent } from 'react';\nimport type { VerseCreateSessionRequest, VerseProject, VerseSeat, VerseWorkspace } from '../../data/api-types.js';\nimport { Dialog } from '../../components/primitives/Dialog.js';\nimport { useRefetch } from '../../data/hooks.js';\nimport { SeatCapacityNote } from './SeatCapacity.js';\nimport { defaultSeatChoice, SeatSelector, type SeatChoice } from './SeatSelector.js';\nimport {\n defaultWorkspaceName,\n extraRootsCaveat,\n extraRootsNote,\n MAX_WORKSPACE_ROOTS,\n validateRootSet,\n workspaceSummary,\n} from './workspace-model.js';\nimport { createVerseWorkspace, verseBootstrapQuery } from './verse-queries.js';\nimport { nativePickerAvailable, pickDirectory } from './folder-picker.js';\nimport styles from './NewChatDialog.module.css';\n\n/**\n * Prefix marking a select value as a WORKSPACE id rather than a folder path.\n * Safe for the same reason `OTHER` is: it starts with a NUL, and a filesystem\n * path can never contain one.\n */\nconst WORKSPACE_PREFIX = '\\0workspace:';\n\nconst OTHER = '\u0000other';\n\nexport interface NewChatDialogProps {\n open: boolean;\n onClose: () => void;\n projects: readonly VerseProject[];\n seats: readonly VerseSeat[];\n /** Named multi-folder workspaces. Absent on an older server. */\n workspaces?: readonly VerseWorkspace[];\n /** Pre-fill (e.g. \"same project, different seat\" from the composer). */\n initialProjectPath?: string | null;\n initialSeat?: SeatChoice | null;\n busy?: boolean;\n error?: string | null;\n onCreate: (req: VerseCreateSessionRequest) => Promise<void> | void;\n}\n\nexport function NewChatDialog({ open, onClose, projects, seats, workspaces = [], initialProjectPath, initialSeat, busy = false, error, onCreate }: NewChatDialogProps) {\n const titleId = useId();\n const projectId = useId();\n const pathId = useId();\n const nameId = useId();\n const seatId = useId();\n const firstField = useRef<HTMLSelectElement>(null);\n const [projectChoice, setProjectChoice] = useState<string>('');\n const [customPath, setCustomPath] = useState('');\n const [seat, setSeat] = useState<SeatChoice | null>(null);\n const [title, setTitle] = useState('');\n const [localError, setLocalError] = useState<string | null>(null);\n /** Ad-hoc folders beyond the primary, when not binding to a workspace. */\n const [extraRoots, setExtraRoots] = useState<string[]>([]);\n /**\n * Projects saved from THIS dialog, held locally as well as sent.\n *\n * `workspaces` is refreshed by the cache invalidation the mutation triggers,\n * but that is a round trip. Keeping the created record here means the option\n * the operator just saved is in the picker on the very next paint — the\n * whole promise of the button is that the folder is now kept, so a second of\n * \"did that work?\" would undo it.\n */\n const [saved, setSaved] = useState<VerseWorkspace[]>([]);\n const [savingProject, setSavingProject] = useState(false);\n const [savedNote, setSavedNote] = useState<string | null>(null);\n\n const sortedProjects = useMemo(() => [...projects].sort((a, b) => Number(b.enrolled) - Number(a.enrolled) || a.name.localeCompare(b.name)), [projects]);\n\n // Reset to the caller's pre-fill ONLY on the open transition. The pre-fill\n // inputs are read through a ref: `projects`/`seats` are fresh arrays on\n // every bootstrap refetch (which any turn finishing elsewhere triggers),\n // and re-running the reset on those would wipe a half-typed path or title.\n const prefill = useRef({ initialProjectPath, initialSeat, projects, seats, sortedProjects });\n prefill.current = { initialProjectPath, initialSeat, projects, seats, sortedProjects };\n useEffect(() => {\n if (!open) return;\n const { initialProjectPath: path, initialSeat: seatChoice, projects: known, seats: available, sortedProjects: sorted } = prefill.current;\n const knownPath = path && known.some((p) => p.path === path) ? path : null;\n setProjectChoice(knownPath ?? (path ? OTHER : sorted[0]?.path ?? OTHER));\n setCustomPath(knownPath ? '' : path ?? '');\n setSeat(seatChoice ?? defaultSeatChoice(available));\n setTitle('');\n setLocalError(null);\n setExtraRoots([]);\n setSavedNote(null);\n setSavingProject(false);\n setSaved([]);\n }, [open]);\n\n // Seats that arrive after the dialog opened (slow bootstrap) fill an empty\n // seat once, without touching anything the operator has typed.\n useEffect(() => {\n if (!open || seat !== null || seats.length === 0) return;\n setSeat(initialSeat ?? defaultSeatChoice(seats));\n }, [open, seat, seats, initialSeat]);\n\n // One re-read per open, not per render: the roster is worth a fresh look at\n // the moment a seat is about to be chosen, and worth nothing after that.\n const refetchBootstrap = useRefetch(verseBootstrapQuery);\n useEffect(() => {\n if (open) refetchBootstrap();\n }, [open, refetchBootstrap]);\n\n // The picker's saved-project list: what the server has, plus anything saved\n // in this dialog that the refreshed list has not caught up with yet.\n const savedProjects = useMemo(() => {\n const byId = new Map<string, VerseWorkspace>();\n for (const w of workspaces) byId.set(w.id, w);\n for (const w of saved) if (!byId.has(w.id)) byId.set(w.id, w);\n return [...byId.values()];\n }, [workspaces, saved]);\n\n const usingWorkspace = projectChoice.startsWith(WORKSPACE_PREFIX);\n const workspaceId = usingWorkspace ? projectChoice.slice(WORKSPACE_PREFIX.length) : null;\n const projectPath = usingWorkspace ? '' : projectChoice === OTHER ? customPath.trim() : projectChoice;\n const chosenSeat = seat === null ? null : seats.find((s) => s.id === seat.seatId) ?? null;\n const disabledSeat = chosenSeat?.health.state === 'unavailable';\n const canCreate = !busy && (usingWorkspace || projectPath.length > 0) && seat !== null && !disabledSeat;\n const chosenWorkspace = workspaceId === null ? null : savedProjects.find((w) => w.id === workspaceId) ?? null;\n\n // A seat whose CLI takes no additional-directory flag reaches only the\n // primary folder. Say that at the point the extra folders are chosen, rather\n // than letting the operator discover it from a diff that will not apply.\n // This holds for a SAVED project too — a project saved with three folders\n // still reaches one of them on a Grok seat, and the picker is the only place\n // that knows both facts at once.\n const adHocNote = extraRootsNote(chosenSeat?.engine ?? null, 1 + extraRoots.length);\n const workspaceCaveat = extraRootsCaveat(chosenSeat?.engine ?? null, chosenWorkspace?.roots.length ?? 0);\n\n /** The native chooser, where there is one. The text input never goes away. */\n const showPicker = nativePickerAvailable();\n async function choosePrimary() {\n const picked = await pickDirectory();\n if (picked !== null && picked.length > 0) {\n setProjectChoice(OTHER);\n setCustomPath(picked);\n }\n }\n async function chooseExtra(index: number) {\n const picked = await pickDirectory();\n if (picked !== null && picked.length > 0) {\n setExtraRoots(extraRoots.map((r, i) => (i === index ? picked : r)));\n }\n }\n\n /**\n * Keep the folder set that is on screen, so it is in this picker next time.\n *\n * Deliberately one press with no naming step: the folder's own name is very\n * nearly always the right one, and the project can be renamed from the\n * sidebar. A dialog inside a dialog to collect a name would cost more than\n * it is worth at the moment someone just wants to keep a folder.\n */\n async function saveProject() {\n const validation = validateRootSet(projectPath, extraRoots);\n if (!validation.ok) {\n setLocalError(validation.error);\n return;\n }\n setSavingProject(true);\n setLocalError(null);\n setSavedNote(null);\n try {\n const name = defaultWorkspaceName(validation.roots[0]!);\n const workspace = await createVerseWorkspace({ name, roots: validation.roots });\n setSaved((prev) => [...prev, workspace]);\n setProjectChoice(`${WORKSPACE_PREFIX}${workspace.id}`);\n setSavedNote(`Saved. “${workspace.name}” is in this list from now on.`);\n } catch (err) {\n setLocalError(err instanceof Error ? err.message : String(err));\n } finally {\n setSavingProject(false);\n }\n }\n\n function submit(event: FormEvent) {\n event.preventDefault();\n if (!seat) {\n setLocalError('Pick a seat first.');\n return;\n }\n // Bound to a named workspace: the server reads the roots from the\n // registry, so no path is sent at all and the two cannot disagree.\n if (workspaceId !== null) {\n setLocalError(null);\n const req: VerseCreateSessionRequest = {\n // `projectPath` is filled in by the server from the workspace primary;\n // the field is required by the type, and the server rejects the pair.\n workspaceId,\n seatId: seat.seatId,\n model: seat.model,\n } as VerseCreateSessionRequest;\n delete (req as Partial<VerseCreateSessionRequest>).projectPath;\n const named = title.trim();\n if (named) req.title = named;\n void onCreate(req);\n return;\n }\n\n const validation = validateRootSet(projectPath, extraRoots);\n if (!validation.ok) {\n setLocalError(validation.error);\n return;\n }\n setLocalError(null);\n const [primary, ...rest] = validation.roots;\n const req: VerseCreateSessionRequest = { projectPath: primary!, seatId: seat.seatId, model: seat.model };\n if (rest.length > 0) req.extraRoots = rest;\n const trimmed = title.trim();\n if (trimmed) req.title = trimmed;\n void onCreate(req);\n }\n\n const message = localError ?? error ?? null;\n\n return (\n <Dialog open={open} onClose={onClose} titleId={titleId} title=\"New chat\" initialFocusRef={firstField} widthClassName={styles.width}>\n <form className={styles.form} onSubmit={submit} noValidate>\n <label className={styles.field} htmlFor={projectId}>\n <span className={styles.label}>Project</span>\n <select id={projectId} ref={firstField} value={projectChoice} onChange={(event) => setProjectChoice(event.target.value)} className={styles.select}>\n {/* The group exists only when there is something in it. An empty\n \"Saved projects\" heading is a promise the console cannot keep,\n and until this dialog could create one it was exactly that. */}\n {savedProjects.length > 0 ? (\n <optgroup label=\"Saved projects\">\n {savedProjects.map((w) => (\n <option key={w.id} value={`${WORKSPACE_PREFIX}${w.id}`}>\n {w.name} — {workspaceSummary(w)}\n </option>\n ))}\n </optgroup>\n ) : null}\n {sortedProjects.map((p) => (\n <option key={p.path} value={p.path}>{p.name}{p.enrolled ? '' : ' (recent)'} — {p.path}</option>\n ))}\n <option value={OTHER}>Other folder…</option>\n </select>\n </label>\n {projectChoice === OTHER && !usingWorkspace ? (\n <label className={styles.field} htmlFor={pathId}>\n <span className={styles.label}>Folder path</span>\n {/* The text input is unconditional: the console also runs in a\n plain browser, which has no directory chooser at all. The\n native button is an ADDITION where a shell can provide one. */}\n <div className={styles.rootRow}>\n <input id={pathId} className={styles.input} value={customPath} onChange={(event) => setCustomPath(event.target.value)}\n placeholder=\"/absolute/path/to/project\" autoComplete=\"off\" spellCheck={false} />\n {showPicker ? (\n <button type=\"button\" className={styles.addRoot} onClick={() => void choosePrimary()}>Choose folder…</button>\n ) : null}\n </div>\n </label>\n ) : null}\n {workspaceCaveat ? <p className={styles.hint}>{workspaceCaveat}</p> : null}\n {/* Extra folders, for the very common \"this service plus the shared\n library it depends on\". Hidden for a workspace, whose roots are\n defined once in the registry and must not be edited per chat —\n that is the difference between a workspace and an ad-hoc set. */}\n {usingWorkspace ? null : (\n <div className={styles.field}>\n <span className={styles.label}>\n Also include <span className={styles.optional}>optional</span>\n </span>\n {extraRoots.map((root, index) => (\n <div key={index} className={styles.rootRow}>\n <input\n className={styles.input}\n value={root}\n onChange={(event) => setExtraRoots(extraRoots.map((r, i) => (i === index ? event.target.value : r)))}\n placeholder=\"/absolute/path/to/another/folder\"\n aria-label={`Additional folder ${index + 1}`}\n autoComplete=\"off\"\n spellCheck={false}\n />\n {showPicker ? (\n <button\n type=\"button\"\n className={styles.removeRoot}\n onClick={() => void chooseExtra(index)}\n aria-label={`Choose additional folder ${index + 1}`}\n >Choose folder…</button>\n ) : null}\n <button\n type=\"button\"\n className={styles.removeRoot}\n onClick={() => setExtraRoots(extraRoots.filter((_, i) => i !== index))}\n aria-label={`Remove additional folder ${index + 1}`}\n >Remove</button>\n </div>\n ))}\n {extraRoots.length + 1 < MAX_WORKSPACE_ROOTS ? (\n <button type=\"button\" className={styles.addRoot} onClick={() => setExtraRoots([...extraRoots, ''])}>\n Add a folder\n </button>\n ) : null}\n {adHocNote ? <p className={styles.hint}>{adHocNote}</p> : null}\n {/* Keep this folder set. Nothing about a SAVED project can be\n edited per chat — that is the difference between a project and\n an ad-hoc set — so the offer appears only on the ad-hoc path. */}\n <div className={styles.rootRow}>\n <button type=\"button\" className={styles.addRoot} onClick={() => void saveProject()}\n disabled={savingProject || projectPath.length === 0}>\n {savingProject ? 'Saving…' : 'Save as a project'}\n </button>\n <span className={styles.hint}>Keeps these folders in the list above. No chat needed first.</span>\n </div>\n </div>\n )}\n {/* OUTSIDE the ad-hoc block on purpose: saving switches the picker to\n the project it just created, which unmounts that block — and the\n confirmation that the folder was kept is exactly what must not\n disappear at that moment. */}\n {savedNote ? <p role=\"status\" className={styles.hint}>{savedNote}</p> : null}\n\n <SeatSelector id={seatId} seats={seats} value={seat} onChange={setSeat} />\n {chosenSeat === null ? null : <SeatCapacityNote seat={chosenSeat} className={styles.capacity} />}\n {seats.length === 0 ? <p className={styles.hint}>No seats yet — connect an account or start Ollama, then reload.</p> : null}\n <label className={styles.field} htmlFor={nameId}>\n <span className={styles.label}>Title <span className={styles.optional}>optional</span></span>\n <input id={nameId} className={styles.input} value={title} onChange={(event) => setTitle(event.target.value)}\n placeholder=\"Defaults to your first message\" maxLength={120} />\n </label>\n {message ? <p role=\"alert\" className={styles.error}>{message}</p> : null}\n <div className={styles.actions}>\n <button type=\"button\" className={styles.cancel} onClick={onClose}>Cancel</button>\n <button type=\"submit\" className={styles.create} disabled={!canCreate}>{busy ? 'Creating…' : 'Start chat'}</button>\n </div>\n </form>\n </Dialog>\n );\n}\n",".width { width: min(560px, calc(100vw - 32px)); }\n\n.input {\n width: 100%;\n min-height: calc(var(--control-h) + var(--space-1));\n padding: 0 var(--space-3);\n margin-bottom: var(--space-2);\n border: 0;\n border-bottom: 1px solid var(--border-subtle);\n border-radius: 0;\n background: transparent;\n color: var(--text-primary);\n font-size: var(--text-md-size);\n}\n.input::placeholder { color: var(--text-tertiary); }\n/* Replaces the global ring: a 2px accent underline on the search line. */\n.input:focus-visible { outline: none; box-shadow: inset 0 -1px 0 var(--accent-500); border-bottom-color: var(--accent-500); }\n\n.list {\n list-style: none;\n margin: 0;\n padding: 0;\n max-height: min(60vh, 440px);\n overflow-y: auto;\n}\n\n.row {\n display: grid;\n grid-template-columns: 2px minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--space-3);\n min-height: calc(var(--density-row) + var(--space-2));\n padding: var(--space-1) var(--space-3);\n cursor: pointer;\n color: var(--text-secondary);\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n/* The list had no pointer hover at all — only the keyboard-selected row was\n ever tinted, so a mouse user got no feedback crossing the results. Hover\n stops one step short of the selected ground so the two stay distinct. */\n.row:hover:not(.rowActive) { background: var(--bg-hover); color: var(--text-primary); }\n.rowActive { background: var(--bg-selected); color: var(--text-primary); }\n\n.marker { width: 2px; height: var(--engine-marker-h); border-radius: 1px; background: var(--verse-engine, var(--text-tertiary)); }\n.engine-claude { --verse-engine: var(--engine-claude, #c96442); }\n.engine-codex { --verse-engine: var(--engine-codex, #10a37f); }\n.engine-grok { --verse-engine: var(--engine-grok, #6b7280); }\n.engine-local { --verse-engine: var(--engine-local, #7c5cff); }\n\n.rowText { display: flex; flex-direction: column; gap: 1px; min-width: 0; }\n.rowPrimary {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-sm-size);\n color: var(--text-primary);\n}\n.rowSecondary {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-2xs-size, 11px);\n color: var(--text-tertiary);\n}\n.rowActive .rowSecondary,\n.row:hover .rowSecondary,\n.rowActive .rowTrailing,\n.row:hover .rowTrailing { color: var(--text-secondary); }\n.rowTrailing {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n}\n\n.emptyRow { padding: var(--space-4) var(--space-3); color: var(--text-tertiary); font-size: var(--text-sm-size); }\n","/**\n * routes/verse/QuickSwitcher.tsx — ⌘K. A minimal listbox over existing\n * chats plus a \"New chat on <seat>\" row per selectable seat. The shared\n * CommandPalette is bound to the HashRouter nav table, which this\n * full-bleed console does not mount, so this is the small list the contract\n * allows instead — same Dialog primitive, same keyboard model.\n *\n * Each row carries the same 2px engine marker the sidebar uses, so the\n * switcher reads as the same list seen from a different angle.\n */\nimport { useEffect, useId, useMemo, useRef, useState, type KeyboardEvent } from 'react';\nimport type { VerseEngine, VerseProject, VerseSeat, VerseSession } from '../../data/api-types.js';\nimport { Dialog } from '../../components/primitives/Dialog.js';\nimport type { SeatChoice } from './SeatSelector.js';\nimport { formatRelative, projectName, seatLabel } from './verse-model.js';\nimport styles from './QuickSwitcher.module.css';\n\nexport interface QuickSwitcherProps {\n open: boolean;\n onClose: () => void;\n sessions: readonly VerseSession[];\n seats: readonly VerseSeat[];\n projects: readonly VerseProject[];\n onSelectSession: (id: string) => void;\n onNewChat: (seat: SeatChoice | null) => void;\n}\n\ninterface Row {\n id: string;\n kind: 'session' | 'seat';\n engine: VerseEngine;\n primary: string;\n secondary: string;\n trailing: string;\n run: () => void;\n}\n\nexport function QuickSwitcher({ open, onClose, sessions, seats, projects, onSelectSession, onNewChat }: QuickSwitcherProps) {\n const titleId = useId();\n const listId = useId();\n const input = useRef<HTMLInputElement>(null);\n const [query, setQuery] = useState('');\n const [active, setActive] = useState(0);\n\n useEffect(() => {\n if (open) {\n setQuery('');\n setActive(0);\n }\n }, [open]);\n\n const rows = useMemo<Row[]>(() => {\n const q = query.trim().toLowerCase();\n const sessionRows: Row[] = [...sessions]\n .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))\n .map((s) => ({\n id: `session:${s.id}`,\n kind: 'session' as const,\n engine: s.engine,\n primary: s.title || 'Untitled chat',\n secondary: `${projectName(s.projectPath, projects)} · ${seatLabel(seats, s)} · ${s.model}`,\n trailing: formatRelative(s.updatedAt),\n run: () => { onSelectSession(s.id); onClose(); },\n }));\n const seatRows: Row[] = seats\n .filter((seat) => seat.health.state !== 'unavailable' && seat.models.length > 0)\n .map((seat) => ({\n id: `seat:${seat.id}`,\n kind: 'seat' as const,\n engine: seat.engine,\n primary: `New chat on ${seat.label}`,\n secondary: seat.models[0]!.label,\n trailing: '⌘N',\n run: () => { onNewChat({ seatId: seat.id, model: seat.models[0]!.id }); onClose(); },\n }));\n const all = [...sessionRows, ...seatRows];\n if (!q) return all;\n return all.filter((r) => r.primary.toLowerCase().includes(q) || r.secondary.toLowerCase().includes(q));\n }, [query, sessions, seats, projects, onSelectSession, onNewChat, onClose]);\n\n useEffect(() => {\n if (active >= rows.length) setActive(0);\n }, [rows.length, active]);\n\n function onKeyDown(event: KeyboardEvent<HTMLInputElement>) {\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n setActive((i) => (rows.length ? (i + 1) % rows.length : 0));\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n setActive((i) => (rows.length ? (i - 1 + rows.length) % rows.length : 0));\n } else if (event.key === 'Enter') {\n event.preventDefault();\n rows[active]?.run();\n }\n }\n\n return (\n <Dialog open={open} onClose={onClose} titleId={titleId} title=\"Switch chat\" initialFocusRef={input} widthClassName={styles.width}>\n <input ref={input} className={styles.input} value={query} placeholder=\"Search chats or start one on a seat…\"\n role=\"combobox\" aria-expanded=\"true\" aria-controls={listId} aria-activedescendant={rows[active] ? `${listId}-${active}` : undefined}\n aria-autocomplete=\"list\" autoComplete=\"off\" onChange={(event) => { setQuery(event.target.value); setActive(0); }} onKeyDown={onKeyDown} />\n <ul id={listId} role=\"listbox\" className={styles.list} aria-label=\"Chats and seats\">\n {rows.length === 0 ? <li className={styles.emptyRow}>Nothing matches.</li> : rows.map((row, i) => (\n <li key={row.id} id={`${listId}-${i}`} role=\"option\" aria-selected={i === active}\n className={`${styles.row} ${styles[`engine-${row.engine}`] ?? ''} ${i === active ? styles.rowActive : ''}`}\n data-kind={row.kind}\n onMouseEnter={() => setActive(i)} onMouseDown={(event) => event.preventDefault()} onClick={row.run}>\n <span className={styles.marker} aria-hidden=\"true\" />\n <span className={styles.rowText}>\n <span className={styles.rowPrimary}>{row.primary}</span>\n <span className={styles.rowSecondary}>{row.secondary}</span>\n </span>\n <span className={styles.rowTrailing} aria-hidden=\"true\">{row.trailing}</span>\n </li>\n ))}\n </ul>\n </Dialog>\n );\n}\n","/**\n * SessionRoots.module.css — one row per folder this chat can reach.\n *\n * Tone is carried by a left border AND by words (the badge and the caveat\n * line), never by colour alone — DESIGN-V2 §6.\n */\n\n.roots { padding: var(--space-4) var(--space-4) 0; }\n\n.title {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n margin: 0 0 var(--space-2);\n font-size: var(--text-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--text-muted);\n}\n\n.count {\n padding: 0 var(--space-1);\n border-radius: var(--radius-sm);\n background: var(--surface-raised);\n font-variant-numeric: tabular-nums;\n letter-spacing: 0;\n}\n\n.workspace {\n margin: 0 0 var(--space-2);\n font-size: var(--text-xs);\n color: var(--text-muted);\n}\n\n.list {\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: var(--space-2);\n}\n\n.root {\n padding: var(--space-2);\n border-radius: var(--radius-sm);\n border-left: 3px solid var(--border-subtle);\n background: var(--surface-raised);\n}\n\n.root[data-tone='primary'] { border-left-color: var(--accent); }\n.root[data-tone='extra'] { border-left-color: var(--border-strong, var(--border-subtle)); }\n.root[data-tone='unreachable'] { border-left-color: var(--warning, #b7791f); }\n.root[data-tone='missing'] { border-left-color: var(--danger, #c53030); }\n\n.rootHead {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--space-2);\n}\n\n.name {\n font-size: var(--text-sm);\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.badge {\n flex: none;\n font-size: var(--text-2xs, 0.6875rem);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--text-muted);\n}\n\n/* The full path, shown rather than hovered. `direction: rtl` with the text\n isolated flips only WHICH END the ellipsis eats — the head, so the tail\n that actually disambiguates two same-named checkouts survives. The bdi\n isolation keeps the path itself rendering left-to-right. */\n.path {\n margin: var(--space-1) 0 0;\n direction: rtl;\n text-align: left;\n unicode-bidi: plaintext;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: var(--font-mono);\n font-size: var(--text-xs);\n color: var(--text-muted);\n}\n\n.git,\n.remote,\n.caveat {\n margin: var(--space-1) 0 0;\n font-size: var(--text-xs);\n color: var(--text-muted);\n}\n\n.git { font-variant-numeric: tabular-nums; }\n\n.remote {\n font-family: var(--font-mono);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.caveat { color: var(--text-strong, var(--text-default)); }\n\n.note,\n.error {\n margin: var(--space-2) 0 0;\n font-size: var(--text-xs);\n line-height: 1.45;\n color: var(--text-muted);\n}\n\n.error { color: var(--danger, #c53030); }\n","/**\n * routes/verse/SessionRoots.tsx — the folders THIS chat can reach, each with\n * its own git identity.\n *\n * WHY PER-ROOT IDENTITY IS THE POINT. A turn that edits two repositories\n * produces two diffs. Without a branch and a dirty count per root, the\n * transcript cannot attribute them, and \"3 files changed\" silently spans two\n * repositories on two different branches. So every root gets its own line:\n * branch, how many entries are dirty, and how far it has drifted from its\n * upstream.\n *\n * WHAT IT REFUSES TO IMPLY:\n * - A root the engine cannot reach (a Grok seat takes no additional-directory\n * flag) is LISTED and marked, never hidden — the operator chose it.\n * - A root that is not enrolled is marked as refused BY THE AUTONOMOUS LANE,\n * not as unusable here. This chat can edit it; the fleet cannot.\n * - A root with no repo says so, rather than leaving a gap that would read as\n * \"clean, on the default branch\".\n *\n * The data is fetched per open rather than cached: a branch is stale the\n * moment a turn commits.\n */\nimport { useEffect, useState } from 'react';\nimport type { VerseSession, VerseSessionRootsResponse } from '../../data/api-types.js';\nimport { rootCaveat, rootGitLine, rootTone } from './workspace-model.js';\nimport { fetchVerseSessionRoots } from './verse-queries.js';\nimport styles from './SessionRoots.module.css';\n\nexport interface SessionRootsProps {\n session: VerseSession | null;\n /** Bumped by the caller after a turn finishes, so branches re-read. */\n refreshKey?: number;\n}\n\nexport function SessionRoots({ session, refreshKey = 0 }: SessionRootsProps) {\n const [data, setData] = useState<VerseSessionRootsResponse | null>(null);\n const [error, setError] = useState<string | null>(null);\n const sessionId = session?.id ?? null;\n\n useEffect(() => {\n if (!sessionId) {\n setData(null);\n return;\n }\n const controller = new AbortController();\n setError(null);\n fetchVerseSessionRoots(sessionId, controller.signal)\n .then((next) => setData(next))\n .catch((err: unknown) => {\n if (controller.signal.aborted) return;\n setData(null);\n setError(err instanceof Error ? err.message : 'could not read this chat’s folders');\n });\n return () => controller.abort();\n }, [sessionId, refreshKey]);\n\n if (!session) return null;\n\n // A single-folder chat is the overwhelmingly common case and already says\n // which folder it is everywhere else. Showing a one-row \"Folders\" list for\n // it would be noise, so this surfaces only when there is something to\n // attribute between.\n if (data !== null && data.roots.length <= 1 && data.workspaceId === null) return null;\n\n return (\n <section className={styles.roots} aria-labelledby=\"verse-res-roots\">\n <h3 id=\"verse-res-roots\" className={styles.title}>\n Folders\n {data ? <span className={styles.count}>{data.roots.length}</span> : null}\n </h3>\n\n {data?.workspaceName ? (\n <p className={styles.workspace}>\n Workspace <strong>{data.workspaceName}</strong>\n </p>\n ) : null}\n\n {error ? <p role=\"alert\" className={styles.error}>{error}</p> : null}\n\n <ul className={styles.list}>\n {(data?.roots ?? []).map((root) => {\n const git = rootGitLine(root);\n const caveat = rootCaveat(root);\n return (\n <li key={root.path} className={styles.root} data-tone={rootTone(root)}>\n <div className={styles.rootHead}>\n <span className={styles.name}>{root.name}</span>\n <span className={styles.badge}>{root.primary ? 'primary' : 'added'}</span>\n </div>\n {/* The path was a hover `title` on the folder name. This card is\n the one place in the app that exists to ATTRIBUTE a diff to a\n repository, and two checkouts of the same repo share a name —\n so the thing that tells them apart cannot be the one fact you\n have to hover to read. It is shown, directory-first, with the\n head clipping so the tail that disambiguates stays visible. */}\n <p className={styles.path}>{root.path}</p>\n <p className={styles.git}>{git ?? 'not a git repo'}</p>\n {root.git?.remote ? <p className={styles.remote}>{root.git.remote}</p> : null}\n {caveat ? <p className={styles.caveat}>{caveat}</p> : null}\n </li>\n );\n })}\n </ul>\n\n {(data?.notes ?? []).map((note) => (\n <p key={note} className={styles.note}>{note}</p>\n ))}\n </section>\n );\n}\n","/**\n * routes/verse/resources-collapse.ts — which resource-panel groups and seats\n * the operator left open.\n *\n * WHY THIS IS NOT `ashlr.verse.ui.v2`. That key's shape is the shell contract\n * (docs/VERSE-CONTRACT-V2.md) and verse-ui-store.test pins it field for field.\n * Collapse is a preference about the seat list, so it lives under its own key.\n *\n * WHY IT IS PERSISTED AT ALL. A spent seat starts collapsed because that is\n * the one the operator does not need open — two Codex accounts pinned at\n * their limit were hundreds of pixels of dead weight above the seat that\n * still had room. A data refresh, and a browser refresh, must not re-derive\n * that default over an explicit choice: opening a spent seat to read its\n * reset, then clicking Refresh, would otherwise slam it shut again.\n *\n * Defaults are applied at read time, never written. A seat that later\n * becomes usable opens itself unless the operator had collapsed it on purpose.\n *\n * Pure aside from the two localStorage functions. No React.\n */\nimport type { VerseEngine } from '../../data/api-types.js';\nimport { isVerseEngine } from './verse-model.js';\nimport type { SeatCapacityClass, SeatSubscriptionView, SeatWindowView } from './seat-subscription.js';\n\nexport const RESOURCES_COLLAPSE_KEY = 'ashlr.verse.resources.v1';\n\n/** Bounded so a long-lived browser cannot accumulate a seat id per deleted account. */\nconst SEAT_CHOICE_LIMIT = 80;\nconst SEAT_ID_MAX = 200;\n\nexport interface ResourcesCollapseState {\n /** Engines the operator collapsed. Absent means open — groups start open. */\n collapsedGroups: readonly VerseEngine[];\n /**\n * Explicit per-seat choices. `true` is open, `false` is closed.\n * A missing id means \"use the default\", which depends on the live verdict.\n */\n seats: Readonly<Record<string, boolean>>;\n}\n\nexport function emptyResourcesCollapse(): ResourcesCollapseState {\n return { collapsedGroups: [], seats: {} };\n}\n\n/**\n * Exhausted and signed-out both project to `blocked` (seat-subscription.ts).\n * That is the seat that cannot take a turn, and it is the one that starts shut.\n * `tight` stays open: a Codex week at its limit with spendable credits is\n * still usable, and hiding that fact is the lie the credits rule exists to prevent.\n */\nexport function seatDefaultOpen(cls: SeatCapacityClass): boolean {\n return cls !== 'blocked';\n}\n\nexport function groupIsOpen(state: ResourcesCollapseState, engine: VerseEngine): boolean {\n return !state.collapsedGroups.includes(engine);\n}\n\nexport function seatIsOpen(state: ResourcesCollapseState, seatId: string, cls: SeatCapacityClass): boolean {\n const choice = state.seats[seatId];\n return typeof choice === 'boolean' ? choice : seatDefaultOpen(cls);\n}\n\nexport function toggleGroupCollapse(state: ResourcesCollapseState, engine: VerseEngine): ResourcesCollapseState {\n const collapsedGroups = state.collapsedGroups.includes(engine)\n ? state.collapsedGroups.filter((item) => item !== engine)\n : [...state.collapsedGroups, engine];\n return { ...state, collapsedGroups };\n}\n\nexport function toggleSeatCollapse(\n state: ResourcesCollapseState,\n seatId: string,\n cls: SeatCapacityClass,\n): ResourcesCollapseState {\n if (!isSeatId(seatId)) return state;\n const seats = { ...state.seats, [seatId]: !seatIsOpen(state, seatId, cls) };\n return { ...state, seats: boundSeats(seats) };\n}\n\n/**\n * One bar per window the seat actually carries, binding first.\n *\n * The probes omit a limit they did not report — Codex does not emit a\n * secondary window when `secondary` is null (provider-observations.ts), and\n * Claude only emits `five_hour`, `seven_day`, and whichever per-model week\n * the CLI printed (claude-account-usage.ts `TITLES`). Nothing here adds a\n * window the seat does not have. An unmeasured window stays in the list so\n * the panel can say \"no reading\" instead of drawing an empty bar.\n */\nexport function reportedLimitBars(\n view: Pick<SeatSubscriptionView, 'kind' | 'binding' | 'others'>,\n): SeatWindowView[] {\n if (view.kind === 'local') return [];\n if (view.binding === null) return [...view.others];\n return [view.binding, ...view.others.filter((window) => window.id !== view.binding!.id)];\n}\n\nfunction isSeatId(value: string): boolean {\n return value.length > 0 && value.length <= SEAT_ID_MAX\n && value !== '__proto__' && value !== 'constructor' && value !== 'prototype';\n}\n\nfunction boundSeats(seats: Readonly<Record<string, boolean>>): Record<string, boolean> {\n const entries = Object.entries(seats);\n if (entries.length <= SEAT_CHOICE_LIMIT) return { ...seats };\n return Object.fromEntries(entries.slice(entries.length - SEAT_CHOICE_LIMIT));\n}\n\nexport function parseResourcesCollapse(raw: string | null): ResourcesCollapseState {\n if (raw === null || raw === '') return emptyResourcesCollapse();\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return emptyResourcesCollapse();\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return emptyResourcesCollapse();\n const record = parsed as Record<string, unknown>;\n\n const collapsedGroups: VerseEngine[] = [];\n if (Array.isArray(record.collapsedGroups)) {\n for (const engine of record.collapsedGroups) {\n if (typeof engine === 'string' && isVerseEngine(engine) && !collapsedGroups.includes(engine)) {\n collapsedGroups.push(engine);\n }\n }\n }\n\n const seats: Record<string, boolean> = {};\n const rawSeats = record.seats;\n if (rawSeats && typeof rawSeats === 'object' && !Array.isArray(rawSeats)) {\n for (const [id, choice] of Object.entries(rawSeats as Record<string, unknown>)) {\n if (!isSeatId(id) || typeof choice !== 'boolean') continue;\n if (Object.keys(seats).length >= SEAT_CHOICE_LIMIT) break;\n Object.defineProperty(seats, id, { value: choice, enumerable: true, writable: true, configurable: true });\n }\n }\n\n return { collapsedGroups, seats };\n}\n\nexport function readResourcesCollapse(): ResourcesCollapseState {\n try {\n return parseResourcesCollapse(localStorage.getItem(RESOURCES_COLLAPSE_KEY));\n } catch {\n return emptyResourcesCollapse();\n }\n}\n\nexport function writeResourcesCollapse(state: ResourcesCollapseState): void {\n try {\n localStorage.setItem(RESOURCES_COLLAPSE_KEY, JSON.stringify({\n collapsedGroups: state.collapsedGroups,\n seats: state.seats,\n }));\n } catch {\n /* a private window without storage still runs the app */\n }\n}\n","/**\n * routes/verse/verse-store.ts — per-session transcript state for the Verse\n * console. Framework-free (useSyncExternalStore glue lives in\n * useVerseSession.ts), same split as data/cache.ts + data/hooks.ts.\n *\n * One entry per session id holds the ordered, seq-deduplicated event log,\n * the latest session record we know of, and the stream connection state.\n * Snapshots are replaced wholesale on every change (Object.is semantics —\n * see DESIGN.md §3 for the bug that rule prevents).\n *\n * `buildTranscript()` derives what the transcript renders from the raw\n * events: streamed `text-delta`s accumulate into a provisional assistant\n * bubble until the matching `assistant-message` arrives and replaces it;\n * `tool-use` and `tool-result` pair up by toolUseId into one card.\n */\nimport type { VerseEvent, VerseSession, VerseUsage } from '../../data/api-types.js';\n\nexport type VerseStreamState = 'idle' | 'connecting' | 'open' | 'reconnecting' | 'closed';\n\nexport interface VerseSessionState {\n sessionId: string;\n session: VerseSession | null;\n events: VerseEvent[];\n lastSeq: number;\n loaded: boolean;\n loadError: string | null;\n stream: VerseStreamState;\n}\n\nconst EMPTY: Omit<VerseSessionState, 'sessionId'> = {\n session: null,\n events: [],\n lastSeq: 0,\n loaded: false,\n loadError: null,\n stream: 'idle',\n};\n\nconst sessions = new Map<string, VerseSessionState>();\nconst listeners = new Set<() => void>();\n\nfunction emit(): void {\n for (const l of listeners) l();\n}\n\nexport function subscribeVerseStore(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nfunction entryFor(sessionId: string): VerseSessionState {\n let e = sessions.get(sessionId);\n if (!e) {\n e = { sessionId, ...EMPTY };\n sessions.set(sessionId, e);\n }\n return e;\n}\n\nfunction patch(sessionId: string, delta: Partial<VerseSessionState>): void {\n const current = entryFor(sessionId);\n sessions.set(sessionId, { ...current, ...delta });\n emit();\n}\n\nconst NONE: VerseSessionState = { sessionId: '', ...EMPTY };\n\n/** Stable reference until the entry changes, so useSyncExternalStore is happy. */\nexport function getVerseSessionState(sessionId: string | null): VerseSessionState {\n if (!sessionId) return NONE;\n return entryFor(sessionId);\n}\n\n/** Merge a fetched detail (session + full event log) into the entry. Events\n * already known (same seq) are kept once; the union stays sorted by seq. The\n * detail fetch starts before the EventSource opens, so a `turn-done` that\n * streamed in meanwhile wins over the older `running` snapshot. */\nexport function seedVerseSession(sessionId: string, session: VerseSession, events: VerseEvent[]): void {\n const current = entryFor(sessionId);\n const merged = mergeEvents(current.events, events);\n patch(sessionId, {\n session: settledStatus(session, merged),\n events: merged,\n lastSeq: merged.length ? merged[merged.length - 1]!.seq : 0,\n loaded: true,\n loadError: null,\n });\n}\n\nexport function setVerseLoadError(sessionId: string, message: string): void {\n patch(sessionId, { loadError: message, loaded: true });\n}\n\nexport function setVerseStreamState(sessionId: string, stream: VerseStreamState): void {\n if (entryFor(sessionId).stream === stream) return;\n patch(sessionId, { stream });\n}\n\n/**\n * Replace the session record (after a turn POST / rename / list refresh).\n * `turnId` is the turn the snapshot claims is running (POST …/turns returns\n * it): when the log already holds that turn's `turn-done`/`cancelled` — a\n * spawn failure settles in the same tick as the 202 — the snapshot is stale\n * and must not drag the composer back to running.\n */\nexport function setVerseSession(sessionId: string, session: VerseSession, turnId?: string): void {\n const current = entryFor(sessionId);\n patch(sessionId, { session: settledStatus(session, current.events, turnId) });\n}\n\n/**\n * Reconcile a `running` snapshot against the event log. Without a `turnId`\n * the running turn is the last `user-message`/`turn-started` in the log; a\n * later `turn-done`/`cancelled` means the server already settled it. With a\n * `turnId`, only that turn's terminal event counts (its `user-message` may\n * not have streamed in yet, so a previous turn's `turn-done` proves nothing).\n * Status follows the same rules applyVerseEvent uses: cancelled → idle,\n * `turn-done ok:false` → error only when an `error` event was logged for it.\n */\nexport function settledStatus(session: VerseSession, events: readonly VerseEvent[], turnId?: string): VerseSession {\n if (session.status !== 'running') return session;\n let anchorSeq = -1;\n let anchorTurn: string | null = turnId ?? null;\n if (!turnId) {\n for (const e of events) {\n if (e.type === 'user-message' || e.type === 'turn-started') {\n anchorSeq = e.seq;\n anchorTurn = e.turnId;\n }\n }\n if (anchorTurn === null) return session;\n }\n let terminal: Extract<VerseEvent, { type: 'turn-done' | 'cancelled' }> | null = null;\n let lastError: string | null = null;\n for (const e of events) {\n if (e.seq <= anchorSeq) continue;\n if (e.type === 'error' && e.turnId === anchorTurn) lastError = e.message;\n if ((e.type === 'turn-done' || e.type === 'cancelled') && e.turnId === anchorTurn) terminal = e;\n }\n if (!terminal) return session;\n const failed = terminal.type === 'turn-done' && !terminal.ok && lastError !== null;\n return {\n ...session,\n status: failed ? 'error' : 'idle',\n lastError: failed ? lastError : null,\n updatedAt: terminal.at > session.updatedAt ? terminal.at : session.updatedAt,\n };\n}\n\n/** Optimistic status flip (e.g. right after POST …/turns returns 202). */\nexport function setVerseSessionStatus(sessionId: string, status: VerseSession['status']): void {\n const current = entryFor(sessionId);\n if (!current.session || current.session.status === status) return;\n patch(sessionId, { session: { ...current.session, status } });\n}\n\n/**\n * Apply one live event. Duplicates (a fresh SSE connection replays from the\n * start) are dropped by seq; out-of-order arrivals are inserted in place.\n * Session-level side effects: `usage` updates the live context meter,\n * `turn-started` flips status to running, `turn-done`/`cancelled`/`error`\n * settle it, and a codex `turn-done.nativeSessionId` is captured.\n */\nexport function applyVerseEvent(sessionId: string, event: VerseEvent): boolean {\n const current = entryFor(sessionId);\n if (!Number.isFinite(event.seq)) return false;\n if (current.events.some((e) => e.seq === event.seq)) return false;\n const events = mergeEvents(current.events, [event]);\n let session = current.session;\n if (session) {\n switch (event.type) {\n case 'turn-started':\n session = { ...session, status: 'running', lastError: null, updatedAt: event.at };\n break;\n case 'usage':\n // The frame carries THIS turn's counts; the record keeps the session\n // totals (server: session-engine applyUsage). Context occupancy and\n // the window are live values, not sums.\n session = {\n ...session,\n usage: {\n inputTokens: session.usage.inputTokens + event.usage.inputTokens,\n outputTokens: session.usage.outputTokens + event.usage.outputTokens,\n cacheReadTokens: session.usage.cacheReadTokens + event.usage.cacheReadTokens,\n cacheCreationTokens: session.usage.cacheCreationTokens + event.usage.cacheCreationTokens,\n contextTokens: event.usage.contextTokens,\n contextWindow: event.usage.contextWindow ?? session.usage.contextWindow,\n },\n updatedAt: event.at,\n };\n break;\n case 'turn-done':\n session = {\n ...session,\n status: event.ok ? 'idle' : session.lastError ? 'error' : 'idle',\n turnCount: session.turnCount + 1,\n nativeSessionId: event.nativeSessionId ?? session.nativeSessionId,\n updatedAt: event.at,\n };\n break;\n case 'error':\n session = { ...session, status: 'error', lastError: event.message, updatedAt: event.at };\n break;\n case 'cancelled':\n session = { ...session, status: 'idle', updatedAt: event.at };\n break;\n default:\n break;\n }\n }\n patch(sessionId, { events, lastSeq: Math.max(current.lastSeq, event.seq), session });\n return true;\n}\n\nexport function forgetVerseSession(sessionId: string): void {\n if (sessions.delete(sessionId)) emit();\n}\n\n/** Test/logout hygiene. */\nexport function resetVerseStore(): void {\n sessions.clear();\n emit();\n}\n\nfunction mergeEvents(existing: VerseEvent[], incoming: VerseEvent[]): VerseEvent[] {\n if (incoming.length === 0) return existing;\n const bySeq = new Map<number, VerseEvent>();\n for (const e of existing) bySeq.set(e.seq, e);\n for (const e of incoming) if (!bySeq.has(e.seq)) bySeq.set(e.seq, e);\n return [...bySeq.values()].sort((a, b) => a.seq - b.seq);\n}\n\n// ---------------------------------------------------------------------------\n// Transcript derivation\n// ---------------------------------------------------------------------------\n\nexport type TranscriptItem =\n | { kind: 'user'; key: string; turnId: string; at: string; text: string }\n | { kind: 'assistant'; key: string; turnId: string; at: string; text: string; streaming: boolean }\n | { kind: 'thinking'; key: string; turnId: string; at: string; text: string }\n | {\n kind: 'tool';\n key: string;\n turnId: string;\n at: string;\n toolUseId: string;\n name: string;\n input: unknown;\n result: { output: string; isError: boolean } | null;\n /** tool-use → tool-result wall time; null while pending or unstamped. */\n durationMs: number | null;\n }\n | { kind: 'error'; key: string; turnId: string | null; at: string; message: string }\n | { kind: 'cancelled'; key: string; turnId: string; at: string }\n | { kind: 'turn-done'; key: string; turnId: string; at: string; ok: boolean; durationMs: number };\n\nexport interface Transcript {\n items: TranscriptItem[];\n /** True while a turn is open (started and not yet done/cancelled). */\n live: boolean;\n /** Most recent usage frame seen in the log, if any. */\n usage: VerseUsage | null;\n}\n\n/** Wall time between two ISO stamps; null when either is unparseable. */\nfunction spanMs(from: string, to: string): number | null {\n const a = Date.parse(from);\n const b = Date.parse(to);\n return Number.isFinite(a) && Number.isFinite(b) ? Math.max(0, b - a) : null;\n}\n\nexport function buildTranscript(events: VerseEvent[]): Transcript {\n const items: TranscriptItem[] = [];\n const toolIndex = new Map<string, number>();\n let pending: { turnId: string; at: string; text: string; key: string } | null = null;\n let live = false;\n let usage: VerseUsage | null = null;\n\n const flushPending = (streaming: boolean) => {\n if (!pending) return;\n items.push({ kind: 'assistant', key: pending.key, turnId: pending.turnId, at: pending.at, text: pending.text, streaming });\n pending = null;\n };\n\n for (const e of events) {\n switch (e.type) {\n case 'user-message':\n flushPending(false);\n items.push({ kind: 'user', key: `u-${e.seq}`, turnId: e.turnId, at: e.at, text: e.text });\n break;\n case 'turn-started':\n live = true;\n break;\n case 'text-delta':\n if (pending && pending.turnId !== e.turnId) flushPending(false);\n if (!pending) pending = { turnId: e.turnId, at: e.at, text: '', key: `d-${e.seq}` };\n pending.text += e.text;\n break;\n case 'assistant-message':\n // The complete message supersedes whatever deltas streamed before it.\n pending = null;\n items.push({ kind: 'assistant', key: `a-${e.seq}`, turnId: e.turnId, at: e.at, text: e.text, streaming: false });\n break;\n case 'thinking':\n flushPending(false);\n items.push({ kind: 'thinking', key: `t-${e.seq}`, turnId: e.turnId, at: e.at, text: e.text });\n break;\n case 'tool-use':\n flushPending(false);\n toolIndex.set(e.toolUseId, items.length);\n items.push({\n kind: 'tool',\n key: `tu-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n toolUseId: e.toolUseId,\n name: e.name,\n input: e.input,\n result: null,\n durationMs: null,\n });\n break;\n case 'tool-result': {\n const idx = toolIndex.get(e.toolUseId);\n const existing = idx === undefined ? undefined : items[idx];\n if (existing && existing.kind === 'tool') {\n items[idx!] = { ...existing, result: { output: e.output, isError: e.isError }, durationMs: spanMs(existing.at, e.at) };\n } else {\n items.push({\n kind: 'tool',\n key: `tr-${e.seq}`,\n turnId: e.turnId,\n at: e.at,\n toolUseId: e.toolUseId,\n name: 'tool',\n input: null,\n result: { output: e.output, isError: e.isError },\n durationMs: null,\n });\n }\n break;\n }\n case 'usage':\n usage = e.usage;\n break;\n case 'error':\n flushPending(false);\n items.push({ kind: 'error', key: `e-${e.seq}`, turnId: e.turnId, at: e.at, message: e.message });\n break;\n case 'cancelled':\n flushPending(false);\n live = false;\n items.push({ kind: 'cancelled', key: `c-${e.seq}`, turnId: e.turnId, at: e.at });\n break;\n case 'turn-done':\n flushPending(false);\n live = false;\n items.push({ kind: 'turn-done', key: `td-${e.seq}`, turnId: e.turnId, at: e.at, ok: e.ok, durationMs: e.durationMs });\n break;\n default:\n break;\n }\n }\n // Deltas still arriving for an open turn render as a streaming bubble.\n flushPending(live);\n return { items, live, usage };\n}\n\n// ---------------------------------------------------------------------------\n// Render-time grouping\n// ---------------------------------------------------------------------------\n\nexport type ToolGroupMember = Extract<TranscriptItem, { kind: 'tool' | 'thinking' }>;\n\nexport interface ToolGroupItem {\n kind: 'toolGroup';\n key: string;\n turnId: string;\n at: string;\n items: ToolGroupMember[];\n /** Tool calls only (thinking blocks are not counted). */\n toolCount: number;\n /** \"Read ×6, Edit ×4\" — names in first-seen order. */\n summary: string;\n errorCount: number;\n /** A member is still waiting for its result. */\n pending: boolean;\n /** Wall time between the first and last member, when both have parseable timestamps. */\n spanMs: number | null;\n}\n\nexport type TranscriptRenderItem = TranscriptItem | ToolGroupItem;\n\n/**\n * Fold runs of two or more consecutive `tool`/`thinking` items from the same\n * turn into one `toolGroup`, so an agentic turn reads as \"N tool calls\"\n * with a single disclosure instead of a wall of cards. Single tool calls\n * stay as they are. Pure over buildTranscript()'s output (the index-based\n * tool-result pairing there is untouched).\n */\nexport function groupTranscriptItems(items: readonly TranscriptItem[]): TranscriptRenderItem[] {\n const out: TranscriptRenderItem[] = [];\n let run: ToolGroupMember[] = [];\n\n const flush = () => {\n if (run.length === 0) return;\n if (run.length === 1) out.push(run[0]!);\n else out.push(makeToolGroup(run));\n run = [];\n };\n\n for (const item of items) {\n if ((item.kind === 'tool' || item.kind === 'thinking') && (run.length === 0 || run[0]!.turnId === item.turnId)) {\n run.push(item);\n continue;\n }\n flush();\n if (item.kind === 'tool' || item.kind === 'thinking') run.push(item);\n else out.push(item);\n }\n flush();\n return out;\n}\n\nfunction makeToolGroup(members: ToolGroupMember[]): ToolGroupItem {\n const counts = new Map<string, number>();\n let errorCount = 0;\n let pending = false;\n for (const m of members) {\n if (m.kind !== 'tool') continue;\n counts.set(m.name, (counts.get(m.name) ?? 0) + 1);\n if (m.result === null) pending = true;\n else if (m.result.isError) errorCount += 1;\n }\n const toolCount = [...counts.values()].reduce((a, b) => a + b, 0);\n const summary = [...counts.entries()].map(([name, n]) => (n > 1 ? `${name} ×${n}` : name)).join(', ');\n const span = spanMs(members[0]!.at, members[members.length - 1]!.at);\n return {\n kind: 'toolGroup',\n key: `g-${members[0]!.key}`,\n turnId: members[0]!.turnId,\n at: members[0]!.at,\n items: members,\n toolCount,\n summary,\n errorCount,\n pending,\n spanMs: span,\n };\n}\n\n/** \"123k\" / \"1.2M\" — compact token counts for the meter and usage rows. */\nexport function formatTokens(n: number | null | undefined): string {\n if (n === null || n === undefined || !Number.isFinite(n)) return '—';\n if (n < 1000) return String(Math.round(n));\n if (n < 1_000_000) return `${Math.round(n / 1000)}k`;\n return `${(n / 1_000_000).toFixed(1).replace(/\\.0$/, '')}M`;\n}\n","/* The right column: seats, local runtime, running chats, this chat's usage.\n Hairlines and whitespace only — no nested boxes. */\n.panel {\n display: flex;\n flex-direction: column;\n min-height: 0;\n background: var(--bg-canvas);\n}\n\n.head {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-2);\n /* DESIGN-V2 §4: header strips are --strip-height, and the token is what the\n desktop shell's inset maths is written against. */\n height: var(--strip-height);\n padding: 0 var(--space-2) 0 var(--space-4);\n border-bottom: 1px solid var(--border-subtle);\n}\n.title {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n.close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--control-h-sm);\n height: var(--control-h-sm);\n border-radius: var(--radius-xs);\n color: var(--text-tertiary);\n font-size: var(--text-md-size);\n line-height: 1;\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.close:hover { background: var(--bg-hover); color: var(--text-primary); }\n.close:active { background: var(--bg-active); }\n\n.scroll { flex: 1; min-height: 0; overflow-y: auto; padding-bottom: var(--space-6); scrollbar-gutter: stable; }\n.section { padding: var(--space-4) var(--space-4) 0; }\n.section + .section { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--border-subtle); }\n.sectionTitle {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--space-2);\n margin-bottom: var(--space-3);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n/* When the reading was taken, and the control that takes a new one. Both sit\n on the section heading so the freshness claim can never drift away from the\n numbers it qualifies. */\n.asOf {\n margin-left: auto;\n font-family: var(--font-display);\n font-weight: var(--font-weight-regular, 400);\n font-variant-numeric: tabular-nums;\n letter-spacing: 0;\n text-transform: none;\n color: var(--text-tertiary);\n}\n.refresh {\n flex: none;\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-xs);\n font-family: var(--font-ui);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-medium);\n letter-spacing: 0;\n text-transform: none;\n color: var(--text-secondary);\n transition: border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.refresh:hover { border-color: var(--border-strong); color: var(--text-primary); background: var(--bg-hover); }\n.refresh:active { background: var(--bg-active); }\n.count { font-variant-numeric: tabular-nums; color: var(--text-secondary); }\n.skeleton { display: flex; flex-direction: column; gap: var(--space-2); }\n.muted { color: var(--text-tertiary); font-size: var(--text-xs-size); line-height: var(--text-xs-line); }\n.muted code { font-size: 0.95em; }\n\n/* ---- seats ------------------------------------------------------------- */\n.engineGroup + .engineGroup { margin-top: var(--space-4); }\n.engineTitle {\n margin-bottom: var(--space-2);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-medium);\n color: var(--text-tertiary);\n}\n/* Provider groups and individual seats are both disclosures. The marker is\n the same triangle the old \"more windows\" row used; the state lives in\n aria-expanded, not in the triangle. */\n.groupToggle,\n.seatToggle {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n width: 100%;\n min-width: 0;\n min-height: var(--control-h-xs);\n text-align: left;\n color: inherit;\n}\n.groupToggle { font: inherit; letter-spacing: inherit; }\n.seatToggle { min-height: var(--density-row, 32px); }\n.groupToggle:hover,\n.seatToggle:hover { color: var(--text-secondary); }\n.groupToggle:focus-visible,\n.seatToggle:focus-visible {\n outline: 2px solid var(--accent-500);\n outline-offset: 2px;\n border-radius: var(--radius-xs);\n}\n.twist {\n flex: none;\n width: 0;\n height: 0;\n border-left: 4px solid currentColor;\n border-top: 3px solid transparent;\n border-bottom: 3px solid transparent;\n transition: transform var(--duration-fast) var(--ease-standard);\n}\n.twist[data-open] { transform: rotate(90deg); }\n.groupToggle .count { margin-left: auto; }\n.seatList, .models, .runningList { list-style: none; margin: 0; padding: 0; }\n.seat {\n padding-left: var(--space-3);\n border-left: 2px solid var(--verse-engine, var(--border-subtle));\n}\n.seat + .seat { margin-top: var(--space-3); }\n/* The seat toggle is wrapped in a Tooltip, whose wrapper spans are\n shrink-to-fit and would collapse a full-width row. Re-stretch by STRUCTURE\n (the primitive's class names are hashed), and keep the rule off the bubble:\n a blanket `display: block` there would beat its `hidden` attribute and pin\n the tooltip open. */\n.seat > span:not([role='tooltip']),\n.seat > span > span:not([role='tooltip']) {\n display: block;\n width: 100%;\n min-width: 0;\n}\n.engine-claude { --verse-engine: var(--engine-claude, #c96442); }\n.engine-codex { --verse-engine: var(--engine-codex, #10a37f); }\n.engine-grok { --verse-engine: var(--engine-grok, #6b7280); }\n.engine-local { --verse-engine: var(--engine-local, #7c5cff); }\n\n.seatHead { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); min-width: 0; }\n.seatToggle .seatLabel { flex: 1; color: var(--text-primary); }\n.seatLabel {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-medium);\n color: var(--text-primary);\n}\n.seatMeta {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-1);\n margin-top: 2px;\n font-size: var(--text-2xs-size, 11px);\n color: var(--text-tertiary);\n}\n.seatSummary { margin-top: var(--space-1); font-size: var(--text-xs-size); line-height: var(--text-xs-line); color: var(--text-secondary); }\n/* The provider's own plan tier, and any figure that must line up down the\n column. Numerals are tabular everywhere they can be compared. */\n.plan { font-family: var(--font-display); text-transform: uppercase; letter-spacing: var(--tracking-label, 0.06em); color: var(--text-secondary); }\n.num { font-family: var(--font-display); font-variant-numeric: tabular-nums; }\n/* The provider's own plain-language facts, plus where the reading came from.\n Secondary to the meter and hanging off it, because they explain the number\n rather than competing with it. */\n.notes {\n list-style: none;\n margin: var(--space-2) 0 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--space-1);\n}\n.notes li {\n padding-left: var(--space-2);\n border-left: 1px solid var(--border-default);\n font-size: var(--text-2xs-size, 11px);\n line-height: var(--text-2xs-line, 14px);\n color: var(--text-tertiary);\n overflow-wrap: anywhere;\n}\n\n.seatWindows { margin-top: var(--space-2); display: flex; flex-direction: column; gap: var(--space-2); }\n.credits { margin: var(--space-2) 0 0; font-size: var(--text-2xs-size, 11px); line-height: var(--text-2xs-line, 14px); color: var(--text-tertiary); }\n\n/* ---- local runtime ----------------------------------------------------- */\n.local { display: flex; flex-direction: column; gap: var(--space-1); }\n.mono {\n font-family: var(--font-mono);\n font-size: var(--text-2xs-size, 11px);\n color: var(--text-tertiary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.models { display: flex; flex-direction: column; gap: 2px; margin-top: var(--space-1); }\n.models code { font-size: var(--text-2xs-size, 11px); color: var(--text-secondary); }\n\n/* ---- running ----------------------------------------------------------- */\n.runningList { display: flex; flex-direction: column; gap: var(--space-1); }\n.runningRow { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }\n.runningOpen {\n flex: 1;\n display: grid;\n grid-template-columns: 6px minmax(0, 1fr);\n align-items: center;\n gap: var(--space-2);\n min-width: 0;\n min-height: var(--density-row, 32px);\n padding: 0 var(--space-2);\n margin-left: calc(-1 * var(--space-2));\n border-radius: var(--radius-xs);\n text-align: left;\n}\n.runningOpen {\n transition: background var(--duration-fast) var(--ease-standard);\n}\n.runningOpen:hover { background: var(--bg-hover); }\n.runningOpen:active { background: var(--bg-active); }\n/* --text-tertiary measures 4.40:1 on light --bg-hover — under the 4.5:1 floor\n once the row is hovered. The ground moves; the child's own colour does not. */\n.runningOpen:hover .runningMeta,\n.runningOpen:active .runningMeta { color: var(--text-secondary); }\n.runningDot {\n width: 6px;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--status-running-solid);\n animation: verse-pulse-res 1.8s ease-out infinite;\n}\n.runningTitle {\n grid-column: 2;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-sm-size);\n color: var(--text-primary);\n}\n.runningMeta {\n grid-column: 2;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-2xs-size, 11px);\n color: var(--text-tertiary);\n}\n.stop {\n flex-shrink: 0;\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-xs);\n color: var(--text-secondary);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-medium);\n transition: border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.stop:hover { border-color: var(--status-danger-solid); color: var(--status-danger-fg); }\n.stop:active { background: var(--status-danger-bg); }\n\n/* ---- usage ------------------------------------------------------------- */\n.usage { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2) var(--space-4); margin: 0; }\n.usage > div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }\n.usage dt {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n.usage dd {\n margin: 0;\n font-family: var(--font-display);\n font-size: var(--text-sm-size);\n font-variant-numeric: tabular-nums;\n color: var(--text-primary);\n}\n\n@keyframes verse-pulse-res {\n 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--status-running-solid) 55%, transparent); }\n 100% { box-shadow: 0 0 0 5px transparent; }\n}\n/* Two triggers, the same pattern as the duration tokens in tokens.css and the\n shimmer in global.css: the OS preference applies unless Settings explicitly\n asked for full motion, and data-motion=\"reduce\" forces it on for an operator\n whose OS says nothing. A persistent `animation` has a hardcoded duration, so\n collapsing --duration-* does NOT reach it — it needs both rules by name. */\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .runningDot { animation: none; }\n /* Guarded like every other motion rule in the app: an operator who chose\n Full motion in Settings against an OS reduce preference keeps it. The\n meter fills themselves are the Meter primitive's, whose transition reads\n --duration-base — already collapsed by the token file under both\n triggers — so only the disclosure marker needs naming here. */\n :root:not([data-motion=\"full\"]) .twist { transition: none; }\n}\n:root[data-motion=\"reduce\"] .runningDot { animation: none; }\n:root[data-motion=\"reduce\"] .twist { transition: none; }\n","/**\n * routes/verse/ResourcesPanel.tsx — the right column: every seat with its\n * subscription and how much of it is left, the local Ollama runtime, running\n * sessions with elapsed time + Stop, and the current session's cumulative\n * token usage.\n *\n * WHAT CHANGED AND WHY (docs/VERSE-TELEMETRY-V2.md).\n *\n * This list is the most-looked-at surface in the app and it showed a bare\n * \"unknown\" pill for every account — the health state, and nothing else. Two\n * separate faults produced that, and both are answered here:\n *\n * 1. THE WRONG FACT WAS BEING SHOWN. `health.state` is `unknown` for Claude\n * BY CONSTRUCTION, and the shared-evidence file behind it is scoped\n * `codex-native-metadata`, so it structurally cannot carry Claude or Grok\n * at all. Meanwhile the windows underneath it were rendered as raw ids\n * (\"seven_day_fable\") with a homemade 2px bar, all three of Claude's\n * windows given equal weight, and a reset collapsed to a bare clock time\n * even though Claude publishes a SENTENCE and no timestamp. So every row\n * now leads with the seat's plan and its BINDING window — the one that\n * actually blocks work — as a labelled <Meter>, with the reset rendered\n * verbatim.\n *\n * TWO FURTHER FACTS THE LIST WAS HIDING.\n *\n * 3. ONE BAR PER ACCOUNT. Claude's probe emits three windows — `five_hour`,\n * `seven_day`, and a per-model `seven_day_{model}` (claude-account-usage.ts\n * TITLES) — and Codex emits each bucket's primary and, only when the\n * provider sent one, its secondary (provider-observations.ts), with\n * credits as a separate fact. Folding the non-binding windows behind\n * \"N more windows\" showed one bar per account. Each reported window is\n * now its own bar with its own reset. A window that arrived without a\n * percent says \"no reading\"; a window the probe did not emit is not\n * drawn at all. Local seats still get no meter.\n * 4. SPENT SEATS START SHUT. A blocked seat (exhausted, or signed out)\n * defaults collapsed, because that is the row the operator does not need\n * open. Groups collapse too. Both choices persist under\n * `ashlr.verse.resources.v1` — not the shell key, whose shape is pinned —\n * so a refresh does not slam an opened spent seat shut again. `tight`\n * stays open: a Codex week at its limit with spendable credits is still\n * usable.\n * 2. THE DATA NEVER REFRESHED. `bootstrap` is a mount-time snapshot with no\n * SSE invalidation, and the collector needs ~75s to warm. Opening the app\n * cold guaranteed \"unknown\" forever. The chat surfaces now poll\n * (useSeatsRefresh), and this panel additionally says WHEN the reading\n * was taken and offers an explicit Refresh — because a number with no\n * timestamp is a claim about the present that nobody checked.\n *\n * Local seats are deliberately NOT given this treatment: they have no\n * subscription, no quota and no bill. They get their readiness and their\n * model, and nothing that implies a meter exists.\n */\nimport { useEffect, useState } from 'react';\nimport type { VerseBootstrap, VerseEngine, VerseSeat, VerseSession } from '../../data/api-types.js';\nimport { RefreshIndicator } from '../../components/primitives/RefreshIndicator.js';\nimport { SkeletonLine } from '../../components/primitives/Skeleton.js';\nimport { StatusBadge } from '../../components/primitives/StatusBadge.js';\nimport { Tooltip } from '../../components/primitives/Tooltip.js';\nimport { useQuery, useRefresh } from '../../data/hooks.js';\nimport { CapacityChip, SeatWindowMeter } from './SeatCapacity.js';\nimport { SessionRoots } from './SessionRoots.js';\nimport {\n groupIsOpen,\n readResourcesCollapse,\n reportedLimitBars,\n seatIsOpen,\n toggleGroupCollapse,\n toggleSeatCollapse,\n writeResourcesCollapse,\n type ResourcesCollapseState,\n} from './resources-collapse.js';\nimport { evidenceNote, seatSubscription, seatSubscriptionSentence, type SeatSubscriptionView } from './seat-subscription.js';\nimport { ENGINE_LABEL, formatClock, formatElapsed, groupSeats, projectName } from './verse-model.js';\nimport { verseBootstrapQuery } from './verse-queries.js';\nimport { formatTokens } from './verse-store.js';\nimport styles from './ResourcesPanel.module.css';\n\nexport interface ResourcesPanelProps {\n bootstrap: VerseBootstrap | undefined;\n sessions: readonly VerseSession[];\n current: VerseSession | null;\n onStop: (sessionId: string) => void;\n onOpen: (sessionId: string) => void;\n onClose: () => void;\n}\n\nfunction useNow(active: boolean): number {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n if (!active) return;\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [active]);\n return now;\n}\n\n/**\n * The newest instant any seat was actually observed at. NOT the time of the\n * last HTTP read: a successful request for a stale collector reading would\n * otherwise stamp old numbers as fresh, which is the one thing a freshness\n * line exists to prevent.\n */\nfunction newestObservation(seats: readonly VerseSeat[]): string | null {\n let newest: string | null = null;\n for (const seat of seats) {\n const at = seatSubscription(seat).observedAt;\n if (at === null) continue;\n if (newest === null || at > newest) newest = at;\n }\n return newest;\n}\n\nfunction useResourcesCollapse(): {\n state: ResourcesCollapseState;\n toggleGroup: (engine: VerseEngine) => void;\n toggleSeat: (seat: VerseSeat, view: SeatSubscriptionView) => void;\n} {\n const [state, setState] = useState(readResourcesCollapse);\n // Functional update so two quick toggles cannot drop each other. Writing\n // here is idempotent: the same previous state always produces the same next.\n const update = (fn: (prev: ResourcesCollapseState) => ResourcesCollapseState): void => {\n setState((prev) => {\n const next = fn(prev);\n writeResourcesCollapse(next);\n return next;\n });\n };\n return {\n state,\n toggleGroup: (engine) => update((prev) => toggleGroupCollapse(prev, engine)),\n toggleSeat: (seat, view) => update((prev) => toggleSeatCollapse(prev, seat.id, view.cls)),\n };\n}\n\nfunction SeatDetails({ seat, view }: { seat: VerseSeat; view: SeatSubscriptionView }) {\n const bars = reportedLimitBars(view);\n const sentence = seatSubscriptionSentence(seat, view);\n const ctx = seat.contextWindow === null ? 'ctx n/a' : `${formatTokens(seat.contextWindow)} ctx`;\n const models = `${seat.models.length} model${seat.models.length === 1 ? '' : 's'}`;\n // Provenance is a note too: a reading served from another process's shared\n // file is not a live probe and must not be presented as one.\n const provenance = evidenceNote(view.evidenceSource);\n const notes = provenance === null ? view.notes : [...view.notes, provenance];\n\n return (\n <>\n <div className={styles.seatMeta}>\n <span>{ENGINE_LABEL[seat.engine]}</span>\n {view.plan === null ? null : <><span aria-hidden=\"true\">·</span><span className={styles.plan}>{view.plan}</span></>}\n <span aria-hidden=\"true\">·</span>\n <span>{models}</span>\n <span aria-hidden=\"true\">·</span>\n <span className={styles.num}>{ctx}</span>\n </div>\n\n {view.kind === 'local' || bars.length === 0 ? (\n // Nothing measured, or a local seat with no subscription at all.\n // Say so. An empty bar would read \"plenty left\". A local seat's\n // health summary already travels in `notes`, so it is not repeated here.\n <>\n <p className={styles.seatSummary}>{view.summary}</p>\n {view.kind === 'local' || seat.health.summary === null || seat.health.summary === view.summary\n ? null\n : <p className={styles.seatSummary}>{seat.health.summary}</p>}\n </>\n ) : (\n <div className={styles.seatWindows}>\n {bars.map((windowView) => (\n <SeatWindowMeter\n key={windowView.id}\n windowView={windowView}\n ariaPrefix={seat.label}\n prominent={view.binding?.id === windowView.id}\n />\n ))}\n </div>\n )}\n\n {view.credits === null ? null : (\n // Credits are not a window. A spent week with a spendable balance is\n // not a blocked account, and there is no maximum to draw a bar against\n // (docs/VERSE-TELEMETRY-V2.md, Codex).\n <p className={styles.credits} title={view.creditsTitle ?? sentence}>{view.credits}</p>\n )}\n\n {/* The provider's own plain-language facts. Owner S's contract requires\n these be SHOWN — a version-pinned probe or a paused collector is an\n explanation, and swallowing it is what made every row read \"unknown\"\n with no way to find out why. */}\n {notes.length === 0 ? null : (\n <ul className={styles.notes}>\n {notes.map((note) => <li key={note}>{note}</li>)}\n </ul>\n )}\n </>\n );\n}\n\nfunction SeatRow({\n seat,\n open,\n onToggle,\n}: {\n seat: VerseSeat;\n open: boolean;\n onToggle: () => void;\n}) {\n const view = seatSubscription(seat);\n const sentence = seatSubscriptionSentence(seat, view);\n const bodyId = `verse-seat-${seat.id.replace(/[^A-Za-z0-9_-]/g, '-')}`;\n\n return (\n <li className={`${styles.seat} ${styles[`engine-${seat.engine}`] ?? ''}`} data-engine={seat.engine}\n data-capacity={view.cls} data-open={open ? 'true' : 'false'}>\n {/* The plan, the word and the reset were on a `title` hung off the inner\n label span — reachable by mouse only, and duplicated onto the chip\n beside it. One tooltip on the CONTROL carries it once, and a\n keyboard operator tabbing the seat list now gets it too. The button\n keeps its own aria-label: this describes, it does not name. */}\n <Tooltip label={sentence} placement=\"left\">\n <button\n type=\"button\"\n className={styles.seatToggle}\n aria-expanded={open}\n aria-controls={bodyId}\n aria-label={seat.label}\n onClick={onToggle}\n >\n <span className={styles.twist} data-open={open ? '' : undefined} aria-hidden=\"true\" />\n <span className={styles.seatLabel}>{seat.label}</span>\n {view.kind === 'local'\n ? <StatusBadge status={seat.health.state} tone={seat.health.state === 'ready' ? 'success' : seat.health.state === 'unavailable' ? 'danger' : 'unknown'} />\n : <CapacityChip view={view} />}\n </button>\n </Tooltip>\n\n {open\n ? <div id={bodyId}><SeatDetails seat={seat} view={view} /></div>\n // The one line that says WHY it is shut. The meters stay unmounted,\n // so a spent account is a row and not a page.\n : <p id={bodyId} className={styles.seatSummary}>{view.summary}</p>}\n </li>\n );\n}\n\nexport function ResourcesPanel({ bootstrap, sessions, current, onStop, onOpen, onClose }: ResourcesPanelProps) {\n const running = sessions.filter((s) => s.status === 'running');\n const now = useNow(running.length > 0);\n const groups = bootstrap ? groupSeats(bootstrap.seats) : [];\n const local = bootstrap?.localRuntime.ollama;\n\n // Subscribed only for the refreshing/settled signal — ChatSection owns the\n // data and passes it in. Same cache key, so this costs no extra request.\n const live = useQuery(verseBootstrapQuery);\n const refresh = useRefresh(verseBootstrapQuery);\n const observedAt = bootstrap ? newestObservation(bootstrap.seats) : null;\n const observedClock = observedAt === null ? null : formatClock(observedAt);\n const collapse = useResourcesCollapse();\n\n return (\n <aside className={styles.panel} aria-label=\"Resources\">\n <header className={styles.head}>\n <h2 className={styles.title}>Resources</h2>\n <button type=\"button\" className={styles.close} onClick={onClose} aria-label=\"Hide resources\">×</button>\n </header>\n <div className={styles.scroll}>\n <section className={styles.section} aria-labelledby=\"verse-res-seats\">\n <h3 id=\"verse-res-seats\" className={styles.sectionTitle}>\n <span>Seats</span>\n {/* A reading with no timestamp is a claim about the present that\n nobody checked. Say when, or say that nothing was read. */}\n <span className={styles.asOf}>\n {observedClock === null ? 'no reading yet' : `as of ${observedClock}`}\n </span>\n {live.status === 'refreshing' ? <RefreshIndicator label=\"Refreshing seats\" /> : null}\n <button type=\"button\" className={styles.refresh} onClick={refresh}>Refresh</button>\n </h3>\n {!bootstrap ? <div className={styles.skeleton}><SkeletonLine width=\"70%\" /><SkeletonLine width=\"50%\" /><SkeletonLine width=\"64%\" /></div>\n : groups.length === 0 ? <p className={styles.muted}>No seats discovered. Connect an account with <code>ashlr accounts</code> or start Ollama.</p>\n : groups.map((group) => {\n const open = groupIsOpen(collapse.state, group.engine);\n const listId = `verse-res-group-${group.engine}`;\n return (\n <div key={group.engine} className={styles.engineGroup}>\n <h4 className={styles.engineTitle}>\n <button\n type=\"button\"\n className={styles.groupToggle}\n aria-expanded={open}\n aria-controls={listId}\n aria-label={`${ENGINE_LABEL[group.engine]} seats`}\n onClick={() => collapse.toggleGroup(group.engine)}\n >\n <span className={styles.twist} data-open={open ? '' : undefined} aria-hidden=\"true\" />\n <span>{ENGINE_LABEL[group.engine]}</span>\n <span className={styles.count}>{group.seats.length}</span>\n </button>\n </h4>\n {open ? (\n <ul id={listId} className={styles.seatList}>\n {group.seats.map((seat) => {\n const view = seatSubscription(seat);\n return (\n <SeatRow\n key={seat.id}\n seat={seat}\n open={seatIsOpen(collapse.state, seat.id, view.cls)}\n onToggle={() => collapse.toggleSeat(seat, view)}\n />\n );\n })}\n </ul>\n ) : <ul id={listId} className={styles.seatList} hidden />}\n </div>\n );\n })}\n </section>\n\n <section className={styles.section} aria-labelledby=\"verse-res-local\">\n <h3 id=\"verse-res-local\" className={styles.sectionTitle}>Local runtime</h3>\n {!local ? <SkeletonLine width=\"60%\" /> : (\n <div className={styles.local}>\n <div className={styles.seatHead}>\n <span className={styles.seatLabel}>Ollama</span>\n <StatusBadge status={local.reachable ? 'ready' : 'unavailable'} tone={local.reachable ? 'success' : 'danger'}>\n {local.reachable ? 'reachable' : 'unreachable'}\n </StatusBadge>\n </div>\n <p className={styles.mono} title={local.baseUrl}>{local.baseUrl}</p>\n {local.reachable ? (\n local.models.length > 0\n ? <ul className={styles.models}>{local.models.map((m) => <li key={m}><code>{m}</code></li>)}</ul>\n : <p className={styles.muted}>No models pulled yet.</p>\n ) : <p className={styles.muted}>Start Ollama to enable local seats.</p>}\n </div>\n )}\n </section>\n\n <section className={styles.section} aria-labelledby=\"verse-res-running\">\n <h3 id=\"verse-res-running\" className={styles.sectionTitle}>Running <span className={styles.count}>{running.length}</span></h3>\n {running.length === 0 ? <p className={styles.muted}>Nothing running.</p> : (\n <ul className={styles.runningList}>\n {running.map((s) => (\n <li key={s.id} className={styles.runningRow}>\n <button type=\"button\" className={styles.runningOpen} onClick={() => onOpen(s.id)} title={s.title}>\n <span className={styles.runningDot} role=\"img\" aria-label=\"Running\" />\n <span className={styles.runningTitle}>{s.title || 'Untitled chat'}</span>\n <span className={styles.runningMeta}>{projectName(s.projectPath, bootstrap?.projects ?? [])} · {formatElapsed(now - new Date(s.updatedAt).getTime())}</span>\n </button>\n <button type=\"button\" className={styles.stop} onClick={() => onStop(s.id)} aria-label={`Stop ${s.title || 'chat'}`}>Stop</button>\n </li>\n ))}\n </ul>\n )}\n </section>\n\n {/* Folders this chat reaches, each with its own branch and dirty\n count — a turn that edits two repos produces two diffs, and they\n have to be attributable. Renders nothing for a single-folder chat,\n which already says its folder everywhere else. `turnCount` is the\n refresh key: a finished turn may have changed a branch. */}\n <SessionRoots session={current} refreshKey={current?.turnCount ?? 0} />\n\n <section className={styles.section} aria-labelledby=\"verse-res-usage\">\n <h3 id=\"verse-res-usage\" className={styles.sectionTitle}>This chat</h3>\n {!current ? <p className={styles.muted}>Select a chat to see its usage.</p> : (\n <dl className={styles.usage}>\n <div><dt>Input</dt><dd>{formatTokens(current.usage.inputTokens)}</dd></div>\n <div><dt>Output</dt><dd>{formatTokens(current.usage.outputTokens)}</dd></div>\n <div><dt>Cache read</dt><dd>{formatTokens(current.usage.cacheReadTokens)}</dd></div>\n <div><dt>Cache write</dt><dd>{formatTokens(current.usage.cacheCreationTokens)}</dd></div>\n <div><dt>Turns</dt><dd>{current.turnCount}</dd></div>\n <div><dt>Context</dt><dd>{formatTokens(current.usage.contextTokens)}{current.usage.contextWindow ? ` / ${formatTokens(current.usage.contextWindow)}` : ''}</dd></div>\n </dl>\n )}\n </section>\n </div>\n </aside>\n );\n}\n","/* Deliberately the same field/label/button vocabulary as\n NewChatDialog.module.css: the two dialogs sit one click apart and a second\n visual language between them would read as a second application. */\n.width { width: min(620px, calc(100vw - 32px)); }\n\n.form { display: grid; gap: var(--space-4); }\n.field { display: grid; gap: var(--space-1); min-width: 0; }\n.label {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.select,\n.input {\n width: 100%;\n min-height: var(--control-h);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-input);\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n text-overflow: ellipsis;\n transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);\n}\n.input::placeholder { color: var(--text-tertiary); }\n.select:hover:not(:disabled),\n.input:hover:not(:disabled) { border-color: var(--border-strong); }\n.select:focus-visible,\n.input:focus-visible { border-color: var(--border-focus); box-shadow: var(--shadow-focus-ring); }\n\n.hint { font-size: var(--text-xs-size); line-height: var(--text-xs-line); color: var(--text-tertiary); }\n.error {\n padding-left: var(--space-3);\n border-left: 2px solid var(--status-danger-solid);\n color: var(--status-danger-fg);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n\n/* One folder: path, then its controls. Wraps rather than shrinking the path\n field to nothing at narrow widths. */\n.rootRow {\n display: flex;\n flex-wrap: wrap;\n gap: var(--space-2);\n align-items: center;\n margin-top: var(--space-2);\n}\n.rootRow .input { flex: 1 1 220px; min-width: 0; }\n\n.rowButton,\n.addRoot {\n flex: none;\n min-height: var(--control-h-sm);\n padding: var(--space-1) var(--space-2);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n background: var(--surface-raised);\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n cursor: pointer;\n transition: border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.rowButton:hover:not(:disabled),\n.addRoot:hover { border-color: var(--border-strong); color: var(--text-primary); }\n.rowButton:disabled { opacity: 0.4; cursor: not-allowed; }\n.addRoot { margin-top: var(--space-2); justify-self: start; }\n\n.checkbox {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n font-size: var(--text-sm-size);\n color: var(--text-secondary);\n}\n\n.priorityRow {\n display: flex;\n gap: var(--space-2);\n align-items: center;\n margin-top: var(--space-2);\n}\n.priorityPath {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n.priorityRow .select { flex: 0 0 auto; width: auto; min-width: 120px; }\n\n.actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }\n.spacer { flex: 1 1 auto; }\n.confirm { font-size: var(--text-xs-size); color: var(--text-secondary); }\n\n.cancel,\n.save,\n.remove,\n.danger {\n min-height: var(--control-h);\n padding: 0 var(--space-4);\n border: 1px solid transparent;\n border-radius: var(--radius-sm);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-medium);\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.cancel,\n.remove { color: var(--text-secondary); }\n.cancel:hover,\n.remove:hover { background: var(--bg-hover); color: var(--text-primary); }\n.danger { color: var(--status-danger-fg); border-color: var(--status-danger-solid); }\n.danger:hover:not(:disabled) { background: var(--bg-hover); }\n.save { background: var(--accent-600); color: var(--accent-contrast); }\n.save:hover:not(:disabled) { background: var(--accent-700); }\n.save:disabled,\n.danger:disabled,\n.remove:disabled { opacity: 0.4; cursor: not-allowed; }\n","/**\n * routes/verse/workspaces/SavedProjectDialog.tsx — create, rename, reorder and\n * delete a SAVED PROJECT (a workspace in `~/.ashlr/verse/workspaces.json`).\n *\n * Why this dialog exists: the workspace routes were complete and nothing in\n * the console ever called them, so the only way to get a saved project was to\n * hand-edit a JSON file. A folder the operator typed into the new-chat dialog\n * came back only AFTER a chat had been created on it. Now a folder can be kept\n * before any chat exists, which is what \"open my project again tomorrow\"\n * actually requires.\n *\n * Three honesty rules are load-bearing here:\n *\n * - THE FIRST FOLDER IS THE PRIMARY. It is the session's cwd, and it is the\n * only folder a Grok seat can reach, so the reorder buttons are not\n * cosmetic and the first row says \"Primary folder\" rather than \"Folder 1\".\n * - PRIORITY ORDERS, IT NEVER GRANTS. `ROOT_PRIORITY_NOTE` is rendered at the\n * point of the choice; ranking a repo `critical` does not enrol it.\n * - NO SEAT IS CHOSEN HERE, so no per-seat caveat can be honest. The dialog\n * states the engine rule flatly instead (`MULTI_ROOT_ENGINE_NOTE`); the\n * seat-specific warning belongs in the new-chat dialog, where a seat exists.\n */\nimport { useEffect, useId, useState, type FormEvent } from 'react';\nimport type { VerseRootPriority, VerseWorkspace } from '../../../data/api-types.js';\nimport { Dialog } from '../../../components/primitives/Dialog.js';\nimport { nativePickerAvailable, pickDirectory } from '../folder-picker.js';\nimport {\n createVerseWorkspace,\n deleteVerseWorkspace,\n setVerseFocusSection,\n setVerseRootPriority,\n updateVerseWorkspace,\n} from '../verse-queries.js';\nimport {\n MAX_WORKSPACE_ROOTS,\n MULTI_ROOT_ENGINE_NOTE,\n moveRoot,\n priorityOf,\n ROOT_PRIORITY_LABEL,\n ROOT_PRIORITY_NOTE,\n ROOT_PRIORITY_ORDER,\n rootRowLabel,\n validateWorkspaceDraft,\n workspaceRootPaths,\n} from '../workspace-model.js';\nimport styles from './SavedProjectDialog.module.css';\n\nexport interface SavedProjectDialogProps {\n open: boolean;\n /** The project being edited, or null to create a new one. */\n workspace: VerseWorkspace | null;\n /** Folder set to pre-fill a NEW project with (primary first). */\n initialRoots?: readonly string[];\n /** Per-path priority as the server holds it. Absent key means `normal`. */\n priorities?: Readonly<Record<string, VerseRootPriority>>;\n /** The section the autonomous lane is focused on, if any. */\n focusSectionId?: string | null;\n onClose: () => void;\n onSaved?: (workspace: VerseWorkspace) => void;\n onDeleted?: (id: string) => void;\n}\n\nexport function SavedProjectDialog(props: SavedProjectDialogProps) {\n const { open, workspace, initialRoots, priorities, focusSectionId = null, onClose, onSaved, onDeleted } = props;\n const titleId = useId();\n const nameId = useId();\n const [name, setName] = useState('');\n const [roots, setRoots] = useState<string[]>(['']);\n const [section, setSection] = useState(false);\n const [focused, setFocused] = useState(false);\n const [priorityDraft, setPriorityDraft] = useState<Record<string, VerseRootPriority>>({});\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Reset on the OPEN transition only, for the same reason NewChatDialog does:\n // the workspace list is a fresh array on every invalidation, and re-running\n // this on it would wipe a half-typed path.\n useEffect(() => {\n if (!open) return;\n const existing = workspace;\n setName(existing?.name ?? '');\n setRoots(existing ? workspaceRootPaths(existing) : [...(initialRoots ?? [])].filter((r) => r.length > 0));\n setSection(existing?.section ?? false);\n setFocused(existing !== null && focusSectionId === existing.id);\n setPriorityDraft({});\n setConfirmingDelete(false);\n setBusy(false);\n setError(null);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- open transition only; the inputs are read once, on purpose.\n }, [open]);\n\n // Always at least one row, so there is somewhere to type the primary folder.\n const rows = roots.length === 0 ? [''] : roots;\n const showPicker = nativePickerAvailable();\n\n function setRow(index: number, value: string) {\n setRoots(rows.map((r, i) => (i === index ? value : r)));\n }\n\n async function choose(index: number) {\n const picked = await pickDirectory();\n if (picked !== null && picked.length > 0) setRow(index, picked);\n }\n\n function priorityFor(path: string): VerseRootPriority {\n return priorityDraft[path] ?? priorityOf(path, priorities);\n }\n\n async function submit(event: FormEvent) {\n event.preventDefault();\n const draft = validateWorkspaceDraft(name, rows);\n if (!draft.ok) {\n setError(draft.error);\n return;\n }\n setBusy(true);\n setError(null);\n try {\n const saved = workspace === null\n ? await createVerseWorkspace({ name: draft.name, roots: draft.roots, section })\n : await updateVerseWorkspace(workspace.id, { name: draft.name, roots: draft.roots, section });\n // Priority is an attribute OF THE REPO, held once per path, so it is a\n // separate call per changed path rather than part of the workspace body.\n for (const path of draft.roots) {\n const next = priorityDraft[path];\n if (next !== undefined && next !== priorityOf(path, priorities)) {\n await setVerseRootPriority(path, next);\n }\n }\n const wasFocused = workspace !== null && focusSectionId === workspace.id;\n if (section && focused !== wasFocused) {\n await setVerseFocusSection(focused ? saved.id : null);\n }\n onSaved?.(saved);\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n }\n\n async function remove() {\n if (workspace === null) return;\n setBusy(true);\n setError(null);\n try {\n await deleteVerseWorkspace(workspace.id);\n onDeleted?.(workspace.id);\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setBusy(false);\n }\n }\n\n return (\n <Dialog\n open={open}\n onClose={onClose}\n titleId={titleId}\n title={workspace === null ? 'Save a project' : 'Edit project'}\n description=\"Saved projects stay in the picker — they do not need a chat on them first.\"\n widthClassName={styles.width}\n >\n <form className={styles.form} onSubmit={(event) => void submit(event)} noValidate>\n <label className={styles.field} htmlFor={nameId}>\n <span className={styles.label}>Name</span>\n <input id={nameId} className={styles.input} value={name} onChange={(event) => setName(event.target.value)}\n placeholder=\"Defaults to the folder’s own name\" maxLength={120} autoComplete=\"off\" />\n </label>\n\n <div className={styles.field}>\n <span className={styles.label}>Folders</span>\n <p className={styles.hint}>\n The first folder is the primary: it is the chat’s working directory. Move a folder to the top to make it\n the primary.\n </p>\n {rows.map((root, index) => (\n <div key={index} className={styles.rootRow}>\n <input\n className={styles.input}\n value={root}\n onChange={(event) => setRow(index, event.target.value)}\n placeholder=\"/absolute/path/to/folder\"\n aria-label={rootRowLabel(index)}\n autoComplete=\"off\"\n spellCheck={false}\n />\n {showPicker ? (\n <button type=\"button\" className={styles.rowButton} onClick={() => void choose(index)}\n aria-label={`Choose ${rootRowLabel(index).toLowerCase()}`}>Choose folder…</button>\n ) : null}\n <button type=\"button\" className={styles.rowButton} disabled={index === 0}\n onClick={() => setRoots(moveRoot(rows, index, 'up'))}\n aria-label={`Move ${rootRowLabel(index).toLowerCase()} up`}>↑</button>\n <button type=\"button\" className={styles.rowButton} disabled={index === rows.length - 1}\n onClick={() => setRoots(moveRoot(rows, index, 'down'))}\n aria-label={`Move ${rootRowLabel(index).toLowerCase()} down`}>↓</button>\n <button type=\"button\" className={styles.rowButton} disabled={rows.length === 1}\n onClick={() => setRoots(rows.filter((_, i) => i !== index))}\n aria-label={`Remove ${rootRowLabel(index).toLowerCase()}`}>Remove</button>\n </div>\n ))}\n {rows.length < MAX_WORKSPACE_ROOTS ? (\n <button type=\"button\" className={styles.addRoot} onClick={() => setRoots([...rows, ''])}>Add a folder</button>\n ) : null}\n {rows.length > 1 ? <p className={styles.hint}>{MULTI_ROOT_ENGINE_NOTE}</p> : null}\n </div>\n\n <div className={styles.field}>\n <label className={styles.checkbox}>\n <input type=\"checkbox\" checked={section} onChange={(event) => setSection(event.target.checked)} />\n <span>Offer this project to the autonomous lane as a section</span>\n </label>\n {section ? (\n <>\n <label className={styles.checkbox}>\n <input type=\"checkbox\" checked={focused} onChange={(event) => setFocused(event.target.checked)} />\n <span>Focus the fleet on this section</span>\n </label>\n <p className={styles.hint}>{ROOT_PRIORITY_NOTE}</p>\n {rows.filter((r) => r.trim().length > 0).map((root, index) => (\n <div key={`${root}-${index}`} className={styles.priorityRow}>\n <span className={styles.priorityPath} title={root}>{root}</span>\n <select\n className={styles.select}\n aria-label={`Priority for ${root}`}\n value={priorityFor(root.trim())}\n onChange={(event) =>\n setPriorityDraft({ ...priorityDraft, [root.trim()]: event.target.value as VerseRootPriority })}\n >\n {ROOT_PRIORITY_ORDER.map((p) => (\n <option key={p} value={p}>{ROOT_PRIORITY_LABEL[p]}</option>\n ))}\n </select>\n </div>\n ))}\n </>\n ) : null}\n </div>\n\n {error ? <p role=\"alert\" className={styles.error}>{error}</p> : null}\n\n <div className={styles.actions}>\n {workspace === null ? null : confirmingDelete ? (\n <>\n <span className={styles.confirm}>Forget this project? Chats already on it are untouched.</span>\n <button type=\"button\" className={styles.danger} onClick={() => void remove()} disabled={busy}>Forget</button>\n <button type=\"button\" className={styles.cancel} onClick={() => setConfirmingDelete(false)}>Keep</button>\n </>\n ) : (\n <button type=\"button\" className={styles.remove} onClick={() => setConfirmingDelete(true)} disabled={busy}>\n Forget project\n </button>\n )}\n <span className={styles.spacer} />\n <button type=\"button\" className={styles.cancel} onClick={onClose}>Cancel</button>\n <button type=\"submit\" className={styles.save} disabled={busy}>{busy ? 'Saving…' : 'Save project'}</button>\n </div>\n </form>\n </Dialog>\n );\n}\n","/* The Projects section sits above the chat groups and borrows their type\n scale exactly, so it reads as one more group heading rather than a second\n kind of list. */\n.projects {\n flex-shrink: 0;\n padding: var(--space-3) 0 var(--space-2);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n.head {\n font-family: var(--font-display);\n display: flex;\n align-items: center;\n gap: var(--space-2);\n padding: 0 var(--space-2) var(--space-1) var(--space-3);\n font-size: var(--text-2xs-size, 11px);\n line-height: 1.4;\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n.headText { flex: 1 1 auto; min-width: 0; }\n\n.add {\n flex: none;\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--control-h-xs, 20px);\n height: var(--control-h-xs, 20px);\n border-radius: var(--radius-sm);\n color: var(--text-tertiary);\n transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.add:hover { color: var(--text-primary); background: var(--bg-hover); }\n.add:active { background: var(--bg-active); }\n\n.list { display: flex; flex-direction: column; list-style: none; margin: 0; padding: 0; }\n\n.project {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n width: 100%;\n min-height: var(--density-row, 32px);\n padding: 0 var(--space-3);\n color: var(--text-secondary);\n text-align: left;\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.project:hover { background: var(--bg-hover); color: var(--text-primary); }\n.project:active { background: var(--bg-active); }\n\n.name {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.summary {\n flex: none;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n color: var(--text-tertiary);\n}\n.project:hover .summary { color: var(--text-secondary); }\n\n.empty {\n padding: var(--space-1) var(--space-3) var(--space-1);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line);\n}\n","/**\n * routes/verse/workspaces/SavedProjects.tsx — the sidebar's \"Projects\"\n * section: every saved project, and the one button that creates one.\n *\n * SELF-SUPPLIED ON PURPOSE. It reads `verseWorkspacesQuery` itself rather\n * than taking the list as a prop, because the sidebar's props are owned by the\n * chat section and this list has exactly one consumer. The key is the same one\n * the new-chat dialog's list is read from, so the cache serves both from one\n * request and the picker and this list can never disagree.\n *\n * Quiet when the read fails: an older server has no /api/verse/workspaces at\n * all, and a permanent red line in the sidebar for a feature that server does\n * not have would be noise, not honesty. The \"Save a project\" button stays —\n * pressing it surfaces the real refusal from the server, in the dialog.\n */\nimport { useState } from 'react';\nimport type { VerseWorkspace } from '../../../data/api-types.js';\nimport { useQuery } from '../../../data/hooks.js';\nimport { PlusIcon } from '../verse-icons.js';\nimport { verseWorkspacesQuery } from '../verse-queries.js';\nimport { workspacePrimary, workspaceSummary } from '../workspace-model.js';\nimport { SavedProjectDialog } from './SavedProjectDialog.js';\nimport styles from './SavedProjects.module.css';\n\nexport function SavedProjects() {\n const query = useQuery(verseWorkspacesQuery);\n const workspaces = query.data?.workspaces ?? [];\n const [editing, setEditing] = useState<{ open: boolean; workspace: VerseWorkspace | null }>(\n { open: false, workspace: null },\n );\n\n return (\n <section className={styles.projects} aria-label=\"Saved projects\">\n <h2 className={styles.head}>\n <span className={styles.headText}>Projects</span>\n <button\n type=\"button\"\n className={styles.add}\n title=\"Save a project\"\n aria-label=\"Save a project\"\n onClick={() => setEditing({ open: true, workspace: null })}\n >\n <PlusIcon />\n </button>\n </h2>\n\n {workspaces.length > 0 ? (\n <ul className={styles.list}>\n {workspaces.map((workspace) => {\n const primary = workspacePrimary(workspace) ?? '';\n return (\n <li key={workspace.id}>\n <button\n type=\"button\"\n className={styles.project}\n title={primary}\n aria-label={`Edit project ${workspace.name}`}\n onClick={() => setEditing({ open: true, workspace })}\n >\n <span className={styles.name}>{workspace.name}</span>\n <span className={styles.summary}>{workspaceSummary(workspace)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n ) : query.status === 'error' ? null : (\n <p className={styles.empty}>No saved projects yet.</p>\n )}\n\n <SavedProjectDialog\n open={editing.open}\n workspace={editing.workspace}\n priorities={query.data?.priorities}\n focusSectionId={query.data?.focusSectionId ?? null}\n onClose={() => setEditing({ open: false, workspace: null })}\n />\n </section>\n );\n}\n",".sidebar {\n display: flex;\n flex-direction: column;\n min-height: 0;\n background: var(--bg-canvas);\n}\n\n/* ---- head: search + new chat + collapse -------------------------------- */\n.head {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: var(--space-1);\n /* DESIGN-V2 §4: header strips are --strip-height, and the token is what the\n desktop shell's inset maths is written against. */\n height: var(--strip-height);\n padding: 0 var(--space-2) 0 var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n}\n\n/* ---- desktop shell (see desktop/README.md \"Desktop shell contract\") -----\n * The Tauri window uses an overlay title bar, so macOS paints the traffic\n * lights over the window's top-left corner — which is exactly where this\n * header's search field sits. Without this the close/minimise/zoom buttons\n * overlap the search input and both become hard to hit.\n *\n * The rail already does this (VerseApp.module.css `.rail`); the sidebar was\n * simply missed, and it is the one panel that actually reaches the corner.\n * `--app-titlebar-height` is absent in a browser, so this resolves to the\n * plain strip height there and nothing moves. */\n.head {\n position: relative;\n height: calc(var(--strip-height) + var(--app-titlebar-height, 0px));\n padding-top: var(--app-titlebar-height, 0px);\n}\n\n/* The cleared strip is draggable, so the window still moves by its top edge\n * rather than becoming a dead band. Zero-height in a browser, where\n * --app-titlebar-height is absent, so it can never eat a click there. */\n.headDragStrip {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: var(--app-titlebar-height, 0px);\n -webkit-app-region: drag;\n app-region: drag;\n pointer-events: auto;\n}\n\n.search {\n position: relative;\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n}\n.searchIcon {\n position: absolute;\n left: 0;\n display: flex;\n color: var(--text-tertiary);\n pointer-events: none;\n}\n.search input {\n width: 100%;\n height: var(--control-h-sm);\n padding: 0 var(--space-2) 0 22px;\n border: 0;\n background: transparent;\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n}\n.search input::placeholder { color: var(--text-tertiary); }\n.search input::-webkit-search-cancel-button { appearance: none; }\n/* The global :focus-visible ring is the indicator here — the field is\n borderless, so nothing else would show keyboard focus. */\n.search:focus-within .searchIcon { color: var(--accent-500); }\n\n.iconButton {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--control-h-sm);\n height: var(--control-h-sm);\n border-radius: var(--radius-sm);\n color: var(--text-tertiary);\n transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.iconButton:hover:not(:disabled) { color: var(--text-primary); background: var(--bg-hover); }\n/* Press state, same contract as the Button primitive: the ground steps one\n more notch, nothing moves. */\n.iconButton:active:not(:disabled) { background: var(--bg-active); }\n.iconButton:disabled { color: var(--text-disabled); cursor: not-allowed; }\n\n/* ---- list -------------------------------------------------------------- */\n.scroll {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding-bottom: var(--space-4);\n scrollbar-gutter: stable;\n}\n.skeleton { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4) var(--space-3); }\n.error {\n display: grid;\n gap: var(--space-2);\n justify-items: start;\n padding: var(--space-4) var(--space-3);\n color: var(--status-danger-fg);\n font-size: var(--text-sm-size);\n}\n.error button {\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n color: var(--text-primary);\n font-size: var(--text-xs-size);\n transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);\n}\n.error button:hover { background: var(--bg-hover); border-color: var(--border-strong); }\n.error button:active { background: var(--bg-active); }\n.empty {\n padding: var(--space-8) var(--space-4);\n color: var(--text-tertiary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.emptyTitle { color: var(--text-secondary); font-weight: var(--font-weight-medium); margin-bottom: var(--space-1); }\n/* An empty list is a dead end unless it carries the way out of itself. Same\n shape as .error button, so the two read as one control vocabulary. */\n.emptyAction {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--control-h-sm);\n margin-top: var(--space-3);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n color: var(--text-primary);\n font-size: var(--text-xs-size);\n transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);\n}\n.emptyAction:hover { background: var(--bg-hover); border-color: var(--border-strong); }\n.emptyAction:active { background: var(--bg-active); }\n.emptyKey {\n padding: 0 var(--space-1);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-xs);\n background: var(--bg-hover);\n color: var(--text-secondary);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n}\n\n.group { padding-top: var(--space-4); }\n.groupTitle {\n font-family: var(--font-display);\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n padding: 0 var(--space-3) var(--space-1);\n font-size: var(--text-2xs-size, 11px);\n line-height: 1.4;\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n.groupName { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.enrolled { flex-shrink: 0; color: var(--text-tertiary); opacity: 0.7; font-weight: var(--font-weight-regular); }\n/* How many chats sit under this heading, pushed to the far edge. It is the\n one number that makes a long list scannable without opening anything, and\n it is aria-hidden because the group's own <section> already names itself. */\n.groupCount {\n flex-shrink: 0;\n margin-left: auto;\n font-variant-numeric: tabular-nums;\n letter-spacing: 0;\n color: var(--text-tertiary);\n font-weight: var(--font-weight-regular);\n}\n\n.list { display: flex; flex-direction: column; list-style: none; margin: 0; padding: 0; }\n/* The row is wrapped in a Tooltip, so the <li>'s child is the tooltip's own\n wrapper span and not the button. That wrapper is shrink-to-fit, which would\n collapse a full-width row and defeat .sessionText's ellipsis. These two\n rules re-stretch whatever spans the primitive interposes, addressed by\n STRUCTURE rather than by its hashed class names, so they survive the\n primitive being swapped.\n The `:not([role='tooltip'])` is load-bearing: the bubble is a sibling\n span, and a blanket `display: block` here would beat its `hidden`\n attribute and leave the tooltip painted open over the transcript — the\n exact failure this change exists to remove. */\n.list > li { display: block; min-width: 0; }\n.list > li > span:not([role='tooltip']),\n.list > li > span > span:not([role='tooltip']) {\n display: block;\n width: 100%;\n min-width: 0;\n}\n\n/* One row: 2px engine marker · title · state · relative time. */\n.session {\n position: relative;\n display: grid;\n grid-template-columns: 2px minmax(0, 1fr) auto auto;\n align-items: center;\n gap: var(--space-2);\n width: 100%;\n min-height: var(--density-row, 32px);\n padding: 0 var(--space-3) 0 var(--space-3);\n color: var(--text-secondary);\n text-align: left;\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.session:hover { background: var(--bg-hover); color: var(--text-primary); }\n.session:active { background: var(--bg-active); }\n.session[aria-current] { background: var(--bg-selected); color: var(--text-primary); }\n/* WHICH ROW AM I ON. --bg-selected and --bg-hover are one step apart, so a\n hovered row and the open one read the same at a glance and the list loses\n its \"you are here\". The selected row now carries THREE non-colour signals\n as well: its engine marker runs the full row height, its title steps up a\n weight, and a solid accent rule sits on the leading edge. None of them is\n colour alone — DESIGN-V2 §6. */\n.session[aria-current] { font-weight: var(--font-weight-medium); }\n.session[aria-current]::before {\n content: '';\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n width: 2px;\n background: var(--accent-500);\n}\n/* The engine marker is deliberately left alone here. Growing it as well put\n two 2px rules a dozen pixels apart and the row read as striped; the edge\n rule is the \"you are here\" and the marker stays the engine's identity. */\n\n.marker {\n width: 2px;\n height: var(--engine-marker-h);\n border-radius: 1px;\n background: var(--verse-engine, var(--text-tertiary));\n}\n.engine-claude { --verse-engine: var(--engine-claude, #c96442); }\n.engine-codex { --verse-engine: var(--engine-codex, #10a37f); }\n.engine-grok { --verse-engine: var(--engine-grok, #6b7280); }\n.engine-local { --verse-engine: var(--engine-local, #7c5cff); }\n\n.sessionText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n\n/* Running: a pulsing dot, never a spinner. */\n.running {\n width: 6px;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--status-running-solid);\n animation: verse-pulse 1.8s ease-out infinite;\n}\n.errored {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 12px;\n height: 12px;\n color: var(--status-danger-fg);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-bold);\n line-height: 1;\n}\n\n/* A turn in flight on a seat whose binding window is spent. Same footprint as\n the error mark so no row changes height, and it carries a glyph plus an\n accessible name — the colour is never the only signal. */\n.seatSpent {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 12px;\n height: 12px;\n color: var(--status-danger-fg);\n font-size: 9px;\n line-height: 1;\n}\n\n.time {\n flex-shrink: 0;\n min-width: 3ch;\n text-align: right;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n}\n/* --text-tertiary is a direct declaration on a CHILD, so the parent's\n :hover/[aria-current] colour change does not reach it — only the ground\n under it moves. Measured on --bg-selected it is 3.95:1 in light and 4.40:1\n in dark, both under the 4.5:1 floor in DESIGN-V2 §6; --text-secondary is\n 6.32:1 on the worst of them. design/tokens-contrast.test.ts now pins the\n token pair so the gap cannot reopen. */\n.session:hover .time,\n.session[aria-current] .time { color: var(--text-secondary); }\n\n/* ---- footer ------------------------------------------------------------ */\n.footer {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n height: var(--control-h);\n padding: 0 var(--space-3);\n border-top: 1px solid var(--border-subtle);\n}\n.footerButton {\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n margin-left: calc(-1 * var(--space-2));\n border-radius: var(--radius-xs);\n color: var(--text-tertiary);\n font-size: var(--text-2xs-size, 11px);\n transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.footerButton:hover { color: var(--text-primary); background: var(--bg-hover); }\n.footerButton:active { background: var(--bg-active); }\n\n@keyframes verse-pulse {\n 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--status-running-solid) 55%, transparent); }\n 100% { box-shadow: 0 0 0 5px transparent; }\n}\n/* Two triggers, the same pattern as the duration tokens in tokens.css and the\n shimmer in global.css: the OS preference applies unless Settings explicitly\n asked for full motion, and data-motion=\"reduce\" forces it on for an operator\n whose OS says nothing. A persistent `animation` has a hardcoded duration, so\n collapsing --duration-* does NOT reach it — it needs both rules by name. */\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .running { animation: none; }\n}\n:root[data-motion=\"reduce\"] .running { animation: none; }\n","/**\n * routes/verse/Sidebar.tsx — search, \"New chat\", and every session grouped\n * by project. One row is: a 2px engine-identity marker, the title, and a\n * right-aligned relative time. A running chat shows a pulsing dot, never a\n * spinner (DESIGN §4) — a spinner claims the UI is busy; the dot says the\n * agent is.\n *\n * Above the chats sits the SAVED PROJECTS list. The chat groups below it are\n * derived from history — a folder appears only once something has been\n * started on it — so they cannot answer \"reopen what I was working on before\n * I ever sent a message\". The projects section is the registry the operator\n * writes deliberately, and it is the only place in the console that creates\n * one.\n *\n * Seat health and the local runtime live in the resources panel, and the\n * theme toggle lives in the shell rail, so nothing competes with the list.\n *\n * ONE exception, added deliberately: a chat that is RUNNING on a seat whose\n * binding window is spent gets a small marker. That combination is worth\n * interrupting for — the turn in flight is the one about to fail — and it is\n * rare enough that the list stays quiet. Every other row says nothing new;\n * the capacity rides in the row's `title` where it costs no pixels.\n */\nimport { useId } from 'react';\nimport type { VerseProject, VerseSeat, VerseSession } from '../../data/api-types.js';\nimport type { QueryStatus } from '../../data/cache.js';\nimport { RefreshIndicator } from '../../components/primitives/RefreshIndicator.js';\nimport { SkeletonLine } from '../../components/primitives/Skeleton.js';\nimport { Tooltip } from '../../components/primitives/Tooltip.js';\nimport { PlusIcon, SearchIcon, SidebarIcon } from './verse-icons.js';\nimport { seatSubscription } from './seat-subscription.js';\nimport { formatRelative, groupSessions, seatById, seatPillLabel } from './verse-model.js';\nimport { SavedProjects } from './workspaces/SavedProjects.js';\nimport styles from './Sidebar.module.css';\n\nexport interface SidebarProps {\n sessions: readonly VerseSession[];\n sessionsStatus: QueryStatus;\n sessionsError: string | null;\n projects: readonly VerseProject[];\n seats: readonly VerseSeat[];\n selectedId: string | null;\n query: string;\n onQuery: (value: string) => void;\n onSelect: (id: string) => void;\n onNew: () => void;\n onRetry: () => void;\n onCollapse: () => void;\n onDisconnect: () => void;\n}\n\nexport function Sidebar(props: SidebarProps) {\n const { sessions, sessionsStatus, sessionsError, projects, seats, selectedId, query, onQuery, onSelect, onNew,\n onRetry, onCollapse, onDisconnect } = props;\n const searchId = useId();\n const groups = groupSessions(sessions, projects, query);\n const loading = sessionsStatus === 'loading' || (sessionsStatus === 'idle' && sessions.length === 0);\n\n return (\n <nav className={styles.sidebar} aria-label=\"Chats\">\n <div className={styles.head}>\n {/* Draggable strip under the overlay title bar, so the cleared\n space still moves the window instead of being a dead band.\n Zero-height in a browser. */}\n <div className={styles.headDragStrip} aria-hidden=\"true\" />\n <label className={styles.search} htmlFor={searchId}>\n <span className={styles.searchIcon} aria-hidden=\"true\"><SearchIcon /></span>\n <span className=\"visually-hidden\">Search chats</span>\n <input id={searchId} type=\"search\" value={query} placeholder=\"Search chats\" autoComplete=\"off\"\n onChange={(event) => onQuery(event.target.value)} />\n </label>\n {/* Icon-only, so each keeps its own aria-label: the tooltip is the\n DESCRIPTION, never the accessible name. */}\n <Tooltip label=\"New chat\" shortcut=\"⌘N\" placement=\"bottom\">\n <button type=\"button\" className={styles.iconButton} onClick={onNew} aria-label=\"New chat\">\n <PlusIcon />\n </button>\n </Tooltip>\n <Tooltip label=\"Hide chat list\" placement=\"bottom\">\n <button type=\"button\" className={styles.iconButton} onClick={onCollapse} aria-label=\"Hide chat list\">\n <SidebarIcon />\n </button>\n </Tooltip>\n {sessionsStatus === 'refreshing' ? <RefreshIndicator label=\"Refreshing chats\" /> : null}\n </div>\n\n <div className={styles.scroll}>\n {/* Saved projects, above the chats. A chat list groups only the\n folders something has ALREADY been started on; this is the list of\n folders the operator asked to keep, which is the one that answers\n \"open the thing I was working on yesterday\". It reads and writes\n the workspace registry itself — see workspaces/SavedProjects.tsx. */}\n <SavedProjects />\n {loading ? (\n <div className={styles.skeleton} aria-busy=\"true\">\n <SkeletonLine width=\"48%\" /><SkeletonLine width=\"86%\" /><SkeletonLine width=\"74%\" />\n <SkeletonLine width=\"40%\" /><SkeletonLine width=\"80%\" />\n </div>\n ) : sessionsStatus === 'error' && sessions.length === 0 ? (\n <div role=\"alert\" className={styles.error}>\n <p>{sessionsError ?? 'Could not load chats.'}</p>\n <button type=\"button\" onClick={onRetry}>Retry</button>\n </div>\n ) : groups.length === 0 ? (\n <div className={styles.empty}>\n {query ? (\n <>\n <p className={styles.emptyTitle}>No chats match “{query}”</p>\n <p>Search covers chat titles and the project each one is on.</p>\n {/* A dead end needs a way out. Without this the only exit is\n to find the field again and clear it by hand. */}\n <button type=\"button\" className={styles.emptyAction} onClick={() => onQuery('')}>\n Clear search\n </button>\n </>\n ) : (\n <>\n <p className={styles.emptyTitle}>No chats yet</p>\n <p>Start one on any project with any seat.</p>\n {/* Deliberately NOT named \"New chat\": the header already has a\n control by that name, and two buttons sharing one\n accessible name is a coin toss for anyone navigating by\n name rather than by sight. */}\n <button type=\"button\" className={styles.emptyAction} onClick={onNew}>\n Start your first chat <kbd className={styles.emptyKey}>⌘N</kbd>\n </button>\n </>\n )}\n </div>\n ) : groups.map((group) => (\n <section key={group.projectPath} className={styles.group} aria-label={group.name}>\n {/* The path stays a native `title`: this heading is not focusable,\n so a tooltip would reach mice only, and what it discloses is\n the text the ellipsis clipped rather than a description. */}\n <h2 className={styles.groupTitle} title={group.projectPath}>\n <span className={styles.groupName}>{group.name}</span>\n {group.enrolled ? <span className={styles.enrolled}>enrolled</span> : null}\n <span className={styles.groupCount} aria-hidden=\"true\">{group.sessions.length}</span>\n </h2>\n <ul className={styles.list}>\n {group.sessions.map((session) => {\n const seat = seatById(seats, session.seatId);\n const capacity = seat === undefined ? null : seatSubscription(seat);\n // Quiet by default: the marker appears only where it changes\n // what the operator would do — a turn in flight on a seat\n // whose binding window is spent.\n const spentWhileRunning = session.status === 'running' && capacity?.cls === 'blocked';\n const title = capacity === null || capacity.cls === 'ready' || capacity.cls === 'unread'\n ? `${session.title} · ${seatPillLabel(seats, session)}`\n : `${session.title} · ${seatPillLabel(seats, session)} · ${capacity.summary}`;\n return (\n <li key={session.id}>\n {/* The row is where the list stops being scannable: the\n title is clipped at one line and the seat is not drawn\n at all. A native `title` disclosed both to mice only —\n this one opens on keyboard focus too, and cannot be\n clipped by the sidebar's own overflow. */}\n <Tooltip label={title} placement=\"right\">\n <button type=\"button\" className={`${styles.session} ${styles[`engine-${session.engine}`] ?? ''}`}\n aria-current={session.id === selectedId ? 'true' : undefined}\n data-focus-key={`verse-session:${session.id}`} data-engine={session.engine}\n onClick={() => onSelect(session.id)}>\n <span className={styles.marker} aria-hidden=\"true\" />\n <span className={styles.sessionText}>{session.title || 'Untitled chat'}</span>\n {spentWhileRunning && capacity !== null ? (\n <span className={styles.seatSpent} role=\"img\"\n aria-label={`Seat limit reached: ${capacity.summary}`}>▮</span>\n ) : null}\n {session.status === 'running' ? (\n <span className={styles.running} role=\"img\" aria-label=\"Running\" />\n ) : session.status === 'error' ? (\n <span className={styles.errored} role=\"img\" aria-label=\"Last turn failed\">!</span>\n ) : null}\n <time className={styles.time} dateTime={session.updatedAt}>{formatRelative(session.updatedAt)}</time>\n </button>\n </Tooltip>\n </li>\n );\n })}\n </ul>\n </section>\n ))}\n </div>\n\n <footer className={styles.footer}>\n <button type=\"button\" onClick={onDisconnect} className={styles.footerButton}>Disconnect</button>\n </footer>\n </nav>\n );\n}\n","/**\n * routes/verse/verse-events.ts — the two live channels the Verse console\n * owns, since scoped consoles never join data/sse.ts's global feed:\n *\n * 1. One EventSource per OPEN session against\n * GET /api/verse/sessions/:id/events. Event name = VerseEvent.type,\n * id = seq (so the browser's own Last-Event-ID reconnect resumes where\n * it left off); each frame is applied to verse-store, which drops\n * anything already seen by seq — a fresh connection replays from the\n * start, exactly like src/core/web/run-stream.ts.\n * 2. One EventSource against /api/events for the `verse-sessions` list\n * digest, which just invalidates the sidebar's cache keys.\n *\n * Both carry the per-tab client proof as `?client=` — the same construction\n * data/client.ts's eventsUrl() uses, because EventSource cannot send the\n * proof as a header (see server.ts readSessionClientProof).\n */\nimport type { VerseEvent, VerseEventType } from '../../data/api-types.js';\nimport { getAuthSnapshot, getReadClientProof } from '../../data/auth-store.js';\nimport { eventsUrl } from '../../data/client.js';\nimport { applyVerseEvent, setVerseStreamState } from './verse-store.js';\nimport { invalidateVerseLists, verseSessionPath } from './verse-queries.js';\n\nexport const VERSE_EVENT_TYPES: readonly VerseEventType[] = [\n 'user-message',\n 'turn-started',\n 'text-delta',\n 'assistant-message',\n 'thinking',\n 'tool-use',\n 'tool-result',\n 'usage',\n 'turn-done',\n 'error',\n 'cancelled',\n];\n\n/** Per-session stream URL, carrying the client proof the way eventsUrl() does. */\nexport function verseSessionEventsUrl(sessionId: string): string {\n return `${verseSessionPath(sessionId, '/events')}?client=${encodeURIComponent(getReadClientProof())}`;\n}\n\nfunction backoffMs(attempt: number): number {\n return Math.min(1000 * 2 ** attempt, 15_000);\n}\n\nfunction parseEvent(raw: string): VerseEvent | null {\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== 'object') return null;\n const candidate = parsed as Partial<VerseEvent>;\n if (typeof candidate.seq !== 'number' || typeof candidate.type !== 'string') return null;\n return parsed as VerseEvent;\n } catch {\n return null;\n }\n}\n\n/**\n * Open the live stream for one session. Returns a disposer; reconnects with\n * backoff on error while the session is still open and the read session is\n * still authenticated.\n */\nexport function openVerseSessionStream(sessionId: string): () => void {\n let source: EventSource | null = null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let attempt = 0;\n let disposed = false;\n\n const connect = () => {\n if (disposed || typeof EventSource === 'undefined') return;\n if (getAuthSnapshot().phase !== 'authenticated') return;\n setVerseStreamState(sessionId, attempt === 0 ? 'connecting' : 'reconnecting');\n const es = new EventSource(verseSessionEventsUrl(sessionId), { withCredentials: true });\n source = es;\n es.onopen = () => {\n attempt = 0;\n setVerseStreamState(sessionId, 'open');\n };\n for (const type of VERSE_EVENT_TYPES) {\n es.addEventListener(type, (evt) => {\n const event = parseEvent((evt as MessageEvent<string>).data);\n if (!event) return;\n applyVerseEvent(sessionId, event);\n if (event.type === 'turn-done' || event.type === 'cancelled' || event.type === 'error') invalidateVerseLists();\n });\n }\n es.onerror = (evt) => {\n // A server-sent event NAMED `error` (a VerseEvent.type) also dispatches\n // through onerror because onerror is the handler for event type \"error\".\n // It arrives as a MessageEvent with data; a real transport failure does\n // not. Without this guard every vendor error replayed on reconnect would\n // tear the stream down again, forever.\n if (typeof MessageEvent !== 'undefined' && evt instanceof MessageEvent) return;\n es.close();\n if (source === es) source = null;\n if (disposed) return;\n setVerseStreamState(sessionId, 'reconnecting');\n if (getAuthSnapshot().phase !== 'authenticated') return;\n timer = setTimeout(() => {\n timer = null;\n attempt += 1;\n connect();\n }, backoffMs(attempt));\n };\n };\n\n connect();\n\n return () => {\n disposed = true;\n if (timer) clearTimeout(timer);\n timer = null;\n source?.close();\n source = null;\n setVerseStreamState(sessionId, 'closed');\n };\n}\n\n/**\n * Sidebar digest channel: listens only for `verse-sessions` on /api/events\n * and refreshes the session list + bootstrap when it fires.\n */\nexport function openVerseListChannel(): () => void {\n let source: EventSource | null = null;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let attempt = 0;\n let disposed = false;\n\n const connect = () => {\n if (disposed || typeof EventSource === 'undefined') return;\n if (getAuthSnapshot().phase !== 'authenticated') return;\n const es = new EventSource(eventsUrl(), { withCredentials: true });\n source = es;\n es.onopen = () => {\n attempt = 0;\n };\n es.addEventListener('verse-sessions', () => invalidateVerseLists());\n es.onerror = () => {\n es.close();\n if (source === es) source = null;\n if (disposed || getAuthSnapshot().phase !== 'authenticated') return;\n timer = setTimeout(() => {\n timer = null;\n attempt += 1;\n connect();\n }, backoffMs(attempt));\n };\n };\n\n connect();\n\n return () => {\n disposed = true;\n if (timer) clearTimeout(timer);\n timer = null;\n source?.close();\n source = null;\n };\n}\n","/**\n * routes/verse/useVerseSession.ts — the only React glue over verse-store /\n * verse-events (same split as data/hooks.ts over cache.ts + sse.ts).\n *\n * Selecting a session: fetch its detail (session record + full event log),\n * seed the store, then hold a live EventSource open until the selection\n * changes or the component unmounts. The store keeps the events after the\n * stream closes, so switching back is instant while the refetch + reconnect\n * catch up in the background.\n */\nimport { useEffect, useMemo, useSyncExternalStore } from 'react';\nimport { openVerseSessionStream } from './verse-events.js';\nimport { fetchVerseSessionDetail } from './verse-queries.js';\nimport {\n buildTranscript,\n getVerseSessionState,\n seedVerseSession,\n setVerseLoadError,\n subscribeVerseStore,\n type Transcript,\n type VerseSessionState,\n} from './verse-store.js';\n\nexport interface VerseSessionView extends VerseSessionState {\n transcript: Transcript;\n}\n\n/**\n * @param reload bump to re-fetch the detail + reconnect for the same id\n * (the transcript's Retry button).\n */\nexport function useVerseSession(sessionId: string | null, reload = 0): VerseSessionView {\n const state = useSyncExternalStore(\n subscribeVerseStore,\n () => getVerseSessionState(sessionId),\n () => getVerseSessionState(sessionId),\n );\n\n useEffect(() => {\n if (!sessionId) return;\n const controller = new AbortController();\n void fetchVerseSessionDetail(sessionId, controller.signal)\n .then((detail) => {\n if (!controller.signal.aborted) seedVerseSession(sessionId, detail.session, detail.events);\n })\n .catch((err: unknown) => {\n if (controller.signal.aborted) return;\n setVerseLoadError(sessionId, err instanceof Error ? err.message : 'Could not load this chat.');\n });\n const close = openVerseSessionStream(sessionId);\n return () => {\n controller.abort();\n close();\n };\n }, [sessionId, reload]);\n\n const transcript = useMemo(() => buildTranscript(state.events), [state.events]);\n return useMemo(() => ({ ...state, transcript }), [state, transcript]);\n}\n","/**\n * routes/verse/chat-panel-sizing.ts — how wide the two side panels of the\n * Chat section are, and what the viewport will actually let them be.\n *\n * WHY THIS IS NOT `ashlr.verse.ui.v2`. That key's shape is the shell contract\n * (docs/VERSE-CONTRACT-V2.md) and verse-ui-store.test pins it field for\n * field; the same precedent that put `resources-collapse.ts` under its own\n * key applies here. This module also needs something the shell store cannot\n * express: a width is not a single number but a PAIR — what the operator\n * asked for, and what the window is currently wide enough to give them.\n *\n * DESIRED vs EFFECTIVE. A sidebar dragged to 420px on a 1900px display must\n * not strand the transcript when the same window is later 1100px wide. So the\n * operator's choice (`desired`) is what persists, and `effective` is that\n * choice re-fitted to the container on every layout change. Shrinking the\n * window narrows the panel; widening it gives the width back, because the\n * transient value was never written down.\n *\n * Pure aside from the two localStorage functions, and framework-free — the\n * React glue lives in ChatResizer.tsx, the same split as\n * verse-ui-store.ts / useVerseUi.ts.\n */\n\nexport type ChatPanelSide = 'sidebar' | 'resources';\n\nexport interface ChatPanelRange {\n readonly min: number;\n readonly max: number;\n readonly def: number;\n}\n\n/**\n * Minimum and maximum are both load-bearing. The minimum is the width below\n * which the panel stops being a panel and becomes a sliver of truncated\n * text; the maximum keeps a wide display from turning the transcript into a\n * column. Defaults match what the shell has always opened at, so nothing\n * moves for an operator who never drags anything.\n */\nexport const CHAT_PANEL_RANGES: Readonly<Record<ChatPanelSide, ChatPanelRange>> = {\n sidebar: { min: 220, max: 420, def: 264 },\n resources: { min: 240, max: 520, def: 320 },\n};\n\n/**\n * The transcript's floor. Below `--measure-read` (720px) reading is already\n * compromised; 480px is where the composer's own controls start wrapping, and\n * it is the point past which a side panel must give width back instead of\n * taking more. The narrow-width media queries in ChatSection.module.css take\n * over below that — this number only decides who yields first.\n */\nexport const MIN_TRANSCRIPT_WIDTH = 480;\n\n/** The 1px hairline track each visible resizer occupies. */\nconst HAIRLINE = 1;\n\n/** Arrow-key step, and the coarse step Shift asks for. */\nexport const CHAT_PANEL_STEP = 16;\nexport const CHAT_PANEL_STEP_COARSE = 64;\n\nexport const CHAT_PANEL_SIZING_KEY = 'ashlr.verse.panels.v1';\n\n/**\n * Read-only migration source. Panel widths lived in the shell store before\n * they were draggable; seeding from it once means an upgrade does not reset\n * a width the operator had already chosen. Never written to from here.\n */\nconst LEGACY_SHELL_KEY = 'ashlr.verse.ui.v2';\n\nexport interface ChatPanelWidths {\n readonly sidebar: number;\n readonly resources: number;\n}\n\n/** What the chat grid can currently afford. */\nexport interface ChatPanelFit {\n /**\n * Width in px of the chat grid itself (NOT the window): rail excluded,\n * because the rail is not the section's to spend. Zero or unknown — jsdom,\n * a hidden section, the first paint — disables viewport fitting entirely\n * rather than guessing, so a width is never clamped against a measurement\n * that does not exist.\n */\n readonly containerWidth: number;\n readonly sidebarVisible: boolean;\n readonly resourcesVisible: boolean;\n}\n\nexport const UNKNOWN_FIT: ChatPanelFit = {\n containerWidth: 0,\n sidebarVisible: true,\n resourcesVisible: true,\n};\n\nexport interface ChatPanelSizing {\n /** The operator's choice. This is what persists. */\n readonly desired: ChatPanelWidths;\n /** That choice, re-fitted to the current container. This is what renders. */\n readonly effective: ChatPanelWidths;\n}\n\n/**\n * Clamp one width into its own range. Nonsense — NaN, a string, a negative\n * number out of a hand-edited localStorage entry — resolves to the default\n * rather than to the minimum, so a corrupt value reads as \"never chosen\".\n */\nexport function clampPanelWidth(side: ChatPanelSide, value: unknown): number {\n const range = CHAT_PANEL_RANGES[side];\n const n = Number(value);\n if (!Number.isFinite(n) || n <= 0) return range.def;\n return Math.max(range.min, Math.min(range.max, Math.round(n)));\n}\n\n/**\n * Re-fit a chosen pair of widths to the container.\n *\n * The resources panel yields first: it is the optional one (it has a toggle,\n * the sidebar's collapse is an overlay at phone width), so on a narrowing\n * window the operator loses reference material before they lose navigation.\n * Neither panel is ever pushed below its own minimum — past that point the\n * media queries hide a panel outright, which is a better answer than a 40px\n * stub of clipped text.\n */\nexport function fitChatPanels(widths: ChatPanelWidths, fit: ChatPanelFit): ChatPanelWidths {\n let sidebar = clampPanelWidth('sidebar', widths.sidebar);\n let resources = clampPanelWidth('resources', widths.resources);\n if (!Number.isFinite(fit.containerWidth) || fit.containerWidth <= 0) return { sidebar, resources };\n\n const hairlines = (fit.sidebarVisible ? HAIRLINE : 0) + (fit.resourcesVisible ? HAIRLINE : 0);\n const budget = fit.containerWidth - MIN_TRANSCRIPT_WIDTH - hairlines;\n const spent = (fit.sidebarVisible ? sidebar : 0) + (fit.resourcesVisible ? resources : 0);\n let over = spent - budget;\n if (over <= 0) return { sidebar, resources };\n\n if (fit.resourcesVisible) {\n const give = Math.min(over, resources - CHAT_PANEL_RANGES.resources.min);\n resources -= give;\n over -= give;\n }\n if (over > 0 && fit.sidebarVisible) {\n const give = Math.min(over, sidebar - CHAT_PANEL_RANGES.sidebar.min);\n sidebar -= give;\n }\n return { sidebar, resources };\n}\n\n// ---------------------------------------------------------------------------\n// Persistence\n// ---------------------------------------------------------------------------\n\nexport function defaultChatPanelWidths(): ChatPanelWidths {\n return { sidebar: CHAT_PANEL_RANGES.sidebar.def, resources: CHAT_PANEL_RANGES.resources.def };\n}\n\n/** Parse either this module's payload or the legacy shell payload. */\nexport function parseChatPanelWidths(raw: string | null): ChatPanelWidths | null {\n if (raw === null || raw === '') return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;\n const record = parsed as Record<string, unknown>;\n // `sidebarWidth`/`resourcesWidth` is the legacy shell spelling.\n const sidebar = record.sidebar ?? record.sidebarWidth;\n const resources = record.resources ?? record.resourcesWidth;\n if (sidebar === undefined && resources === undefined) return null;\n return {\n sidebar: clampPanelWidth('sidebar', sidebar),\n resources: clampPanelWidth('resources', resources),\n };\n}\n\nexport function readChatPanelWidths(): ChatPanelWidths {\n try {\n const own = parseChatPanelWidths(localStorage.getItem(CHAT_PANEL_SIZING_KEY));\n if (own) return own;\n // First run after the upgrade: inherit whatever the shell store had.\n return parseChatPanelWidths(localStorage.getItem(LEGACY_SHELL_KEY)) ?? defaultChatPanelWidths();\n } catch {\n return defaultChatPanelWidths();\n }\n}\n\nexport function writeChatPanelWidths(widths: ChatPanelWidths): void {\n try {\n localStorage.setItem(CHAT_PANEL_SIZING_KEY, JSON.stringify({\n sidebar: widths.sidebar,\n resources: widths.resources,\n }));\n } catch {\n /* a private window without storage still runs the app */\n }\n}\n\n// ---------------------------------------------------------------------------\n// Store\n// ---------------------------------------------------------------------------\n\nlet desired: ChatPanelWidths = readChatPanelWidths();\nlet fit: ChatPanelFit = UNKNOWN_FIT;\nlet snapshot: ChatPanelSizing = { desired, effective: fitChatPanels(desired, fit) };\nconst listeners = new Set<() => void>();\n\nfunction sameWidths(a: ChatPanelWidths, b: ChatPanelWidths): boolean {\n return a.sidebar === b.sidebar && a.resources === b.resources;\n}\n\n/** Snapshot identity changes only when a number actually changed. */\nfunction publish(): void {\n const effective = fitChatPanels(desired, fit);\n if (sameWidths(snapshot.desired, desired) && sameWidths(snapshot.effective, effective)) return;\n snapshot = { desired, effective };\n for (const listener of listeners) listener();\n}\n\nexport function subscribeChatPanels(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function getChatPanelSizing(): ChatPanelSizing {\n return snapshot;\n}\n\n/**\n * Publish what the layout can afford. Called on mount, on window resize and\n * whenever a panel is shown or hidden. Deliberately does NOT persist: a\n * narrow window borrows width, it does not take it.\n */\nexport function setChatPanelFit(next: ChatPanelFit): void {\n if (\n fit.containerWidth === next.containerWidth\n && fit.sidebarVisible === next.sidebarVisible\n && fit.resourcesVisible === next.resourcesVisible\n ) return;\n fit = next;\n publish();\n}\n\nfunction commit(next: ChatPanelWidths): void {\n if (sameWidths(desired, next)) return;\n desired = next;\n writeChatPanelWidths(desired);\n publish();\n}\n\n/** A drag or a direct set. Range-clamped; the fit is applied on read. */\nexport function setChatPanelWidth(side: ChatPanelSide, value: number): void {\n commit({ ...desired, [side]: clampPanelWidth(side, value) });\n}\n\n/**\n * An arrow key. Steps from the EFFECTIVE width, so a keypress moves the\n * handle the operator can see rather than an off-screen remembered one.\n */\nexport function nudgeChatPanelWidth(side: ChatPanelSide, delta: number): void {\n setChatPanelWidth(side, snapshot.effective[side] + delta);\n}\n\n/** Double-click, and the Home/End extremes. */\nexport function resetChatPanelWidth(side: ChatPanelSide): void {\n setChatPanelWidth(side, CHAT_PANEL_RANGES[side].def);\n}\n\n/** Test hygiene — mirrors resetVerseUi(). */\nexport function resetChatPanelSizing(): void {\n desired = defaultChatPanelWidths();\n fit = UNKNOWN_FIT;\n snapshot = { desired, effective: fitChatPanels(desired, fit) };\n try {\n localStorage.removeItem(CHAT_PANEL_SIZING_KEY);\n } catch {\n /* ignore */\n }\n for (const listener of listeners) listener();\n}\n\n/** Re-read storage into the store (a fresh tab, or a test that seeded a key). */\nexport function reloadChatPanelSizing(): void {\n desired = readChatPanelWidths();\n snapshot = { desired, effective: fitChatPanels(desired, fit) };\n for (const listener of listeners) listener();\n}\n","/**\n * routes/verse/ChatResizer.tsx — the drag handle between the chat\n * transcript and a side panel.\n *\n * A 1px hairline that behaves like a 9px target: the hairline is the design\n * (DESIGN-V2 has no chrome), the grab area is the ergonomics. Three things\n * about it are not obvious and are all deliberate:\n *\n * 1. IT IS A CONTROL, NOT A DECORATION. `role=\"separator\"` with a tabindex is\n * the ARIA window-splitter pattern: arrow keys move it, Home/End take it\n * to its limits, and a double-click restores the default. A pointer-only\n * resizer simply does not exist for a keyboard operator.\n *\n * 2. IT MUST NOT EAT THE macOS DRAG STRIP. The grab area overhangs ±4px into\n * the panels either side, and the top 48px of those panels is the window's\n * own drag region (Sidebar `.headDragStrip`, Workspace `.header`\n * data-app-region=\"drag\"). It is painted after them, so without the\n * `--app-titlebar-height` inset in the stylesheet it would steal 4px of\n * the strip AND turn the macOS double-click-to-zoom into a width reset.\n * See desktop/README.md \"Desktop shell contract\".\n *\n * 3. THE DRAG IS RELEASED FROM `window`, NOT FROM THE ELEMENT. Pointer\n * capture is requested, but it is not relied on: a capture that fails, a\n * pointer that leaves the window, a button released over another app and\n * a mid-drag unmount all have to end the drag, because a stuck drag state\n * (everything selects, the cursor sticks) is the most visible bug this\n * control can have.\n */\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore, type KeyboardEvent, type PointerEvent } from 'react';\nimport {\n CHAT_PANEL_RANGES,\n CHAT_PANEL_STEP,\n CHAT_PANEL_STEP_COARSE,\n getChatPanelSizing,\n nudgeChatPanelWidth,\n resetChatPanelWidth,\n setChatPanelWidth,\n subscribeChatPanels,\n type ChatPanelSide,\n type ChatPanelSizing,\n} from './chat-panel-sizing.js';\n\n/** The React glue over chat-panel-sizing.ts (same split as useVerseUi.ts). */\nexport function useChatPanelSizing(): ChatPanelSizing {\n return useSyncExternalStore(subscribeChatPanels, getChatPanelSizing, getChatPanelSizing);\n}\n\n/**\n * Marks the body for the duration of a drag so the stylesheet can suppress\n * selection app-wide. An attribute rather than an inline style: it survives\n * React re-renders, it is one line of CSS, and a test can see it.\n */\nconst BODY_FLAG = 'verseResizing';\n\nfunction markBody(on: boolean): void {\n try {\n if (on) document.body.dataset[BODY_FLAG] = 'true';\n else delete document.body.dataset[BODY_FLAG];\n } catch {\n /* a detached document in a test teardown is not worth throwing over */\n }\n}\n\nexport interface ChatResizerProps {\n side: ChatPanelSide;\n /** The control's accessible name — what it resizes, in the operator's words. */\n label: string;\n className?: string;\n}\n\ninterface DragState {\n pointerId: number;\n originX: number;\n startWidth: number;\n}\n\nexport function ChatResizer({ side, label, className }: ChatResizerProps) {\n const sizing = useChatPanelSizing();\n const range = CHAT_PANEL_RANGES[side];\n const width = sizing.effective[side];\n const drag = useRef<DragState | null>(null);\n const [dragging, setDragging] = useState(false);\n\n /** The one way a drag ends. Idempotent, so every path can call it. */\n const endDrag = useCallback(() => {\n if (!drag.current) return;\n drag.current = null;\n setDragging(false);\n markBody(false);\n }, []);\n\n const onPointerDown = useCallback((event: PointerEvent<HTMLDivElement>) => {\n // Primary button only: a right-click here belongs to the context menu,\n // and a middle-click must not start a drag nobody asked for.\n if (event.button !== 0) return;\n event.preventDefault();\n drag.current = { pointerId: event.pointerId, originX: event.clientX, startWidth: width };\n setDragging(true);\n markBody(true);\n // Best-effort: it keeps the cursor and the events on the handle while the\n // pointer wanders. The window listeners below are the actual contract.\n try {\n event.currentTarget.setPointerCapture?.(event.pointerId);\n } catch {\n /* unsupported, or the pointer is already gone — the window listeners cover it */\n }\n }, [width]);\n\n // Move/end listeners live on the window for the whole drag, so a pointer\n // that leaves the viewport or a button released over another window still\n // lands here. Unmounting mid-drag runs the cleanup and clears the body flag.\n useEffect(() => {\n if (!dragging) return undefined;\n\n const onMove = (event: globalThis.PointerEvent) => {\n const state = drag.current;\n if (!state || event.pointerId !== state.pointerId) return;\n const delta = event.clientX - state.originX;\n // The sidebar grows to the right, the resources panel to the left.\n setChatPanelWidth(side, side === 'sidebar' ? state.startWidth + delta : state.startWidth - delta);\n };\n const onEnd = (event: globalThis.PointerEvent) => {\n const state = drag.current;\n if (state && event.pointerId !== state.pointerId) return;\n endDrag();\n };\n /** Escape puts the width back where the drag started. */\n const onKey = (event: globalThis.KeyboardEvent) => {\n const state = drag.current;\n if (!state || event.key !== 'Escape') return;\n setChatPanelWidth(side, state.startWidth);\n endDrag();\n };\n // The window losing focus (⌘-tab mid-drag, an OS dialog) never delivers a\n // pointerup, so treat it as one rather than staying stuck.\n const onBlur = () => endDrag();\n\n window.addEventListener('pointermove', onMove);\n window.addEventListener('pointerup', onEnd);\n window.addEventListener('pointercancel', onEnd);\n window.addEventListener('keydown', onKey);\n window.addEventListener('blur', onBlur);\n return () => {\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', onEnd);\n window.removeEventListener('pointercancel', onEnd);\n window.removeEventListener('keydown', onKey);\n window.removeEventListener('blur', onBlur);\n markBody(false);\n };\n }, [dragging, side, endDrag]);\n\n const onKeyDown = useCallback((event: KeyboardEvent<HTMLDivElement>) => {\n const step = event.shiftKey ? CHAT_PANEL_STEP_COARSE : CHAT_PANEL_STEP;\n // Left/Right are screen directions, so which one GROWS depends on which\n // edge of the transcript this handle is.\n const toward = side === 'sidebar' ? 1 : -1;\n switch (event.key) {\n case 'ArrowRight':\n nudgeChatPanelWidth(side, step * toward);\n break;\n case 'ArrowLeft':\n nudgeChatPanelWidth(side, -step * toward);\n break;\n case 'Home':\n setChatPanelWidth(side, range.min);\n break;\n case 'End':\n setChatPanelWidth(side, range.max);\n break;\n case 'Enter':\n resetChatPanelWidth(side);\n break;\n default:\n return;\n }\n event.preventDefault();\n }, [side, range.min, range.max]);\n\n return (\n <div\n className={className}\n data-verse-resizer={side}\n data-dragging={dragging ? 'true' : undefined}\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={label}\n aria-valuemin={range.min}\n aria-valuemax={range.max}\n aria-valuenow={width}\n aria-valuetext={`${width} pixels`}\n tabIndex={0}\n onPointerDown={onPointerDown}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onLostPointerCapture={endDrag}\n onKeyDown={onKeyDown}\n // The thing people reach for after over-dragging. In the desktop app a\n // double-click on a DRAG region zooms the window instead — which is why\n // the stylesheet keeps this handle's grab area out of the title bar.\n onDoubleClick={() => resetChatPanelWidth(side)}\n />\n );\n}\n",".workspace {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n min-width: 0;\n background: var(--bg-surface);\n}\n\n/* ---- header strip: 48px, hairline, ghost controls only ------------------ */\n/*\n * Three flex clusters, in reading order: the identity lockup (the only one\n * that shrinks), the seat pill, then the action cluster pinned right by\n * .headerSpacer. Wrapping is never allowed — the strip is exactly one\n * --strip-height row, which is the height the desktop shell's title-bar\n * maths is written against.\n */\n.header {\n position: relative; /* containing block for the 2px context line */\n flex-shrink: 0;\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: var(--space-3);\n /* DESIGN-V2 §4: header strips are --strip-height, and the token is what the\n desktop shell's inset maths is written against. */\n height: var(--strip-height);\n padding: 0 var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n}\n.headerSpacer { flex: 1 1 var(--space-4); min-width: var(--space-2); }\n\n/* ---- identity lockup: project over chat title --------------------------- */\n/*\n * Two lines inside 48px: 11px/1.2 (~13px) over 15px/1.2 (~18px) plus a 1px\n * gap is ~32px, which centres in the strip with room to spare. This is what\n * makes the band a header rather than a rule with an icon on it — and it is\n * the ONLY shrinkable item, so a 200-character title or a deep project path\n * ellipsises here instead of displacing the actions.\n */\n.identity {\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 1px;\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n}\n.eyebrow {\n max-width: 100%;\n color: var(--text-tertiary);\n font-size: var(--text-2xs-size, 11px);\n line-height: 1.2;\n font-weight: var(--font-weight-medium);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.eyebrowSkeleton {\n height: calc(var(--text-2xs-size, 11px) * 1.2);\n width: 9ch;\n border-radius: var(--radius-xs);\n}\n\n/* Both title variants share the type; only the inset BUTTON gets the\n pull-back below. Grouping them keeps the two lines on one scale. */\n.title,\n.titleStatic {\n min-width: 0;\n max-width: 100%;\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n line-height: 1.2;\n font-weight: var(--font-weight-medium);\n letter-spacing: var(--tracking-display, -0.02em);\n}\n/* The static variant is plain text — the skeleton bar and the no-chat state.\n It sits flush at the header's padding edge with no pull-back to undo. */\n.titleStatic {\n color: var(--text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n/* Nothing is selected: the line is a STATE, not a name, so it is quieter than\n a real title while still being the thing the eye lands on. */\n.titleStatic[data-state='empty'] { color: var(--text-secondary); }\n\n.title {\n /* The hover/press target is inset by --space-2 so the chip reads as a target,\n but the TEXT must still line up with the header's padding edge (and with\n the eyebrow directly above it). The pull-back lives here, on the flex item,\n rather than on .titleButton: a negative margin on the button shrinks the\n h1's max-content (the h1 sizes to its child's OUTER width), and\n `.titleButton { max-width: 100% }` then re-clamps the button to that\n reduced box — so the title lost exactly --space-2 of text to the ellipsis at\n every width, even with 350px of empty header beside it (\"New chat\" → \"New c…\").\n On the h1 the margin only shifts the item and its free-space contribution; the\n button keeps its full content width. Optical alignment is identical. */\n margin-left: calc(-1 * var(--space-2));\n}\n.titleButton {\n display: block;\n max-width: 100%;\n padding: 2px var(--space-2);\n border-radius: var(--radius-xs);\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n text-align: left;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.titleButton:hover:not(:disabled) { background: var(--bg-hover); }\n.titleButton:active:not(:disabled) { background: var(--bg-active); }\n.titleButton:disabled { cursor: default; }\n.titleInput {\n /* Same pull-back as .title, for the same reason — the text must not jump\n --space-2 to the right the moment you click Rename. The extra width pays\n for the margin, so the box still ends at the lockup's right edge instead\n of being clipped by its overflow. */\n width: calc(100% + var(--space-2));\n max-width: 48ch;\n padding: 2px var(--space-2);\n margin-left: calc(-1 * var(--space-2));\n border: 1px solid var(--accent-500);\n border-radius: var(--radius-xs);\n background: var(--bg-input);\n color: var(--text-primary);\n font-family: var(--font-display);\n font-size: var(--text-md-size);\n font-weight: var(--font-weight-medium);\n letter-spacing: var(--tracking-display, -0.02em);\n}\n.titleSkeleton {\n height: calc(var(--text-md-size) * 1.2);\n width: 22ch;\n max-width: 40%;\n border-radius: var(--radius-xs);\n}\n\n/* Seat pill: an engine-tinted dot and the seat name. The tint is identity,\n never status — status is text or a glyph everywhere in this app.\n The PROJECT is no longer repeated here; it is the lockup's eyebrow. */\n.seatPill {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n /* Shrinkable, but only after the lockup has given up what it can: .seatText\n has its own ellipsis, so this degrades rather than overflowing. */\n flex: 0 1 auto;\n max-width: 28ch;\n min-width: 0;\n padding: 0 var(--space-2);\n height: var(--control-h-xs);\n border-radius: var(--radius-xs);\n background: color-mix(in srgb, var(--verse-engine, var(--text-tertiary)) 10%, transparent);\n color: var(--text-secondary);\n font-size: var(--text-2xs-size, 11px);\n}\n/* A capacity chip only appears when the seat is tight or spent, so the pill\n is allowed a few more characters exactly then — rather than reserving room\n on every chat for a word that is usually absent. The seat name still\n ellipsises first; the chip is the part worth keeping. */\n.seatPill[data-seat-capacity] { max-width: 40ch; }\n.engineDot {\n flex-shrink: 0;\n width: 5px;\n height: 5px;\n border-radius: var(--radius-full);\n background: var(--verse-engine, var(--text-tertiary));\n}\n.seatText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--text-primary);\n font-weight: var(--font-weight-medium);\n}\n.engine-claude { --verse-engine: var(--engine-claude, #c96442); }\n.engine-codex { --verse-engine: var(--engine-codex, #10a37f); }\n.engine-grok { --verse-engine: var(--engine-grok, #6b7280); }\n.engine-local { --verse-engine: var(--engine-local, #7c5cff); }\n\n.streamState { flex-shrink: 0; font-size: var(--text-2xs-size, 11px); color: var(--text-tertiary); }\n\n/* ---- action cluster ----------------------------------------------------- */\n/*\n * flex-shrink: 0 is the whole contract of this strip's truncation behaviour:\n * whatever the title is, the controls keep their width and the lockup gives\n * up its own instead.\n */\n.actions {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: var(--space-1);\n}\n/* Hairline, not a gap: it separates \"things that act on this chat\" from\n \"things that move the panes\", which is why the two toggles beside it read\n as one control rather than as a stray icon. */\n.actionDivider {\n flex-shrink: 0;\n width: 1px;\n height: var(--space-4);\n margin: 0 var(--space-1);\n background: var(--border-default);\n}\n/* Tighter than the cluster gap on purpose — proximity is what makes the two\n toggles a pair. */\n.toggles {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.ghost,\n.ghostIcon,\n.danger {\n flex-shrink: 0;\n border-radius: var(--radius-xs);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.ghostIcon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--control-h-sm);\n height: var(--control-h-sm);\n}\n.ghost { min-height: var(--control-h-xs); padding: 0 var(--space-2); }\n.ghostIcon:hover:not(:disabled),\n.ghost:hover:not(:disabled) { color: var(--text-primary); background: var(--bg-hover); }\n.ghostIcon:active:not(:disabled),\n.ghost:active:not(:disabled) { background: var(--bg-active); }\n.ghostIcon:disabled,\n.ghost:disabled { opacity: 0.4; cursor: not-allowed; }\n/* A pressed toggle is the OPEN pane. Tinted background as well as colour, so\n the pair reads as a two-state segmented control rather than two icons that\n happen to sit together (§6: never state by colour alone — the state is also\n in aria-pressed and in the tooltip). */\n.ghostIcon[aria-pressed='true'] { color: var(--text-primary); background: var(--bg-hover); }\n.ghostIcon[aria-pressed='true']:hover:not(:disabled) { background: var(--bg-active); }\n\n.danger { min-height: var(--control-h-xs); padding: 0 var(--space-2); color: var(--status-danger-fg); }\n.danger:hover:not(:disabled) { background: var(--status-danger-bg); }\n.danger:active:not(:disabled) { background: var(--status-danger-bg); border-color: var(--status-danger-solid); }\n.confirm { display: inline-flex; align-items: center; gap: var(--space-1); }\n.confirmText { flex-shrink: 0; font-size: var(--text-xs-size); color: var(--text-secondary); white-space: nowrap; }\n\n/* ---- context meter: a 2px line under the header, numbers alongside ------ */\n/* Two channels on purpose. --meter-color paints the 2px FILL, where a status\n solid is exactly right; --meter-text paints the percentage, where a status\n solid is text at 2.52:1 (warning, light) and 3.97:1 (danger, light), and\n where even the DEFAULT accent measures 3.99:1 on dark --bg-surface. The\n -fg tokens are the readable pair for the same states: 7.21 / 7.50 light and\n 9.08 / 8.35 dark. See design/tokens-contrast.test.ts, where the solids are\n given only a 1.8:1 \"visible marker\" floor precisely because they are dots\n and 2px rules, never type. */\n.meter {\n --meter-color: var(--accent-500);\n --meter-text: var(--text-secondary);\n flex-shrink: 0;\n display: inline-flex;\n align-items: baseline;\n gap: var(--space-2);\n}\n.meter-warn { --meter-color: var(--status-warning-solid); --meter-text: var(--status-warning-fg); }\n.meter-danger { --meter-color: var(--status-danger-solid); --meter-text: var(--status-danger-fg); }\n.meter-unknown { --meter-color: var(--border-strong); --meter-text: var(--text-tertiary); }\n\n/* Pinned to the header's bottom edge: full width, exactly 2px, no label. */\n.meterTrack {\n position: absolute;\n left: 0;\n right: 0;\n bottom: -1px;\n height: 2px;\n background: transparent;\n}\n.meterFill {\n height: 100%;\n background: var(--meter-color);\n transition: width var(--duration-slow) var(--ease-decelerate), background var(--duration-base) var(--ease-standard);\n}\n.meterInline .meterTrack {\n position: static;\n width: 64px;\n background: var(--meter-track);\n border-radius: var(--radius-full);\n overflow: hidden;\n}\n\n.meterText {\n display: inline-flex;\n align-items: baseline;\n gap: var(--space-2);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n}\n.meterTokens { white-space: nowrap; }\n/* Both halves of the pair are tabular (the wrapper sets it) — but the percent\n also needs a reserved width, or the strip's right edge shifts as it crosses\n 9 -> 10 -> 100 while a turn streams. */\n.meterPercent { min-width: 4ch; text-align: right; }\n.meterPercent { color: var(--meter-text); font-weight: var(--font-weight-medium); }\n\n/* ---- empty state ------------------------------------------------------- */\n.emptyState {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n gap: var(--space-3);\n max-width: 52ch;\n margin: 0 auto;\n padding: var(--space-8) var(--space-6);\n}\n.emptyMark { color: var(--accent-500); }\n.emptyTitle {\n font-family: var(--font-display);\n font-size: var(--text-2xl-size);\n line-height: var(--text-2xl-line);\n font-weight: var(--font-weight-medium);\n letter-spacing: var(--tracking-display, -0.02em);\n}\n.emptyBody { color: var(--text-secondary); font-size: var(--text-md-size); line-height: var(--text-md-line); }\n.emptyButton {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--control-h);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n color: var(--text-primary);\n font-size: var(--text-sm-size);\n font-weight: var(--font-weight-medium);\n transition: border-color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.emptyButton:hover { border-color: var(--accent-500); }\n.emptyButton:active { background: var(--bg-active); }\n.emptyButton kbd { font-family: var(--font-mono); font-size: var(--text-2xs-size, 11px); color: var(--text-tertiary); }\n.emptyWarn {\n padding-left: var(--space-3);\n border-left: 2px solid var(--status-warning-solid);\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n}\n.emptyWarn code { font-size: var(--text-xs-size); color: var(--text-primary); }\n\n/* ---- narrow windows ----------------------------------------------------- */\n/* The window is resizable down to a phone-ish width, and the strip degrades\n from the right-hand end inwards: the lockup and the pane toggles are the\n last things standing, because they are \"where am I\" and \"give me my space\n back\". */\n@media (max-width: 900px) {\n .seatPill { max-width: 20ch; }\n .seatPill[data-seat-capacity] { max-width: 28ch; }\n}\n@media (max-width: 760px) {\n /* Only the token pair goes; the PERCENT stays. Hiding .meterText left the\n 2px line as the sole carrier of ok/warn/danger, i.e. state by colour\n alone (§6) — and 760px is a touch viewport, where the title tooltip that\n covers mouse users never fires. .meterPercent is 11px tabular and costs\n about 4ch, and it is tinted with --meter-text, which pairs the status\n colour with text (§6) AND clears the 4.5:1 body-text floor in the same\n section — the status SOLIDS do not, which is why they stay on the fill. */\n .meterTokens { display: none; }\n .seatPill { max-width: 14ch; }\n .seatPill[data-seat-capacity] { max-width: 22ch; }\n}\n@media (max-width: 620px) {\n /* The seat is still one tap away — the composer names it and offers the\n switch — so at phone width the strip keeps the title and the toggles\n rather than three half-truncated things. */\n .seatPill { display: none; }\n .header { gap: var(--space-2); }\n}\n/* Guarded like every other animated surface here (tokens.css, global.css,\n Transcript, Sidebar, Composer, ResourcesPanel): appearance-store.ts writes\n data-motion=\"full\" precisely so an operator can opt out of the OS\n preference, and an unguarded media query ignores that choice. */\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .meterFill { transition: none; }\n}\n\n/* ---- desktop shell (see desktop/README.md \"Desktop shell contract\") -----\n * In the Tauri window the OS title bar overlays the top 48px and the macOS\n * traffic lights float over the top-LEFT 92px of the WINDOW. This strip does\n * not start at the window's left edge — the 56px rail does — so the inset it\n * owes is the overlap, never the full 92px.\n *\n * The `+ var(--space-2)` is the lockup's optical pull-back paid back: .title\n * and .titleInput sit --space-2 left of the padding edge so their TEXT lines\n * up with the eyebrow, which would otherwise put the rename button's hit area\n * (and the traffic lights) in the same 8px. Adding it here keeps every\n * interactive thing clear of the lights instead of removing the alignment.\n *\n * Both vars are absent in a browser, where the whole calc floors to a negative\n * number (0 - 56 + 8 = -48px), max() picks --space-3, and the layout is\n * byte-for-byte what it was. */\n.header {\n padding-left: max(\n var(--space-3),\n calc(var(--app-traffic-light-inset, 0px) - var(--rail-width, 56px) + var(--space-2))\n );\n}\n","/**\n * routes/verse/ContextMeter.tsx — live context-window occupancy.\n *\n * DESIGN §4: not a labelled progress bar. The bar is a 2px full-width line\n * pinned to the bottom edge of the header strip (the component's own root\n * stays unpositioned so the header is its containing block); the numbers\n * ride alongside in the display font as `18k / 66k`, with the tooltip and\n * `aria-valuetext` carrying the long form.\n *\n * Amber from 70%, red from 90% (the V1 contract's thresholds); an unknown\n * window renders \"n/a\" rather than a guess.\n */\nimport { formatTokens } from './verse-store.js';\nimport styles from './Workspace.module.css';\n\nexport const CONTEXT_WARN_PERCENT = 70;\nexport const CONTEXT_DANGER_PERCENT = 90;\n\nexport interface ContextMeterProps {\n contextTokens: number | null | undefined;\n contextWindow: number | null | undefined;\n /** `inline` draws the track in flow (resources panel) instead of pinned. */\n variant?: 'header' | 'inline';\n}\n\nexport function contextTone(percent: number | null): 'ok' | 'warn' | 'danger' | 'unknown' {\n if (percent === null) return 'unknown';\n if (percent >= CONTEXT_DANGER_PERCENT) return 'danger';\n if (percent >= CONTEXT_WARN_PERCENT) return 'warn';\n return 'ok';\n}\n\nexport function ContextMeter({ contextTokens, contextWindow, variant = 'header' }: ContextMeterProps) {\n const tokens = typeof contextTokens === 'number' && Number.isFinite(contextTokens) ? Math.max(0, contextTokens) : 0;\n const window = typeof contextWindow === 'number' && contextWindow > 0 ? contextWindow : null;\n const percent = window ? Math.min(100, Math.round((tokens / window) * 100)) : null;\n const tone = contextTone(percent);\n const label = window ? `${formatTokens(tokens)} / ${formatTokens(window)}` : `${formatTokens(tokens)} / n/a`;\n const percentLabel = percent === null ? 'n/a' : `${percent}%`;\n return (\n <div\n className={`${styles.meter} ${styles[`meter-${tone}`] ?? ''} ${variant === 'inline' ? styles.meterInline : ''}`}\n role=\"meter\" aria-label=\"Context window\" aria-valuemin={0} aria-valuemax={100}\n aria-valuenow={percent ?? undefined} aria-valuetext={`${label} (${percentLabel})`}\n title={`Context window — ${label} (${percentLabel})`} data-tone={tone}\n >\n <div className={styles.meterTrack} aria-hidden=\"true\">\n <div className={styles.meterFill} style={{ width: `${percent ?? 0}%` }} />\n </div>\n <span className={styles.meterText}>\n <span className={styles.meterTokens}>{label}</span>\n <span className={styles.meterPercent}>{percentLabel}</span>\n </span>\n </div>\n );\n}\n","/**\n * routes/verse/DictationButton.tsx — push-to-talk for the composer via the\n * Web Speech API (`SpeechRecognition` / `webkitSpeechRecognition`). Interim\n * results stream into the textarea through `onInterim`; final segments are\n * committed through `onFinal`. Escape stops listening. When the browser has\n * no recognizer (Firefox, Tauri/WKWebView today) the button is disabled and\n * a tooltip points at Wispr Flow / Superwhisper — system-level dictation\n * types straight into the textarea, so nothing is lost.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { Tooltip } from '../../components/primitives/Tooltip.js';\nimport styles from './Composer.module.css';\n\nexport const DICTATION_FALLBACK_HINT = 'Use Wispr Flow / Superwhisper — system dictation works in this box';\n\ninterface RecognitionResultLike {\n isFinal: boolean;\n 0: { transcript: string };\n length: number;\n}\ninterface RecognitionEventLike {\n resultIndex: number;\n results: ArrayLike<RecognitionResultLike>;\n}\ninterface RecognitionLike {\n lang: string;\n continuous: boolean;\n interimResults: boolean;\n onresult: ((event: RecognitionEventLike) => void) | null;\n onend: (() => void) | null;\n onerror: ((event: { error?: string }) => void) | null;\n start(): void;\n stop(): void;\n abort(): void;\n}\ntype RecognitionCtor = new () => RecognitionLike;\n\n/** Resolve the recognizer constructor, if this runtime ships one. */\nexport function getSpeechRecognition(): RecognitionCtor | null {\n const w = globalThis as unknown as { SpeechRecognition?: RecognitionCtor; webkitSpeechRecognition?: RecognitionCtor };\n return w.SpeechRecognition ?? w.webkitSpeechRecognition ?? null;\n}\n\nexport interface DictationButtonProps {\n disabled?: boolean;\n onInterim: (text: string) => void;\n onFinal: (text: string) => void;\n onListeningChange?: (listening: boolean) => void;\n}\n\nexport function DictationButton({ disabled = false, onInterim, onFinal, onListeningChange }: DictationButtonProps) {\n const Recognizer = getSpeechRecognition();\n const [listening, setListening] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const recognizer = useRef<RecognitionLike | null>(null);\n const callbacks = useRef({ onInterim, onFinal, onListeningChange });\n callbacks.current = { onInterim, onFinal, onListeningChange };\n\n const stop = useCallback(() => {\n const active = recognizer.current;\n recognizer.current = null;\n if (active) {\n active.onresult = null;\n active.onend = null;\n active.onerror = null;\n try {\n active.stop();\n } catch {\n /* already stopped */\n }\n }\n setListening(false);\n callbacks.current.onInterim('');\n callbacks.current.onListeningChange?.(false);\n }, []);\n\n const start = useCallback(() => {\n if (!Recognizer || recognizer.current) return;\n let instance: RecognitionLike;\n try {\n instance = new Recognizer();\n } catch {\n setError('Dictation could not start in this browser.');\n return;\n }\n instance.lang = navigator.language || 'en-US';\n instance.continuous = true;\n instance.interimResults = true;\n instance.onresult = (event) => {\n let interim = '';\n let finalText = '';\n for (let i = event.resultIndex; i < event.results.length; i += 1) {\n const result = event.results[i];\n if (!result) continue;\n const transcript = result[0]?.transcript ?? '';\n if (result.isFinal) finalText += transcript;\n else interim += transcript;\n }\n if (finalText) callbacks.current.onFinal(finalText.trim());\n callbacks.current.onInterim(interim);\n };\n instance.onerror = (event) => {\n const code = event.error ?? 'unknown';\n if (code === 'not-allowed' || code === 'service-not-allowed') setError('Microphone access was denied.');\n else if (code !== 'aborted' && code !== 'no-speech') setError(`Dictation stopped (${code}).`);\n stop();\n };\n instance.onend = () => {\n if (recognizer.current === instance) stop();\n };\n recognizer.current = instance;\n setError(null);\n try {\n instance.start();\n } catch {\n recognizer.current = null;\n setError('Dictation could not start in this browser.');\n return;\n }\n setListening(true);\n callbacks.current.onListeningChange?.(true);\n }, [Recognizer, stop]);\n\n // Escape stops dictation from anywhere on the page; unmount stops it too.\n useEffect(() => {\n if (!listening) return;\n function onKey(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n event.preventDefault();\n stop();\n }\n }\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [listening, stop]);\n useEffect(() => () => {\n const active = recognizer.current;\n recognizer.current = null;\n try {\n active?.abort();\n } catch {\n /* ignore */\n }\n }, []);\n\n if (!Recognizer) {\n return (\n <span className={styles.dictationWrap}>\n {/* This button previously carried the hint THREE times over: a native\n `title`, an aria-describedby, and a hand-rolled `role=\"tooltip\"`\n span that lived in the DOM permanently at opacity 0 and was\n revealed by a :hover rule on the wrapper. That span is the grey\n slab that overhangs the panel beside the composer. One Tooltip\n replaces all three and is mounted only while it is open. */}\n <Tooltip label={DICTATION_FALLBACK_HINT} placement=\"top\">\n <button type=\"button\" className={styles.dictation} disabled aria-disabled=\"true\">\n <MicIcon />\n <span className=\"visually-hidden\">Dictation unavailable</span>\n </button>\n </Tooltip>\n </span>\n );\n }\n\n return (\n <span className={styles.dictationWrap}>\n {/* Icon-only, so the aria-label stays put: the tooltip describes, it\n does not name. */}\n <Tooltip label={listening ? 'Stop dictation' : 'Dictate'} shortcut={listening ? 'Esc' : undefined} placement=\"top\">\n <button type=\"button\" className={`${styles.dictation} ${listening ? styles.dictationLive : ''}`}\n disabled={disabled && !listening} aria-pressed={listening}\n aria-label={listening ? 'Stop dictation (Esc)' : 'Start dictation'}\n onClick={() => (listening ? stop() : start())}>\n <MicIcon />\n {listening ? <span className={styles.dictationPulse} aria-hidden=\"true\" /> : null}\n </button>\n </Tooltip>\n {error ? <span role=\"alert\" className={styles.dictationError}>{error}</span> : null}\n </span>\n );\n}\n\nfunction MicIcon() {\n return (\n <svg viewBox=\"0 0 20 20\" width=\"16\" height=\"16\" aria-hidden=\"true\" focusable=\"false\">\n <rect x=\"7\" y=\"2\" width=\"6\" height=\"10\" rx=\"3\" fill=\"currentColor\" />\n <path d=\"M4.5 9.5a5.5 5.5 0 0 0 11 0M10 15v3M7 18h6\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n","/**\n * routes/verse/Composer.tsx — the message box. Enter sends, Shift+Enter\n * inserts a newline; one control row beneath it carries the seat pill\n * (engine-tinted dot + name), the mic, and send/stop. No inner card: a\n * hairline that takes the accent on focus is the whole chrome (DESIGN §5).\n *\n * While a turn is running the box stays EDITABLE so the next message (typed\n * or dictated) can be drafted during the reply — only Send is withheld and\n * Stop takes its place. This deliberately relaxes the V1 contract line\n * \"Composer disabled while running except stop\": a disabled textarea loses\n * focus on every send and turns the loop (type · Enter · read · type) into a\n * click-into-the-box ritual, and system dictation lands nowhere.\n *\n * Sessions are seat-bound, so the seat pill is read-only: its menu says what\n * this chat runs on and offers \"New chat on …\" per seat, which asks the\n * parent to start a new chat rather than mutating this one.\n */\nimport { useCallback, useEffect, useId, useMemo, useRef, useState, type KeyboardEvent } from 'react';\nimport type { VerseSeat } from '../../data/api-types.js';\nimport { CONTEXT_DANGER_PERCENT, CONTEXT_WARN_PERCENT } from './ContextMeter.js';\nimport { costHint, loadDraft, loadHistory, pushHistory, saveDraft } from './chat/composer-state.js';\nimport { DictationButton } from './DictationButton.js';\nimport type { SeatChoice } from './SeatSelector.js';\nimport { seatCapacity, SEAT_CAPACITY_WORD, seatPillLabel } from './verse-model.js';\nimport { formatTokens } from './verse-store.js';\nimport styles from './Composer.module.css';\n\nexport interface ComposerProps {\n /** Which chat this box belongs to — drafts and ↑ history are per session. */\n sessionId?: string | null;\n seats: readonly VerseSeat[];\n seat: SeatChoice;\n /** Engine of the current chat; only used for the pill's identity dot. */\n engine?: VerseSeat['engine'];\n running: boolean;\n disabled: boolean;\n disabledReason?: string | null;\n locked: boolean;\n /** True when this session already has turns — the hint row has done its job. */\n hintSeen?: boolean;\n /** Live context occupancy, for the pre-send cost hint. */\n contextTokens?: number | null;\n contextWindow?: number | null;\n onSend: (text: string) => Promise<boolean> | boolean;\n onStop: () => void;\n onSeatChange: (choice: SeatChoice) => void;\n autoFocus?: boolean;\n}\n\nconst MAX_TEXT_BYTES = 64 * 1024;\n\n/**\n * How long typing must pause before the draft is written to `localStorage`.\n *\n * `saveDraft` re-parses the whole drafts map, mutates it, re-serialises it and\n * writes it back synchronously — up to 40 sessions of 64 KB. On every keystroke\n * that lands on the main thread inside the composer's own render commit, which\n * is the one place in the app where the operator feels a stall directly. The\n * draft is a crash-recovery convenience, so 400ms of exposure costs nothing;\n * every path that actually loses the component flushes it immediately.\n */\nconst DRAFT_WRITE_DEBOUNCE_MS = 400;\n/** DESIGN §5: the box grows to 40% of the viewport, then scrolls. */\nconst MAX_HEIGHT_RATIO = 0.4;\nconst MAX_HEIGHT_FALLBACK_PX = 320;\n\nexport function Composer({ sessionId = null, seats, seat, engine, running, disabled, disabledReason, locked,\n hintSeen = false, contextTokens = null, contextWindow = null,\n onSend, onStop, onSeatChange, autoFocus = false }: ComposerProps) {\n // A draft survives ⌘K, a reload and a crash; it is restored on mount and\n // written back on every keystroke (Composer is keyed by session id, so a\n // mount is exactly one chat).\n const [draft, setDraft] = useState(() => loadDraft(sessionId));\n const [interim, setInterim] = useState('');\n const [sending, setSending] = useState(false);\n const [listening, setListening] = useState(false);\n const [sentHere, setSentHere] = useState(false);\n /** -1 = editing a fresh draft; 0..n-1 = walking back through sent messages. */\n const [historyAt, setHistoryAt] = useState(-1);\n // `useRef` takes a VALUE, not a lazy initializer: written as\n // `useRef(loadHistory(sessionId))` this re-read and re-parsed the whole sent\n // map from localStorage on every render — every keystroke and every streamed\n // token — and threw the result away each time. `useState`'s initializer is\n // the lazy one, and it runs exactly once, which is what the ref wanted.\n const [initialHistory] = useState(() => loadHistory(sessionId));\n const history = useRef<string[]>(initialHistory);\n const stashed = useRef('');\n const textarea = useRef<HTMLTextAreaElement>(null);\n const form = useRef<HTMLFormElement>(null);\n const helpId = useId();\n const text = interim ? `${draft}${draft && !draft.endsWith(' ') ? ' ' : ''}${interim}` : draft;\n const tooLong = useMemo(() => new TextEncoder().encode(text).length > MAX_TEXT_BYTES, [text]);\n const canSend = !disabled && !running && !sending && text.trim().length > 0 && !tooLong;\n const showHint = !hintSeen && !sentHere;\n const cost = useMemo(\n () => costHint(text, contextTokens, contextWindow, CONTEXT_WARN_PERCENT, CONTEXT_DANGER_PERCENT),\n [text, contextTokens, contextWindow],\n );\n\n // Persist the draft as it is typed, but not ON every keystroke — see\n // DRAFT_WRITE_DEBOUNCE_MS. Dictation interim text is deliberately NOT\n // persisted: it is not committed until the recognizer finalizes it.\n //\n // `persistedDraft` is what storage already holds, seeded with the value\n // `loadDraft` returned, so mounting does not write back what it just read.\n const persistedDraft = useRef(draft);\n const latestDraft = useRef(draft);\n latestDraft.current = draft;\n\n const flushDraft = useCallback(() => {\n if (persistedDraft.current === latestDraft.current) return;\n persistedDraft.current = latestDraft.current;\n saveDraft(sessionId, latestDraft.current);\n }, [sessionId]);\n\n useEffect(() => {\n if (persistedDraft.current === draft) return undefined;\n const id = setTimeout(flushDraft, DRAFT_WRITE_DEBOUNCE_MS);\n return () => clearTimeout(id);\n }, [draft, flushDraft]);\n\n // A tab closing, and the component going away (⌘K to another chat), are the\n // two ways the debounce window could otherwise swallow the last few\n // characters. Both flush synchronously.\n useEffect(() => {\n window.addEventListener('beforeunload', flushDraft);\n return () => {\n window.removeEventListener('beforeunload', flushDraft);\n flushDraft();\n };\n }, [flushDraft]);\n\n useEffect(() => {\n if (autoFocus) textarea.current?.focus();\n }, [autoFocus]);\n\n // ⌘. stops the running turn from anywhere in the app, the way ⌘. has meant\n // \"cancel\" on this platform for forty years. Only armed while a turn is\n // actually running, so it can never fire on an idle chat.\n useEffect(() => {\n if (!running) return;\n const onKey = (event: globalThis.KeyboardEvent) => {\n if (event.key !== '.' || (!event.metaKey && !event.ctrlKey) || event.shiftKey || event.altKey) return;\n event.preventDefault();\n onStop();\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [running, onStop]);\n\n // When the reply finishes, hand focus back to the box unless the operator\n // moved it somewhere deliberate outside the composer. Focus on <body>, on a\n // node that just unmounted (the Stop button), or on one of the composer's\n // own controls all count as \"nowhere useful\".\n useEffect(() => {\n if (running || !autoFocus) return;\n const active = document.activeElement;\n const ours = active !== null && active !== textarea.current && form.current?.contains(active) === true;\n if (active === null || active === document.body || !active.isConnected || ours) textarea.current?.focus();\n }, [running, autoFocus]);\n\n // Grow with content up to 40% of the viewport; shrink back when cleared.\n useEffect(() => {\n const node = textarea.current;\n if (!node) return;\n const viewport = typeof window === 'undefined' ? 0 : window.innerHeight;\n const max = viewport > 0 ? Math.round(viewport * MAX_HEIGHT_RATIO) : MAX_HEIGHT_FALLBACK_PX;\n node.style.height = 'auto';\n node.style.height = `${Math.min(node.scrollHeight, max)}px`;\n }, [text]);\n\n const submit = useCallback(async () => {\n if (!canSend) return;\n const value = text.trim();\n setSending(true);\n try {\n const ok = await onSend(value);\n if (ok) {\n const last = history.current[history.current.length - 1];\n if (last !== value) history.current = [...history.current, value];\n pushHistory(sessionId, value);\n setHistoryAt(-1);\n stashed.current = '';\n setDraft('');\n // Clear the stored draft now: the message is sent, and leaving it in\n // storage for the debounce window risks restoring a sent prompt.\n persistedDraft.current = '';\n latestDraft.current = '';\n saveDraft(sessionId, '');\n setInterim('');\n setSentHere(true);\n }\n } finally {\n setSending(false);\n textarea.current?.focus();\n }\n }, [canSend, text, onSend, sessionId]);\n\n /**\n * Shell-style recall. ↑ from the top of an untouched box walks back through\n * what was already sent here; ↓ walks forward and finally restores whatever\n * was being written. Only fires at the very start/end of the text, so\n * multi-line editing keeps both arrow keys.\n */\n function recall(delta: -1 | 1): boolean {\n const list = history.current;\n if (list.length === 0) return false;\n if (historyAt === -1) {\n if (delta > 0) return false;\n stashed.current = draft;\n const next = list.length - 1;\n setHistoryAt(next);\n setDraft(list[next]!);\n setInterim('');\n return true;\n }\n const next = historyAt + delta;\n if (next < 0) return true;\n if (next >= list.length) {\n setHistoryAt(-1);\n setDraft(stashed.current);\n return true;\n }\n setHistoryAt(next);\n setDraft(list[next]!);\n return true;\n }\n\n function onKeyDown(event: KeyboardEvent<HTMLTextAreaElement>) {\n const node = event.currentTarget;\n const collapsed = node.selectionStart === node.selectionEnd;\n if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault();\n void submit();\n return;\n }\n // ⌘/Ctrl+Enter also sends, so a hand already on the modifier for a\n // multi-line draft does not have to reach for plain Enter.\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey) && !event.nativeEvent.isComposing) {\n event.preventDefault();\n void submit();\n return;\n }\n // ⌘. is NOT handled here: the document-level listener above owns it, and\n // handling it in both places called onStop twice whenever the box had\n // focus — which is nearly always.\n //\n // History walking. ↑ enters history only from the very start of an\n // untouched box, so multi-line editing keeps the arrow keys; once IN\n // history both arrows walk it, because a recalled message leaves the\n // caret at its end and a second ↑ must still step back, the way a shell\n // does. Typing anything leaves history (see the textarea's onChange).\n if (event.key === 'ArrowUp' && collapsed && (historyAt !== -1 || (node.selectionStart === 0 && !interim))) {\n if (recall(-1)) event.preventDefault();\n return;\n }\n if (event.key === 'ArrowDown' && collapsed && historyAt !== -1) {\n if (recall(1)) event.preventDefault();\n }\n }\n\n const placeholder = disabled\n ? disabledReason ?? 'Sending is disabled'\n : running\n ? 'Draft your next message…'\n : 'Message the agent…';\n\n return (\n <form ref={form} className={styles.composer} onSubmit={(event) => { event.preventDefault(); void submit(); }} aria-describedby={helpId}>\n <div className={`${styles.box} ${listening ? styles.boxListening : ''}`}>\n <textarea ref={textarea} className={styles.textarea} value={text} rows={1} placeholder={placeholder}\n aria-label=\"Message\" disabled={disabled}\n onChange={(event) => { setInterim(''); setHistoryAt(-1); setDraft(event.target.value); }} onKeyDown={onKeyDown} />\n <div className={styles.row}>\n <SeatPill seats={seats} seat={seat} engine={engine} disabled={disabled} onNewChat={onSeatChange} />\n <div className={styles.spacer} />\n <DictationButton disabled={disabled}\n onInterim={setInterim}\n onFinal={(chunk) => setDraft((current) => (current && !current.endsWith(' ') ? `${current} ${chunk}` : `${current}${chunk}`))}\n onListeningChange={setListening} />\n {running ? (\n <button key=\"stop\" type=\"button\" className={styles.stop} onClick={onStop}\n title=\"Stop the running turn (⌘.)\" aria-label=\"Stop the running turn\">\n <span className={styles.stopIcon} aria-hidden=\"true\" />Stop\n </button>\n ) : (\n <button key=\"send\" type=\"submit\" className={styles.send} disabled={!canSend} aria-label={locked ? 'Send (unlocks first)' : 'Send message'}>\n {sending ? 'Sending…' : locked ? 'Unlock & send' : 'Send'}\n </button>\n )}\n </div>\n </div>\n {cost ? (\n <p className={styles.cost} data-tone={cost.tone} role=\"status\">\n <span className={styles.costFigure}>≈{formatTokens(cost.draftTokens)}</span> tokens for this message —\n sending would reach <span className={styles.costFigure}>{cost.projectedPercent}%</span> of the context window.\n {cost.tone === 'danger' ? ' Start a new chat to keep the agent sharp.' : ''}\n <span className=\"visually-hidden\"> This is an estimate; the provider counts the real total.</span>\n </p>\n ) : null}\n <p id={helpId} className={`${styles.help} ${showHint || tooLong || listening || running || disabled || historyAt !== -1 ? '' : styles.helpQuiet}`}>\n {tooLong ? <span role=\"alert\" className={styles.helpError}>Message is over 64 KB — trim it before sending.</span>\n : listening ? 'Listening… Esc stops dictation.'\n : disabled && disabledReason ? disabledReason\n : running ? <>Reply in progress — your draft stays here · <kbd>⌘.</kbd> or Stop interrupts the turn</>\n : historyAt !== -1 ? <>Recalled message {historyAt + 1} of {history.current.length} · <kbd>↓</kbd> returns to your draft</>\n : showHint\n ? <><kbd>Enter</kbd> sends · <kbd>Shift</kbd>+<kbd>Enter</kbd> new line · <kbd>↑</kbd> recalls · <kbd>⌘N</kbd> new chat · <kbd>⌘K</kbd> switch</>\n : null}\n </p>\n </form>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Seat pill + menu\n// ---------------------------------------------------------------------------\n\ninterface SeatPillProps {\n seats: readonly VerseSeat[];\n seat: SeatChoice;\n engine?: VerseSeat['engine'];\n disabled: boolean;\n onNewChat: (choice: SeatChoice) => void;\n}\n\nfunction SeatPill({ seats, seat, engine, disabled, onNewChat }: SeatPillProps) {\n const [open, setOpen] = useState(false);\n const wrap = useRef<HTMLDivElement>(null);\n const button = useRef<HTMLButtonElement>(null);\n const menuId = useId();\n const current = seatById(seats, seat.seatId);\n const tint = engine ?? current?.engine;\n const label = seatPillLabel(seats, { seatId: seat.seatId, engine: tint ?? 'claude', model: seat.model });\n const options = seats.filter((s) => s.health.state !== 'unavailable' && s.models.length > 0);\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (event: PointerEvent) => {\n if (wrap.current && !wrap.current.contains(event.target as Node)) setOpen(false);\n };\n const onKey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n setOpen(false);\n button.current?.focus();\n }\n };\n document.addEventListener('pointerdown', onPointerDown);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n useEffect(() => {\n if (open) wrap.current?.querySelector<HTMLButtonElement>('[role=\"menuitem\"]')?.focus();\n }, [open]);\n\n function onMenuKey(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;\n const items = Array.from(wrap.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]') ?? []);\n if (items.length === 0) return;\n event.preventDefault();\n const index = items.indexOf(document.activeElement as HTMLButtonElement);\n const next = event.key === 'ArrowDown' ? (index + 1) % items.length : (index - 1 + items.length) % items.length;\n items[next]?.focus();\n }\n\n return (\n <div ref={wrap} className={`${styles.seatPillWrap} ${tint ? styles[`engine-${tint}`] ?? '' : ''}`}>\n <button ref={button} type=\"button\" className={styles.seatPill} data-engine={tint}\n aria-haspopup=\"menu\" aria-expanded={open} aria-controls={open ? menuId : undefined} disabled={disabled}\n title=\"This chat is bound to one seat — open to start a new chat on another\"\n onClick={() => setOpen((v) => !v)}>\n <span className={styles.engineDot} aria-hidden=\"true\" />\n <span className={styles.seatPillText}>{label}</span>\n </button>\n {open ? (\n <div id={menuId} role=\"menu\" aria-label=\"Seat\" className={styles.seatMenu} onKeyDown={onMenuKey}>\n <p className={styles.seatMenuHeading}>This chat runs on <strong>{label}</strong></p>\n {options.length === 0 ? <p className={styles.seatMenuEmpty}>No other seats are available right now.</p> : null}\n {options.map((s) => {\n // The capacity belongs HERE, at the point of choice. This menu\n // filtered only on `health.state !== 'unavailable'`, and Claude's\n // health is `unknown` by construction, so a seat with a 100%-used\n // weekly window looked exactly like a fresh one.\n const capacity = seatCapacity(s);\n return (\n <button key={s.id} type=\"button\" role=\"menuitem\" className={`${styles.seatMenuItem} ${styles[`engine-${s.engine}`] ?? ''}`}\n data-capacity={capacity.cls}\n onClick={() => { setOpen(false); onNewChat({ seatId: s.id, model: s.models[0]!.id }); }}>\n <span className={styles.engineDot} aria-hidden=\"true\" />\n <span className={styles.seatMenuText}>\n <span className={styles.seatMenuPrimary}>New chat on {s.label}</span>\n <span className={styles.seatMenuSecondary}>{s.models[0]!.label}{s.id === seat.seatId ? ' · same seat' : ''}</span>\n {capacity.cls === 'unread' ? null : (\n <span className={styles.seatMenuCapacity}>\n {SEAT_CAPACITY_WORD[capacity.cls]} · {capacity.text}\n </span>\n )}\n </span>\n </button>\n );\n })}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction seatById(seats: readonly VerseSeat[], id: string): VerseSeat | undefined {\n return seats.find((s) => s.id === id);\n}\n","/**\n * routes/verse/chat/line-diff.ts — a unified diff for edits that never came\n * with one.\n *\n * `routes/inbox/diff-parser.ts` parses unified diffs and `DiffViewer.tsx`\n * renders them; neither is rewritten here. What is missing for the chat\n * transcript is the other direction: an `Edit` tool call carries\n * `old_string` / `new_string`, a `Write` carries `content`, and nothing in\n * the payload is a diff. This module produces the unified-diff TEXT for\n * those, so the existing parser and highlighter do the rest.\n *\n * Honesty (DESIGN §6). A tool payload says what was replaced, never where in\n * the file it sat, so the emitted hunk header starts at line 1 and callers\n * are told the result is `anchored: false`; the viewer then hides the\n * line-number gutter rather than printing numbers that are not the file's.\n *\n * Pure, no React, no DOM.\n */\n\n/** Above this many lines on either side the LCS table is too large to be\n * worth it, and a wholesale replacement is a truthful rendering anyway. */\nconst LCS_LINE_LIMIT = 1200;\n\nexport type DiffOp = { kind: 'same' | 'add' | 'del'; text: string };\n\n/**\n * Longest-common-subsequence line diff. O(n·m) time and memory, which is why\n * `LCS_LINE_LIMIT` exists; past it the caller gets one delete-all/add-all\n * block, which is what a wholesale rewrite genuinely is.\n */\nexport function diffLines(oldLines: readonly string[], newLines: readonly string[]): DiffOp[] {\n const n = oldLines.length;\n const m = newLines.length;\n if (n === 0 && m === 0) return [];\n if (n === 0) return newLines.map((text) => ({ kind: 'add' as const, text }));\n if (m === 0) return oldLines.map((text) => ({ kind: 'del' as const, text }));\n if (n > LCS_LINE_LIMIT || m > LCS_LINE_LIMIT) {\n return [\n ...oldLines.map((text) => ({ kind: 'del' as const, text })),\n ...newLines.map((text) => ({ kind: 'add' as const, text })),\n ];\n }\n\n // Trim the common prefix/suffix first: edits are usually local, and this\n // keeps the table small for the cases that matter most.\n let start = 0;\n while (start < n && start < m && oldLines[start] === newLines[start]) start++;\n let endOld = n - 1;\n let endNew = m - 1;\n while (endOld >= start && endNew >= start && oldLines[endOld] === newLines[endNew]) {\n endOld--;\n endNew--;\n }\n\n const a = oldLines.slice(start, endOld + 1);\n const b = newLines.slice(start, endNew + 1);\n const rows = a.length;\n const cols = b.length;\n const width = cols + 1;\n const table = new Int32Array((rows + 1) * width);\n for (let i = rows - 1; i >= 0; i--) {\n for (let j = cols - 1; j >= 0; j--) {\n table[i * width + j] = a[i] === b[j]\n ? table[(i + 1) * width + (j + 1)]! + 1\n : Math.max(table[(i + 1) * width + j]!, table[i * width + (j + 1)]!);\n }\n }\n\n const ops: DiffOp[] = [];\n for (let k = 0; k < start; k++) ops.push({ kind: 'same', text: oldLines[k]! });\n let i = 0;\n let j = 0;\n while (i < rows && j < cols) {\n if (a[i] === b[j]) {\n ops.push({ kind: 'same', text: a[i]! });\n i++;\n j++;\n } else if (table[(i + 1) * width + j]! >= table[i * width + (j + 1)]!) {\n ops.push({ kind: 'del', text: a[i]! });\n i++;\n } else {\n ops.push({ kind: 'add', text: b[j]! });\n j++;\n }\n }\n while (i < rows) ops.push({ kind: 'del', text: a[i++]! });\n while (j < cols) ops.push({ kind: 'add', text: b[j++]! });\n for (let k = endOld + 1; k < n; k++) ops.push({ kind: 'same', text: oldLines[k]! });\n return ops;\n}\n\nexport interface UnifiedDiffOptions {\n /** Path written into the `---`/`+++` headers. */\n path: string;\n /** Context lines kept around each change. */\n context?: number;\n /** Free text after the `@@` markers (e.g. `edit 2 of 3`). */\n section?: string;\n /** 1-based line the old side starts at, when it is genuinely known. */\n oldStart?: number;\n /** 1-based line the new side starts at, when it is genuinely known. */\n newStart?: number;\n}\n\n/**\n * Render ops as unified-diff text. Unchanged runs longer than 2×context\n * collapse into separate hunks, exactly as `diff -u` does, so an edit deep\n * in a long block does not drag the whole block into the view.\n */\nexport function toUnifiedDiff(ops: readonly DiffOp[], options: UnifiedDiffOptions): string {\n const context = Math.max(0, options.context ?? 3);\n const baseOld = options.oldStart ?? 1;\n const baseNew = options.newStart ?? 1;\n if (ops.length === 0 || !ops.some((op) => op.kind !== 'same')) return '';\n\n // Index every op with the line numbers it occupies on each side.\n interface Placed extends DiffOp { oldNo: number; newNo: number }\n const placed: Placed[] = [];\n let oldNo = baseOld;\n let newNo = baseNew;\n for (const op of ops) {\n placed.push({ ...op, oldNo, newNo });\n if (op.kind !== 'add') oldNo++;\n if (op.kind !== 'del') newNo++;\n }\n\n // Group changed ops into runs, each padded by `context` unchanged lines,\n // merging runs whose padding overlaps.\n const ranges: Array<{ from: number; to: number }> = [];\n for (let k = 0; k < placed.length; k++) {\n if (placed[k]!.kind === 'same') continue;\n const from = Math.max(0, k - context);\n const to = Math.min(placed.length - 1, k + context);\n const last = ranges[ranges.length - 1];\n if (last && from <= last.to + 1) last.to = Math.max(last.to, to);\n else ranges.push({ from, to });\n }\n\n const out: string[] = [`--- a/${options.path}`, `+++ b/${options.path}`];\n for (const range of ranges) {\n const slice = placed.slice(range.from, range.to + 1);\n const oldCount = slice.filter((op) => op.kind !== 'add').length;\n const newCount = slice.filter((op) => op.kind !== 'del').length;\n const firstOld = slice.find((op) => op.kind !== 'add')?.oldNo ?? baseOld;\n const firstNew = slice.find((op) => op.kind !== 'del')?.newNo ?? baseNew;\n const section = options.section ? ` ${options.section}` : '';\n out.push(`@@ -${oldCount === 0 ? firstOld - 1 : firstOld},${oldCount} +${newCount === 0 ? firstNew - 1 : firstNew},${newCount} @@${section}`);\n for (const op of slice) out.push(`${op.kind === 'add' ? '+' : op.kind === 'del' ? '-' : ' '}${op.text}`);\n }\n return out.join('\\n');\n}\n\n/** `old` → `new` as unified-diff text, or `''` when they are identical. */\nexport function unifiedDiffFor(oldText: string, newText: string, options: UnifiedDiffOptions): string {\n if (oldText === newText) return '';\n return toUnifiedDiff(diffLines(splitLines(oldText), splitLines(newText)), options);\n}\n\n/** Split preserving empty lines; a lone trailing newline is not a line. */\nexport function splitLines(text: string): string[] {\n if (text === '') return [];\n const lines = text.split('\\n');\n if (lines[lines.length - 1] === '') lines.pop();\n return lines;\n}\n","/**\n * routes/verse/chat/tool-semantics.ts — what a tool call actually DID.\n *\n * An agentic session is mostly tool work, and `{name, input, result}` is too\n * raw to read: the transcript can tell you `Edit` ran with some JSON, not\n * that `src/core/api.ts` gained four lines. Everything downstream — the\n * per-turn file-activity summary, the diff rendering, the command block, the\n * error affordances — needs the same derived facts, so they are derived ONCE\n * here, as pure functions over the event payload.\n *\n * Deliberately conservative. A fact that cannot be read out of the payload\n * (an exit code the tool never printed, the file offset an `Edit` payload\n * does not carry) is reported as unknown rather than guessed — DESIGN §6,\n * and the same discipline VERSE-TELEMETRY-V2 imposes on provider data.\n */\nimport { splitLines, unifiedDiffFor } from './line-diff.js';\n\nexport type ToolAction =\n | 'read'\n | 'edit'\n | 'create'\n | 'delete'\n | 'command'\n | 'search'\n | 'task'\n | 'web'\n | 'other';\n\n/** Actions that change the working tree — the blast radius of a turn. */\nexport const MUTATING_ACTIONS: readonly ToolAction[] = ['edit', 'create', 'delete'];\n\nexport interface ToolDiff {\n /** Unified-diff text, ready for `routes/inbox/diff-parser.ts`. */\n text: string;\n /**\n * False when the line numbers are synthetic. An `Edit` payload says what\n * was replaced, never where it sat, so the viewer hides the gutter rather\n * than printing numbers that are not the file's.\n */\n anchored: boolean;\n /** More than one file — the inbox `DiffViewer` file tree earns its place. */\n multiFile: boolean;\n /** Where the diff came from, for the block's caption. */\n origin: 'payload' | 'output';\n}\n\nexport interface CommandFacts {\n command: string;\n /** Only when the result states one in so many words; otherwise unknown. */\n exitCode: number | null;\n}\n\nexport interface WrittenContent {\n path: string;\n text: string;\n}\n\nexport interface ToolFacts {\n /** Normalized name with any MCP prefix removed (`ashlr__edit` → `edit`). */\n base: string;\n action: ToolAction;\n /** Files this call touched, most significant first; may be empty. */\n paths: string[];\n command: CommandFacts | null;\n diff: ToolDiff | null;\n /** A whole file written whose previous contents were never in the payload. */\n written: WrittenContent | null;\n /** The tool reported failure, or stated a non-zero exit. */\n failed: boolean;\n /** Still waiting for its result. */\n pending: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Name → action\n// ---------------------------------------------------------------------------\n\nconst ACTION_BY_NAME = new Map<string, ToolAction>([\n ['read', 'read'], ['readfile', 'read'], ['read_file', 'read'], ['view', 'read'],\n ['notebookread', 'read'], ['notebook_read', 'read'], ['cat', 'read'], ['open', 'read'],\n ['edit', 'edit'], ['multiedit', 'edit'], ['multi_edit', 'edit'], ['notebookedit', 'edit'],\n ['notebook_edit', 'edit'], ['str_replace', 'edit'], ['str_replace_editor', 'edit'],\n ['str_replace_based_edit_tool', 'edit'], ['apply_patch', 'edit'], ['patch', 'edit'],\n ['edit_structural', 'edit'], ['search_replace_regex', 'edit'], ['rename_file', 'edit'],\n ['update', 'edit'], ['applydiff', 'edit'], ['apply_diff', 'edit'],\n ['write', 'create'], ['create', 'create'], ['create_file', 'create'], ['writefile', 'create'],\n ['write_file', 'create'], ['new_file', 'create'],\n ['delete', 'delete'], ['delete_file', 'delete'], ['remove_file', 'delete'], ['rm', 'delete'],\n ['bash', 'command'], ['shell', 'command'], ['exec', 'command'], ['run', 'command'],\n ['run_command', 'command'], ['runcommand', 'command'], ['run_terminal_cmd', 'command'],\n ['bash_start', 'command'], ['bash_tail', 'command'], ['terminal', 'command'], ['test', 'command'],\n ['grep', 'search'], ['glob', 'search'], ['search', 'search'], ['find', 'search'],\n ['codebase_search', 'search'], ['ls', 'search'], ['tree', 'search'], ['list_dir', 'search'],\n ['task', 'task'], ['agent', 'task'], ['dispatch_agent', 'task'], ['subagent', 'task'],\n ['webfetch', 'web'], ['websearch', 'web'], ['fetch', 'web'], ['http', 'web'], ['browser', 'web'],\n]);\n\n/**\n * Strip transport prefixes so an MCP-routed edit reads as an edit:\n * `mcp__plugin_ashlr_ashlr__ashlr__edit` → `edit`.\n */\nexport function baseToolName(name: string): string {\n const parts = name.split('__').filter(Boolean);\n return (parts[parts.length - 1] ?? name).trim().toLowerCase();\n}\n\nexport function actionForName(name: string): ToolAction {\n return ACTION_BY_NAME.get(baseToolName(name)) ?? 'other';\n}\n\n/** Short verb for a file-activity row; also the a11y wording. */\nexport const ACTION_LABEL: Record<ToolAction, string> = {\n read: 'read',\n edit: 'edited',\n create: 'created',\n delete: 'deleted',\n command: 'ran',\n search: 'searched',\n task: 'delegated',\n web: 'fetched',\n other: 'used',\n};\n\n// ---------------------------------------------------------------------------\n// Payload readers\n// ---------------------------------------------------------------------------\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction str(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nconst PATH_KEYS = [\n 'file_path', 'filePath', 'notebook_path', 'notebookPath', 'target_file',\n 'path', 'file', 'filename', 'fileName', 'relative_workspace_path',\n];\n\n/** Every path-ish string in the payload, first-seen order, de-duplicated. */\nexport function pathsIn(input: unknown): string[] {\n const rec = record(input);\n if (!rec) return [];\n const out: string[] = [];\n const push = (value: unknown) => {\n const s = str(value);\n if (s && !out.includes(s)) out.push(s);\n };\n for (const key of PATH_KEYS) push(rec[key]);\n const list = rec.paths ?? rec.file_paths ?? rec.files;\n if (Array.isArray(list)) for (const item of list) push(typeof item === 'string' ? item : record(item)?.path);\n return out;\n}\n\n/** `src/web-ui/App.tsx` → `App.tsx`. Never the whole path in a dense row. */\nexport function fileBasename(path: string): string {\n const parts = path.split(/[\\\\/]/).filter(Boolean);\n return parts[parts.length - 1] ?? path;\n}\n\n/** The directory part, for the second line of a file-activity row. */\nexport function fileDirname(path: string): string {\n const parts = path.split(/[\\\\/]/);\n parts.pop();\n return parts.join('/');\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nconst COMMAND_KEYS = ['command', 'cmd', 'script', 'shell_command', 'commandLine'];\n\n/**\n * A line that is nothing but a stated exit status. Deliberately anchored to\n * the whole line: `exit 1` appearing inside a shell script in the output is\n * not the command's exit code, and reporting it as one would be a lie in the\n * place the operator is most likely to trust.\n */\nconst EXIT_LINE = /^[ \\t]*(?:exit(?:ed)?[ \\t]+(?:with[ \\t]+)?(?:code|status)|exit[ \\t]*code|exit[ \\t]*status|command[ \\t]+exited[ \\t]+with[ \\t]+code)[ \\t]*[:=]?[ \\t]*(\\d{1,3})[ \\t]*\\.?$/im;\n\n/** The exit code the output states, or null when it states none. */\nexport function statedExitCode(output: string): number | null {\n const match = EXIT_LINE.exec(output);\n if (!match) return null;\n const code = Number(match[1]);\n return Number.isInteger(code) && code >= 0 && code <= 255 ? code : null;\n}\n\n// ---------------------------------------------------------------------------\n// Diffs\n// ---------------------------------------------------------------------------\n\nconst GIT_HEADER = /^diff --git /m;\nconst OLD_HEADER = /^--- (?:a\\/|\\/dev\\/null|[^\\n]*\\t)/m;\nconst NEW_HEADER = /^\\+\\+\\+ (?:b\\/|\\/dev\\/null|[^\\n]*\\t)/m;\nconst HUNK_HEADER = /^@@ -\\d+(?:,\\d+)? \\+\\d+(?:,\\d+)? @@/m;\n\n/**\n * True when this text is itself a unified diff we can hand to the parser.\n *\n * A `@@` hunk is sufficient but NOT necessary. `git diff`/`git show` output\n * consisting only of renames, only of mode changes, or only of\n * \"Binary files … differ\" carries no hunk header at all; requiring one sent\n * that output down the raw-terminal path, where a rename reads as noise. The\n * parser already degrades a hunkless entry into `unparsedNotice` and a\n * `renamed`/`added`/`deleted` status, both of which `DiffBlock` renders — so a\n * `diff --git` header on its own is enough to treat the text as a diff.\n */\nexport function looksLikeUnifiedDiff(text: string): boolean {\n if (!text) return false;\n if (GIT_HEADER.test(text)) return true;\n // Without the git header the `---`/`+++` pair is only conclusive alongside a\n // hunk; plain prose can contain a line of dashes.\n return HUNK_HEADER.test(text) && OLD_HEADER.test(text) && NEW_HEADER.test(text);\n}\n\nfunction fileCount(diff: string): number {\n const git = diff.match(/^diff --git /gm);\n if (git) return git.length;\n return (diff.match(/^--- /gm) ?? []).length;\n}\n\ninterface EditPair { old: string; next: string }\n\n/** `{old_string, new_string}` under any of the spellings the tools use. */\nfunction editPair(value: unknown): EditPair | null {\n const rec = record(value);\n if (!rec) return null;\n const old = rec.old_string ?? rec.oldString ?? rec.old_str ?? rec.old ?? rec.search ?? rec.find;\n const next = rec.new_string ?? rec.newString ?? rec.new_str ?? rec.new ?? rec.replace ?? rec.replacement;\n if (typeof old !== 'string' || typeof next !== 'string') return null;\n return { old, next };\n}\n\n/**\n * One file header followed by every edit's hunks. Each edit gets its own\n * synthetic offset so the hunks stay distinct for the parser; the numbers\n * are not the file's, which is why the result is `anchored: false`.\n */\nfunction diffForEdits(path: string, edits: readonly EditPair[]): string {\n const bodies: string[] = [];\n let offset = 1;\n edits.forEach((edit, index) => {\n const text = unifiedDiffFor(edit.old, edit.next, {\n path,\n oldStart: offset,\n newStart: offset,\n section: edits.length > 1 ? `edit ${index + 1} of ${edits.length}` : undefined,\n });\n offset += Math.max(splitLines(edit.old).length, splitLines(edit.next).length) + 8;\n if (text) bodies.push(text.split('\\n').slice(2).join('\\n'));\n });\n if (bodies.length === 0) return '';\n return [`--- a/${path}`, `+++ b/${path}`, ...bodies].join('\\n');\n}\n\n/** A brand-new file as an all-additions diff; its new-side numbers are real. */\nfunction diffForCreate(path: string, content: string): string {\n const lines = splitLines(content);\n if (lines.length === 0) return '';\n return [\n `--- /dev/null`,\n `+++ b/${path}`,\n `@@ -0,0 +1,${lines.length} @@`,\n ...lines.map((line) => `+${line}`),\n ].join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// The one entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Ceiling on any agent-supplied text this module carries into a `ToolFacts`.\n *\n * `ToolUseCard` caps the raw output it renders, but the diff and written-file\n * paths bypass that cap entirely: they read `result.output` / `input.content`\n * straight off the payload. A `git diff` over a large tree, or a `Write` of a\n * generated file, then gets fully parsed by `DiffBlock` and fully materialised\n * into the DOM — and `buildTurns` re-parses it for every tool call on every\n * transcript rebuild. This is agent-controlled content with no upstream bound,\n * so the bound belongs here, where the text is first captured.\n *\n * Matches `CommandOutput`'s own ceiling so the two paths truncate alike.\n */\nexport const MAX_FACT_TEXT_CHARS = 200_000;\n\n/** Truncate with the same sentence `CommandOutput` uses, so the UI reads as one. */\nexport function capFactText(text: string): string {\n if (text.length <= MAX_FACT_TEXT_CHARS) return text;\n return `${text.slice(0, MAX_FACT_TEXT_CHARS)}\\n… (${text.length - MAX_FACT_TEXT_CHARS} more characters not shown)`;\n}\n\nexport interface ToolCallInput {\n name: string;\n input: unknown;\n result: { output: string; isError: boolean } | null;\n}\n\n/** Claude Code's Write says which of the two it did; nothing else does. */\nconst WROTE_EXISTING = /\\bhas been updated\\b|\\bsuccessfully (?:over)?written\\b|\\bupdated successfully\\b/i;\nconst WROTE_NEW = /\\b(?:file )?created successfully\\b|\\bnew file created\\b/i;\n\nexport function readToolFacts({ name, input, result }: ToolCallInput): ToolFacts {\n const base = baseToolName(name);\n let action = actionForName(name);\n const rec = record(input);\n const output = result?.output ?? '';\n const pending = result === null;\n\n // Write is create-or-overwrite and only the RESULT knows which.\n if (action === 'create' && result && WROTE_EXISTING.test(output) && !WROTE_NEW.test(output)) action = 'edit';\n\n const paths = pathsIn(input);\n const primary = paths[0] ?? null;\n\n let command: CommandFacts | null = null;\n if (rec) {\n for (const key of COMMAND_KEYS) {\n const value = str(rec[key]);\n if (value) {\n command = { command: value, exitCode: result ? statedExitCode(output) : null };\n if (action === 'other') action = 'command';\n break;\n }\n }\n }\n\n let diff: ToolDiff | null = null;\n let written: WrittenContent | null = null;\n\n // 1. The result is itself a diff (`git diff`, a patch tool echoing back).\n if (result && looksLikeUnifiedDiff(output)) {\n diff = { text: capFactText(output), anchored: true, multiFile: fileCount(output) > 1, origin: 'output' };\n }\n\n // 2. The INPUT is a diff (apply_patch / a patch argument).\n if (!diff && rec) {\n const patch = str(rec.patch) ?? str(rec.diff);\n if (patch && looksLikeUnifiedDiff(patch)) {\n diff = { text: capFactText(patch), anchored: true, multiFile: fileCount(patch) > 1, origin: 'payload' };\n }\n }\n\n // 3. Edit-shaped payloads: one pair, or MultiEdit's `edits` array.\n if (!diff && rec && primary) {\n const single = editPair(rec);\n const listValue = rec.edits ?? rec.replacements ?? rec.changes;\n const many = Array.isArray(listValue)\n ? listValue.map(editPair).filter((e): e is EditPair => e !== null)\n : [];\n const pairs = many.length > 0 ? many : single ? [single] : [];\n if (pairs.length > 0) {\n const text = diffForEdits(primary, pairs);\n if (text) diff = { text: capFactText(text), anchored: false, multiFile: false, origin: 'payload' };\n if (action === 'other') action = 'edit';\n }\n }\n\n // 4. A whole file written. A create's line numbers are real; an overwrite's\n // old side was never in the payload, so it is shown as content, not as a\n // diff claiming the file had nothing in it before.\n if (!diff && rec && primary) {\n const content = typeof rec.content === 'string' ? rec.content\n : typeof rec.contents === 'string' ? rec.contents\n : typeof rec.text === 'string' && (action === 'create' || action === 'edit') ? rec.text\n : null;\n if (content !== null) {\n if (action === 'create') {\n const text = diffForCreate(primary, content);\n if (text) diff = { text: capFactText(text), anchored: true, multiFile: false, origin: 'payload' };\n } else {\n written = { path: primary, text: capFactText(content) };\n }\n }\n }\n\n const failed = result !== null && (result.isError || (command?.exitCode ?? 0) > 0);\n\n return { base, action, paths, command, diff, written, failed, pending };\n}\n\n/** DOM id a file-activity row scrolls to. One per tool call. */\nexport function toolAnchorId(toolUseId: string): string {\n return `verse-tool-${toolUseId.replace(/[^A-Za-z0-9_-]/g, '')}`;\n}\n","/**\n * routes/verse/chat/turn-model.ts — a session as a list of TURNS.\n *\n * `verse-store.groupTranscriptItems()` already folds runs of tool calls into\n * one summary row; what it does not do is say where one exchange ends and\n * the next begins. Everything this file exists for needs that boundary: the\n * per-turn file-activity summary (the blast radius of one ask), the outline\n * that makes a fifty-turn session navigable, keyboard movement between\n * turns, and \"jump to the first error in this turn\".\n *\n * Pure over `groupTranscriptItems()`'s output — no React, no DOM, no\n * fetching — so the numbers in the summary can be tested directly against an\n * event log.\n */\nimport { parseUnifiedDiff } from '../../inbox/diff-parser.js';\nimport type { ToolGroupItem, TranscriptItem, TranscriptRenderItem } from '../verse-store.js';\nimport { readToolFacts, type ToolAction, type ToolFacts } from './tool-semantics.js';\n\nexport type TurnStatus = 'running' | 'ok' | 'error' | 'stopped';\n\n/**\n * Work that survives a transcript rebuild.\n *\n * `buildTurns` runs on EVERY streamed token: `useVerseSession` rebuilds\n * `state.events` per event, `buildTranscript` allocates fresh item objects from\n * it, and both of Transcript's memos therefore miss. Without this, every delta\n * re-derived the semantics of every tool call in the session — including a full\n * LCS diff per Edit payload, which allocates an `Int32Array` up to the 1200-line\n * cap. Fifty moderate edits cost hundreds of milliseconds of main-thread work\n * per frame, on the one surface whose frame budget is already spoken for.\n *\n * Caching is sound because `toolUseId` is a stable identity and a tool call's\n * `{name, input, result}` is immutable ONCE ITS RESULT HAS LANDED\n * (`verse-store.buildTranscript` replaces the item object exactly once, when the\n * `tool-result` event arrives). A cached entry derived while the call was still\n * pending is therefore the only one that can go stale, and it is the only one\n * recomputed.\n */\nexport interface TurnCache {\n facts: Map<string, ToolFacts>;\n /** `countDiffLines` over the same immutable diff text. */\n counts: Map<string, { additions: number; deletions: number }>;\n /** Flattened searchable text per tool call — the expensive half of the index. */\n toolText: Map<string, string>;\n}\n\nexport function createTurnCache(): TurnCache {\n return { facts: new Map(), counts: new Map(), toolText: new Map() };\n}\n\n/**\n * Facts for one tool call, reusing the cached instance whenever it is still\n * valid. Exported so a test can assert the second build recomputes nothing.\n */\nexport function cachedToolFacts(\n tool: { toolUseId: string; name: string; input: unknown; result: { output: string; isError: boolean } | null },\n cache: TurnCache | null,\n): ToolFacts {\n const hit = cache?.facts.get(tool.toolUseId);\n // A pending entry must be recomputed once the result lands; anything else is\n // derived from data that can no longer change.\n if (hit && !(hit.pending && tool.result !== null)) return hit;\n const fact = readToolFacts({ name: tool.name, input: tool.input, result: tool.result });\n if (cache) {\n cache.facts.set(tool.toolUseId, fact);\n cache.counts.delete(tool.toolUseId);\n cache.toolText.delete(tool.toolUseId);\n }\n return fact;\n}\n\nexport interface TurnFileEntry {\n path: string;\n reads: number;\n edits: number;\n creates: number;\n deletes: number;\n /** The strongest thing that happened to it: delete > create > edit > read. */\n action: Extract<ToolAction, 'read' | 'edit' | 'create' | 'delete'>;\n /** Tool call to scroll to when the row is clicked. */\n anchorToolUseId: string;\n /** Summed from the diffs the calls carried; 0 when none did. */\n additions: number;\n deletions: number;\n /** At least one call touching this file failed. */\n failed: boolean;\n}\n\nexport interface TurnBlock {\n key: string;\n turnId: string | null;\n items: TranscriptRenderItem[];\n /** The ask that opened the turn, for the outline. */\n prompt: string | null;\n /** ISO stamp of the first item. */\n at: string;\n files: TurnFileEntry[];\n toolCount: number;\n commandCount: number;\n /** Failing tool calls plus logged errors. */\n errorCount: number;\n /** Id of the first failing thing in the turn, for jump-to-error. */\n firstErrorAnchor: string | null;\n status: TurnStatus;\n durationMs: number | null;\n}\n\nexport interface TurnModel {\n turns: TurnBlock[];\n /** Facts keyed by toolUseId, so the cards do not re-derive them. */\n facts: Map<string, ToolFacts>;\n /** Every error anchor in document order — the transcript-level jump list. */\n errorAnchors: string[];\n}\n\n/** DOM id for a note (error / stopped / turn-done) so it can be scrolled to. */\nexport function noteAnchorId(key: string): string {\n return `verse-note-${key.replace(/[^A-Za-z0-9_-]/g, '')}`;\n}\n\n/** DOM id for one turn section. */\nexport function turnAnchorId(key: string): string {\n return `verse-turn-${key.replace(/[^A-Za-z0-9_-]/g, '')}`;\n}\n\nconst STRENGTH: Record<TurnFileEntry['action'], number> = { read: 0, edit: 1, create: 2, delete: 3 };\n\n/**\n * Additions/deletions for a unified diff, summed across every file in it.\n *\n * This was a flat scan that skipped any line starting with `---` or `+++` as a\n * file header. Inside a hunk those prefixes are CONTENT, not structure: a\n * deleted line reading `-- a/x` is emitted as `--- a/x`, a Markdown `---` rule\n * deleted is `----`, and a diff of a diff — what editing a `.patch` fixture or\n * running `git diff` over one produces — is made almost entirely of them. Every\n * such line was dropped, so the `+N −M` on the collapsed tool card undercounted\n * exactly the changes that are hardest to eyeball.\n *\n * Delegating to the shared parser (`routes/inbox/diff-parser.ts`) fixes that\n * and retires the second diff dialect: `DiffBlock` renders `file.additions` /\n * `file.deletions` out of this same parse, so the badge on the summary line and\n * the stats in the expanded block are now the same numbers by construction\n * rather than by two implementations happening to agree.\n *\n * Cost is real but bounded and paid once: `cachedDiffCounts` memoizes by\n * `toolUseId`, and the text is capped at `MAX_FACT_TEXT_CHARS` upstream.\n */\nexport function countDiffLines(text: string): { additions: number; deletions: number } {\n let additions = 0;\n let deletions = 0;\n for (const file of parseUnifiedDiff(text).files) {\n additions += file.additions;\n deletions += file.deletions;\n }\n return { additions, deletions };\n}\n\n/** `countDiffLines` over text that cannot change once cached. */\nfunction cachedDiffCounts(\n toolUseId: string,\n text: string,\n cache: TurnCache | null,\n): { additions: number; deletions: number } {\n const hit = cache?.counts.get(toolUseId);\n if (hit) return hit;\n const counts = countDiffLines(text);\n cache?.counts.set(toolUseId, counts);\n return counts;\n}\n\nfunction toolMembers(item: TranscriptRenderItem): Array<Extract<TranscriptItem, { kind: 'tool' }>> {\n if (item.kind === 'tool') return [item];\n if (item.kind === 'toolGroup') {\n return (item as ToolGroupItem).items.filter((m): m is Extract<TranscriptItem, { kind: 'tool' }> => m.kind === 'tool');\n }\n return [];\n}\n\n/**\n * A new turn opens on a `user` item, or on any item whose turnId differs\n * from the one being accumulated. Items that arrive before the first user\n * message (a resumed session's tail, a session-level error with a null\n * turnId) collect into a leading block rather than being dropped.\n */\nexport function buildTurns(\n items: readonly TranscriptRenderItem[],\n cache: TurnCache | null = null,\n): TurnModel {\n const facts = new Map<string, ToolFacts>();\n const errorAnchors: string[] = [];\n const turns: TurnBlock[] = [];\n\n let current: TranscriptRenderItem[] = [];\n const flush = () => {\n if (current.length === 0) return;\n turns.push(makeTurn(current, facts, errorAnchors, cache));\n current = [];\n };\n\n let turnId: string | null | undefined;\n for (const item of items) {\n const itemTurn = 'turnId' in item ? item.turnId : null;\n const boundary = item.kind === 'user' || (turnId !== undefined && itemTurn !== null && itemTurn !== turnId);\n if (boundary) flush();\n if (item.kind === 'user' || turnId === undefined || itemTurn !== null) turnId = itemTurn;\n current.push(item);\n }\n flush();\n\n return { turns, facts, errorAnchors };\n}\n\nfunction makeTurn(\n items: TranscriptRenderItem[],\n facts: Map<string, ToolFacts>,\n errorAnchors: string[],\n cache: TurnCache | null,\n): TurnBlock {\n const first = items[0]!;\n const byPath = new Map<string, TurnFileEntry>();\n let toolCount = 0;\n let commandCount = 0;\n let errorCount = 0;\n let firstErrorAnchor: string | null = null;\n let status: TurnStatus = 'running';\n let durationMs: number | null = null;\n let prompt: string | null = null;\n\n const noteError = (anchor: string) => {\n errorCount++;\n if (!firstErrorAnchor) firstErrorAnchor = anchor;\n errorAnchors.push(anchor);\n };\n\n for (const item of items) {\n if (item.kind === 'user' && prompt === null) prompt = item.text;\n\n for (const tool of toolMembers(item)) {\n toolCount++;\n const fact = cachedToolFacts(tool, cache);\n facts.set(tool.toolUseId, fact);\n if (fact.action === 'command') commandCount++;\n if (fact.failed) noteError(`verse-tool-${tool.toolUseId.replace(/[^A-Za-z0-9_-]/g, '')}`);\n\n const action = fact.action;\n if (action !== 'read' && action !== 'edit' && action !== 'create' && action !== 'delete') continue;\n const counts = fact.diff ? cachedDiffCounts(tool.toolUseId, fact.diff.text, cache) : { additions: 0, deletions: 0 };\n for (const path of fact.paths) {\n const entry = byPath.get(path) ?? {\n path,\n reads: 0, edits: 0, creates: 0, deletes: 0,\n action,\n anchorToolUseId: tool.toolUseId,\n additions: 0, deletions: 0,\n failed: false,\n };\n if (action === 'read') entry.reads++;\n else if (action === 'edit') entry.edits++;\n else if (action === 'create') entry.creates++;\n else entry.deletes++;\n if (STRENGTH[action] > STRENGTH[entry.action]) {\n entry.action = action;\n // The row should land on the call that CHANGED the file, not on the\n // read that happened to come first.\n entry.anchorToolUseId = tool.toolUseId;\n }\n if (action !== 'read') {\n entry.additions += counts.additions;\n entry.deletions += counts.deletions;\n }\n if (fact.failed) entry.failed = true;\n byPath.set(path, entry);\n }\n }\n\n switch (item.kind) {\n case 'error':\n noteError(noteAnchorId(item.key));\n status = 'error';\n break;\n case 'cancelled':\n status = 'stopped';\n break;\n case 'turn-done':\n durationMs = item.durationMs > 0 ? item.durationMs : durationMs;\n // A stop already explained itself; `ok:false` after it is not a\n // second failure (the same rule Transcript's `explained` set uses).\n if (item.ok) status = status === 'running' ? 'ok' : status;\n else if (status === 'running') {\n status = 'error';\n noteError(noteAnchorId(item.key));\n }\n break;\n default:\n break;\n }\n }\n\n return {\n key: first.key,\n turnId: 'turnId' in first ? first.turnId : null,\n items,\n prompt,\n at: first.at,\n // Strongest action first. The map is in first-touch order, and an agentic\n // turn reads widely before editing narrowly — so in read order the three\n // edits in a 40-file turn sit behind \"Show 35 more files\", hiding exactly\n // the rows whose `+N −M` justified the summary in the first place.\n files: [...byPath.values()].sort(\n (a, b) =>\n STRENGTH[b.action] - STRENGTH[a.action] ||\n b.additions + b.deletions - (a.additions + a.deletions) ||\n a.path.localeCompare(b.path),\n ),\n toolCount,\n commandCount,\n errorCount,\n firstErrorAnchor,\n status,\n durationMs,\n };\n}\n\n/** `12 files · 4 edited, 8 read` — the one-line form for a collapsed summary. */\nexport function describeFiles(files: readonly TurnFileEntry[]): string {\n if (files.length === 0) return '';\n const counts = { edited: 0, created: 0, deleted: 0, read: 0 };\n for (const file of files) {\n if (file.action === 'edit') counts.edited++;\n else if (file.action === 'create') counts.created++;\n else if (file.action === 'delete') counts.deleted++;\n else counts.read++;\n }\n const parts: string[] = [];\n if (counts.created) parts.push(`${counts.created} created`);\n if (counts.edited) parts.push(`${counts.edited} edited`);\n if (counts.deleted) parts.push(`${counts.deleted} deleted`);\n if (counts.read) parts.push(`${counts.read} read`);\n return parts.join(', ');\n}\n\n// ---------------------------------------------------------------------------\n// In-session search\n// ---------------------------------------------------------------------------\n\n/**\n * Everything in a turn that is worth searching, flattened once and cached on\n * the turn object. A rebuilt transcript produces new objects, so the WeakMap\n * lets the old strings go with them.\n */\nconst SEARCH_TEXT = new WeakMap<TurnBlock, string>();\n\n/** Per tool call — a build log should not make one turn megabytes of index. */\nconst TOOL_TEXT_LIMIT = 4000;\n\n/**\n * One tool call flattened for search. Cached by `toolUseId` under the same\n * immutability rule as the facts: `JSON.stringify` of a 4000-char payload per\n * call per keystroke is what made an active query cost the whole session.\n */\nfunction toolSearchText(\n item: Extract<TranscriptItem, { kind: 'tool' }>,\n cache: TurnCache | null,\n): string {\n const hit = cache?.toolText.get(item.toolUseId);\n if (hit !== undefined) return hit;\n const parts: string[] = [item.name];\n if (typeof item.input === 'string') parts.push(item.input.slice(0, TOOL_TEXT_LIMIT));\n else if (item.input) {\n try {\n parts.push(JSON.stringify(item.input).slice(0, TOOL_TEXT_LIMIT));\n } catch {\n /* a payload that will not stringify simply is not searchable */\n }\n }\n if (item.result) parts.push(item.result.output.slice(0, TOOL_TEXT_LIMIT));\n const text = parts.join('\\n');\n // Only cache a finished call: a pending one's output is still to come.\n if (cache && item.result) cache.toolText.set(item.toolUseId, text);\n return text;\n}\n\nexport function turnSearchText(turn: TurnBlock, cache: TurnCache | null = null): string {\n const cached = SEARCH_TEXT.get(turn);\n if (cached !== undefined) return cached;\n const parts: string[] = [];\n const visit = (item: TranscriptRenderItem | TranscriptItem): void => {\n switch (item.kind) {\n case 'user':\n case 'assistant':\n case 'thinking':\n parts.push(item.text);\n break;\n case 'error':\n parts.push(item.message);\n break;\n case 'tool':\n parts.push(toolSearchText(item, cache));\n break;\n case 'toolGroup':\n for (const member of (item as ToolGroupItem).items) visit(member);\n break;\n default:\n break;\n }\n };\n for (const item of turn.items) visit(item);\n const text = parts.join('\\n');\n SEARCH_TEXT.set(turn, text);\n return text;\n}\n\nexport interface TurnMatch {\n turnKey: string;\n /** Text around the first hit, for the outline row. */\n snippet: string;\n}\n\nconst SNIPPET_PAD = 48;\n\n/** Case-insensitive substring search across every turn, in document order. */\nexport function searchTurns(\n turns: readonly TurnBlock[],\n query: string,\n cache: TurnCache | null = null,\n): TurnMatch[] {\n const needle = query.trim().toLowerCase();\n if (needle.length === 0) return [];\n const out: TurnMatch[] = [];\n for (const turn of turns) {\n const haystack = turnSearchText(turn, cache);\n const at = haystack.toLowerCase().indexOf(needle);\n if (at === -1) continue;\n const from = Math.max(0, at - SNIPPET_PAD);\n const to = Math.min(haystack.length, at + needle.length + SNIPPET_PAD);\n const snippet = `${from > 0 ? '…' : ''}${haystack.slice(from, to).replace(/\\s+/g, ' ').trim()}${to < haystack.length ? '…' : ''}`;\n out.push({ turnKey: turn.key, snippet });\n }\n return out;\n}\n\n/** Turn title for the outline: the ask, trimmed to one line. */\nexport function turnTitle(turn: TurnBlock, max = 72): string {\n const source = turn.prompt?.replace(/\\s+/g, ' ').trim();\n if (source) return source.length > max ? `${source.slice(0, max - 1)}…` : source;\n if (turn.toolCount > 0) return `${turn.toolCount} tool call${turn.toolCount === 1 ? '' : 's'}`;\n return 'Session note';\n}\n","/**\n * routes/verse/chat/chat.module.css — the agentic parts of the transcript:\n * diffs, command output, the per-turn file summary and the nav strip.\n *\n * Same language as the rest of Verse (DESIGN §1–2): hairlines and whitespace\n * instead of cards, no shadows except on the one true overlay (the outline\n * menu), colour only where it carries meaning, and every meaning also\n * carried by a word or a glyph so nothing depends on the tint alone.\n */\n\n/* ========================================================================== */\n/* Diff */\n/* ========================================================================== */\n\n/*\n * The add/delete tints are the diff's OWN, not the badge `--status-*-bg`\n * tokens they used to borrow. Those are ~14% alpha and composite to\n * near-isoluminant pairs over `--bg-code` — 1.01:1 apart in light, 1.05:1 in\n * dark — so the only thing separating an addition from a deletion was a\n * red/green hue difference, the exact pair that collapses under\n * protanopia/deuteranopia.\n *\n * Mixing against `--bg-code` at 22% makes each row legible against the\n * surrounding context (1.24:1 / 1.32:1 light, 1.45:1 / 1.32:1 dark, where\n * before they were ~1.03:1 washes). It does NOT meaningfully separate the two\n * from EACH OTHER: measured, they are 1.06:1 apart in light and 1.10:1 in\n * dark. That is deliberate and it is the honest statement of the design —\n * weighting deletions heavier than additions to buy luminance would say\n * something about the change that is not true. The tint is a supporting cue;\n * the CARRIER is the `+`/`−` glyph in `.diffMarker`, which is why that column\n * is pinned to `--text-secondary` (body contrast on both tints) rather than\n * left at tertiary. design/tokens-contrast.test.ts asserts exactly that pair,\n * so the glyph cannot quietly recede back into the tint.\n */\n.diff {\n --diff-add: color-mix(in srgb, var(--status-success-solid) 22%, var(--bg-code));\n --diff-del: color-mix(in srgb, var(--status-danger-solid) 22%, var(--bg-code));\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-code);\n overflow: hidden;\n}\n\n/* Screen-reader-only text (the rename's \"renamed to\", which the arrow shows\n visually). Not display:none — it must stay in the accessibility tree. */\n.visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n.diffMulti { min-width: 0; }\n\n.diffHead {\n display: flex;\n align-items: center;\n gap: var(--space-3);\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2) 0 var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n}\n.diffPath {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n direction: rtl;\n text-align: left;\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n}\n/* A rename's OLD path. Recessive against the new one, which is the path the\n operator will go on to open, but present — dropping it was what made a\n rename read as \"nothing happened\". */\n.diffOldPath {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n direction: rtl;\n text-align: left;\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n.diffOldPath::after {\n content: ' \\2192';\n color: var(--text-tertiary);\n}\n\n/* The word, because a rename/add/delete is not conveyed by the paths alone. */\n.diffStatus {\n flex: 0 0 auto;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n\n.diffStats {\n flex: 0 0 auto;\n display: flex;\n gap: var(--space-2);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n}\n.diffAdd { color: var(--status-success-fg); }\n.diffDel { color: var(--status-danger-fg); }\n\n.diffNotice {\n margin: 0;\n padding: var(--space-2) var(--space-3);\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: var(--text-secondary);\n}\n.diffEmpty {\n padding: var(--space-3);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n.diffTable {\n width: 100%;\n border-collapse: collapse;\n table-layout: fixed;\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n.diffNo {\n width: 42px;\n min-width: 42px;\n padding: 0 var(--space-2);\n text-align: right;\n vertical-align: top;\n user-select: none;\n font-variant-numeric: tabular-nums;\n /* These are REAL line numbers the operator reads to locate a change in their\n editor, not a disabled-control label. `--text-disabled` measures 2.33:1\n light / 2.48:1 dark on `--bg-code` and is exempted from 4.5:1 only because\n WCAG exempts disabled text — an exemption this usage cannot borrow.\n `--text-tertiary` does not fix it either: it is 4.40:1 on light `--bg-code`\n (its 4.83:1 figure is against `--bg-surface`, a lighter ground).\n `--text-secondary` is the token already pinned above the floor on this\n ground, and is still clearly recessive against `.diffText`'s\n `--text-primary`. */\n color: var(--text-secondary);\n}\n.diffMarker {\n width: 14px;\n min-width: 14px;\n text-align: center;\n vertical-align: top;\n user-select: none;\n /* The +/− is the non-colour channel for add vs delete, so it has to clear the\n body floor on the tinted rows, not sit at tertiary. */\n color: var(--text-secondary);\n}\n.diffText {\n padding: 0 var(--space-2) 0 0;\n vertical-align: top;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.diffCode { font-family: inherit; }\n\n.diffRow_add { background: var(--diff-add); }\n.diffRow_del { background: var(--diff-del); }\n.diffRow_context { background: transparent; }\n\n.diffHunkRow > * {\n padding-top: var(--space-1);\n padding-bottom: var(--space-1);\n border-top: 1px solid var(--border-subtle);\n background: var(--bg-canvas);\n}\n.diffHunkRow:first-child > * { border-top: 0; }\n.diffHunkHead {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n\n.diffMore,\n.commandMore,\n.activityMore {\n display: block;\n width: 100%;\n min-height: var(--control-h-xs);\n padding: 0 var(--space-3);\n border-top: 1px solid var(--border-subtle);\n background: transparent;\n color: var(--text-secondary);\n font-family: var(--font-ui);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-medium);\n text-align: left;\n cursor: pointer;\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.diffMore:hover,\n.commandMore:hover,\n.activityMore:hover { background: var(--bg-hover); color: var(--text-primary); }\n\n.diffUnanchored {\n margin: 0;\n padding: var(--space-2) var(--space-3);\n border-top: 1px solid var(--border-subtle);\n color: var(--text-tertiary);\n /* Prose, not a micro-label: tokens.css sets the body floor at 12px and\n reserves --text-2xs for uppercase labels and keyboard hints. */\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n.tok_plain { color: var(--text-primary); }\n.tok_comment { color: var(--text-tertiary); font-style: italic; }\n.tok_string { color: var(--status-success-fg); }\n.tok_number { color: var(--status-warning-fg); }\n.tok_keyword { color: var(--accent-600); font-weight: var(--font-weight-medium); }\n\n/* ========================================================================== */\n/* Command output */\n/* ========================================================================== */\n\n.command {\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-code);\n overflow: hidden;\n}\n.command[data-failed='true'] { border-left: 2px solid var(--status-danger-solid); }\n\n.commandLine {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n padding: var(--space-2) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n}\n.commandPrompt {\n flex: 0 0 auto;\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n user-select: none;\n}\n.commandText {\n min-width: 0;\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n color: var(--text-primary);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.commandStatus {\n display: flex;\n align-items: center;\n gap: var(--space-3);\n min-height: var(--control-h-xs);\n padding: 0 var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n}\n.commandStatusText {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n font-variant-numeric: tabular-nums;\n color: var(--text-secondary);\n}\n.commandStatusText[data-tone='bad'] { color: var(--status-danger-fg); }\n.commandStatusText[data-tone='pending'] { color: var(--status-warning-fg); }\n.commandMeta {\n font-size: var(--text-2xs-size, 11px);\n color: var(--text-tertiary);\n}\n\n.commandPre {\n margin: 0;\n max-height: 420px;\n overflow: auto;\n padding: var(--space-3);\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n white-space: pre;\n color: var(--text-primary);\n tab-size: 8;\n}\n.commandPending {\n margin: 0;\n padding: var(--space-3);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n\n/* ========================================================================== */\n/* File activity — the blast radius of one turn */\n/* ========================================================================== */\n\n.activity {\n margin-top: var(--space-3);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n overflow: hidden;\n}\n\n.activityHead {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n min-height: var(--control-h-xs);\n padding: var(--space-1) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n background: var(--bg-canvas);\n}\n.activityCount {\n font-family: var(--font-display);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n font-variant-numeric: tabular-nums;\n color: var(--text-primary);\n}\n.activityLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n.activityBreakdown {\n margin-left: auto;\n font-size: var(--text-2xs-size, 11px);\n color: var(--text-tertiary);\n}\n\n.activityList { list-style: none; margin: 0; padding: 0; }\n/* Each row is wrapped in a Tooltip, whose wrapper spans are shrink-to-fit and\n would collapse the row's grid. Re-stretch them by STRUCTURE, not by the\n primitive's hashed class names. `:not([role='tooltip'])` keeps this away\n from the bubble itself — a blanket `display: block` would beat its `hidden`\n attribute and leave it painted open. */\n.activityList > li > span:not([role='tooltip']),\n.activityList > li > span > span:not([role='tooltip']) {\n display: block;\n width: 100%;\n min-width: 0;\n}\n\n.activityRow {\n display: grid;\n grid-template-columns: 2px 6ch minmax(0, 1fr) auto auto;\n align-items: center;\n gap: var(--space-2);\n width: 100%;\n min-height: var(--density-row-sm);\n padding: 0 var(--space-3) 0 0;\n background: transparent;\n border: 0;\n text-align: left;\n cursor: pointer;\n transition: background var(--duration-fast) var(--ease-standard);\n}\n.activityRow:hover { background: var(--bg-hover); }\n.activityRow:active { background: var(--bg-active); }\n\n/* The 2px rule repeats what .activityVerb says in words — never the only\n carrier of the meaning (DESIGN §6). For `data-failed` that was NOT true:\n the tint swapped from info to danger and nothing else changed, and those two\n solids are 1.29:1 apart in light and 1.08:1 in dark, i.e. the same rule once\n hue is removed. `.activityFailed` below is the word that carries it. */\n.activityRule { align-self: stretch; background: var(--border-default); }\n.activityRow[data-action='edit'] .activityRule { background: var(--status-info-solid); }\n.activityRow[data-action='create'] .activityRule { background: var(--status-success-solid); }\n.activityRow[data-action='delete'] .activityRule { background: var(--status-danger-solid); }\n.activityRow[data-failed='true'] .activityRule { background: var(--status-danger-solid); }\n\n.activityVerb {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n padding-left: var(--space-3);\n white-space: nowrap;\n}\n.activityRow[data-action='edit'] .activityVerb,\n.activityRow[data-action='create'] .activityVerb,\n.activityRow[data-action='delete'] .activityVerb { color: var(--text-secondary); }\n\n/* The visible failure marker: a glyph plus the word, in the danger FOREGROUND\n token (which clears the text floor) rather than the solid used for fills. */\n.activityFailed {\n flex: 0 0 auto;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n white-space: nowrap;\n color: var(--status-danger-fg);\n}\n\n.activityPath {\n display: flex;\n align-items: baseline;\n gap: var(--space-2);\n min-width: 0;\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n}\n.activityName { color: var(--text-primary); white-space: nowrap; }\n.activityDir {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n direction: rtl;\n text-align: left;\n color: var(--text-tertiary);\n font-size: var(--text-2xs-size, 11px);\n}\n.activityTimes,\n.activityDelta {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n white-space: nowrap;\n}\n.activityDelta { display: flex; gap: var(--space-2); }\n.activityAdd { color: var(--status-success-fg); }\n.activityDel { color: var(--status-danger-fg); }\n\n/* ========================================================================== */\n/* Nav strip + outline */\n/* ========================================================================== */\n\n.nav {\n position: relative;\n z-index: 1;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--density-row, 32px);\n padding: 0 var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n}\n.navSpacer { flex: 1; }\n\n.navOutlineButton {\n display: inline-flex;\n align-items: center;\n gap: var(--space-1);\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border-radius: var(--radius-xs);\n background: transparent;\n border: 0;\n color: var(--text-secondary);\n cursor: pointer;\n transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.navOutlineButton:hover { background: var(--bg-hover); color: var(--text-primary); }\n.navChevron { display: inline-flex; transition: transform var(--duration-fast) var(--ease-standard); }\n.navChevron[data-open='true'] { transform: rotate(90deg); }\n.navCount {\n font-family: var(--font-display);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-semibold);\n font-variant-numeric: tabular-nums;\n}\n.navWord {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n}\n\n.navSearch {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n flex: 0 1 26ch;\n min-width: 12ch;\n height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-input);\n transition: border-color var(--duration-fast) var(--ease-standard);\n}\n/* The wrapper is the visual control — the <input> inside it has no border,\n no ground and no padding of its own — so the standard ring belongs on the\n wrapper. It used to be a 1px border-colour change, which is not a focus\n indicator under DESIGN-V2 §6 (\"a visible :focus-visible ring, 2px accent,\n 2px offset\"); the global ring meanwhile landed on the bare input, inset\n inside the box the operator can actually see. Hoist one, suppress the\n other, and keep the border tint as the second channel. */\n.navSearch:focus-within {\n border-color: var(--accent-500);\n box-shadow: var(--shadow-focus-ring);\n}\n.navSearchIcon { display: inline-flex; color: var(--text-tertiary); }\n.navSearch input {\n min-width: 0;\n flex: 1;\n border: 0;\n background: none;\n color: var(--text-primary);\n font-family: var(--font-ui);\n font-size: var(--text-xs-size);\n}\n.navSearch input::-webkit-search-cancel-button { display: none; }\n.navSearch input:focus-visible { outline: none; box-shadow: none; }\n\n.navMatches {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.navStep { display: inline-flex; gap: 2px; }\n.navStep button {\n min-width: var(--control-h-xs);\n min-height: var(--control-h-xs);\n border: 0;\n border-radius: var(--radius-xs);\n background: transparent;\n color: var(--text-secondary);\n cursor: pointer;\n line-height: 1;\n}\n.navStep button:hover { background: var(--bg-hover); color: var(--text-primary); }\n\n.navError {\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 0;\n border-left: 2px solid var(--status-danger-solid);\n border-radius: 0 var(--radius-xs) var(--radius-xs) 0;\n background: transparent;\n color: var(--status-danger-fg);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-medium);\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--duration-fast) var(--ease-standard);\n}\n.navError:hover { background: var(--status-danger-bg); }\n.navErrorGlyph {\n font-family: var(--font-display);\n font-weight: var(--font-weight-semibold);\n}\n\n.outline {\n position: absolute;\n top: calc(100% + 2px);\n left: var(--space-2);\n right: var(--space-2);\n max-width: var(--measure-read);\n max-height: min(60vh, 520px);\n overflow-y: auto;\n padding: var(--space-1);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-surface-raised);\n box-shadow: var(--shadow-menu, var(--shadow-md));\n}\n.outlineEmpty {\n padding: var(--space-3);\n color: var(--text-tertiary);\n font-size: var(--text-xs-size);\n}\n.outlineList { list-style: none; margin: 0; padding: 0; }\n.outlineRow {\n display: grid;\n grid-template-columns: 3ch minmax(0, 1fr) auto;\n gap: var(--space-2);\n width: 100%;\n padding: var(--space-2);\n border: 0;\n border-radius: var(--radius-xs);\n background: transparent;\n text-align: left;\n cursor: pointer;\n transition: background var(--duration-fast) var(--ease-standard);\n}\n.outlineRow:hover { background: var(--bg-hover); }\n.outlineIndex {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n padding-top: 2px;\n}\n.outlineBody { display: grid; gap: 2px; min-width: 0; }\n.outlineTitle {\n font-size: var(--text-xs-size);\n color: var(--text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.outlineSnippet {\n font-family: var(--font-mono);\n /* A quotation from the transcript — content the operator reads to pick a\n turn, not a label. Body floor, per tokens.css. */\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.outlineMeta {\n font-size: var(--text-2xs-size, 11px);\n color: var(--text-tertiary);\n}\n.outlineStatus {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n color: var(--text-tertiary);\n}\n.outlineRow[data-status='error'] .outlineStatus { color: var(--status-danger-fg); }\n.outlineRow[data-status='running'] .outlineStatus { color: var(--status-running-fg); }\n\n@media (max-width: 900px) {\n .navSearch { flex-basis: 14ch; }\n .activityRow { grid-template-columns: 2px 6ch minmax(0, 1fr) auto auto; }\n .activityDir { display: none; }\n}\n","/**\n * routes/verse/chat/FileActivity.tsx — the blast radius of one turn.\n *\n * The question this answers is the first one asked of any agentic turn:\n * *what did it touch?* Today that costs expanding every tool card and\n * reading JSON. Here it is one compact list — which files were read,\n * edited, created or deleted, with counts and line deltas — and clicking a\n * row scrolls to the call that changed it.\n *\n * DESIGN §6: the action is a WORD, never only the tint on the rule. The\n * 2px left rule repeats the same information for scanning, and the row's\n * accessible name spells it out in full.\n */\nimport { useState } from 'react';\nimport { Tooltip } from '../../../components/primitives/Tooltip.js';\nimport { fileBasename, fileDirname } from './tool-semantics.js';\nimport { describeFiles, type TurnFileEntry } from './turn-model.js';\nimport styles from './chat.module.css';\n\n/** Beyond this the list collapses; a big refactor should not be a wall. */\nconst COLLAPSE_AFTER = 8;\n\nconst VERB: Record<TurnFileEntry['action'], string> = {\n read: 'read',\n edit: 'edited',\n create: 'created',\n delete: 'deleted',\n};\n\nexport interface FileActivityProps {\n files: readonly TurnFileEntry[];\n /** Scroll to the tool call that did the work. */\n onJump: (toolUseId: string) => void;\n}\n\nexport function FileActivity({ files, onJump }: FileActivityProps) {\n const [expanded, setExpanded] = useState(false);\n if (files.length === 0) return null;\n const visible = expanded || files.length <= COLLAPSE_AFTER ? files : files.slice(0, COLLAPSE_AFTER);\n const hidden = files.length - visible.length;\n\n return (\n <section className={styles.activity} aria-label=\"Files this turn touched\">\n <h3 className={styles.activityHead}>\n <span className={styles.activityCount}>{files.length}</span>\n <span className={styles.activityLabel}>file{files.length === 1 ? '' : 's'}</span>\n <span className={styles.activityBreakdown}>{describeFiles(files)}</span>\n </h3>\n <ul className={styles.activityList}>\n {visible.map((file) => {\n const times = file.reads + file.edits + file.creates + file.deletes;\n const name = `${VERB[file.action]} ${file.path}${times > 1 ? `, ${times} calls` : ''}${\n file.additions || file.deletions ? `, +${file.additions} −${file.deletions}` : ''\n }${file.failed ? ', a call on this file failed' : ''}`;\n return (\n <li key={file.path}>\n {/* The row draws the basename in full and lets the DIRECTORY\n clip, which is the half that tells two same-named files\n apart. The full path stays in aria-label — this restores it\n for sighted operators, on focus as well as hover. */}\n <Tooltip label={file.path} placement=\"right\">\n <button type=\"button\" className={styles.activityRow} data-action={file.action}\n data-failed={file.failed ? 'true' : undefined}\n onClick={() => onJump(file.anchorToolUseId)} aria-label={name}>\n <span className={styles.activityRule} aria-hidden=\"true\" />\n <span className={styles.activityVerb}>{VERB[file.action]}</span>\n <span className={styles.activityPath}>\n <span className={styles.activityName}>{fileBasename(file.path)}</span>\n <span className={styles.activityDir}>{fileDirname(file.path)}</span>\n </span>\n {file.failed ? (\n // DESIGN §6: the danger tint on the 2px rule was the ONLY\n // difference between a failed row and a successful one, and\n // it is the same rule once hue is removed. The word is what\n // actually carries it.\n <span className={styles.activityFailed} aria-hidden=\"true\">! failed</span>\n ) : null}\n {times > 1 ? <span className={styles.activityTimes}>×{times}</span> : null}\n <span className={styles.activityDelta}>\n {file.additions > 0 ? <span className={styles.activityAdd}>+{file.additions}</span> : null}\n {file.deletions > 0 ? <span className={styles.activityDel}>−{file.deletions}</span> : null}\n </span>\n </button>\n </Tooltip>\n </li>\n );\n })}\n </ul>\n {hidden > 0 || expanded ? (\n <button type=\"button\" className={styles.activityMore} aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}>\n {expanded ? 'Show fewer files' : `Show ${hidden} more file${hidden === 1 ? '' : 's'}`}\n </button>\n ) : null}\n </section>\n );\n}\n","/**\n * routes/verse/chat/TranscriptNav.tsx — making a fifty-turn session\n * navigable.\n *\n * A long agentic session scrolls past the point where scrolling is a way to\n * find anything. This strip gives it three handles: an outline of the turns\n * (with what each one touched), a search over everything in the transcript —\n * prose, tool arguments and tool output alike — and a jump straight to the\n * first failure.\n *\n * It is chrome, so it obeys DESIGN §4: one hairline-bottomed row at\n * `--density-row`, ghost controls only, no filled buttons. It renders only\n * when the session is long enough to need it, so a two-turn chat stays as\n * bare as it is today.\n */\nimport { useEffect, useId, useRef, useState } from 'react';\nimport { ChevronIcon, SearchIcon } from '../verse-icons.js';\nimport { turnTitle, type TurnBlock, type TurnMatch } from './turn-model.js';\nimport styles from './chat.module.css';\n\nexport interface TranscriptNavProps {\n turns: readonly TurnBlock[];\n query: string;\n onQuery: (value: string) => void;\n matches: readonly TurnMatch[];\n /** Index into `matches`, or -1 when nothing is selected yet. */\n matchIndex: number;\n onStepMatch: (delta: number) => void;\n errorCount: number;\n onJumpError: () => void;\n onJumpTurn: (turnKey: string) => void;\n /** Focus hand-off: the transcript raises this when ⌘F is pressed. */\n focusToken: number;\n}\n\nconst STATUS_GLYPH: Record<TurnBlock['status'], string> = {\n running: '•',\n ok: '',\n error: '!',\n stopped: '×',\n};\n\nconst STATUS_WORD: Record<TurnBlock['status'], string> = {\n running: 'running',\n ok: 'completed',\n error: 'failed',\n stopped: 'stopped',\n};\n\nexport function TranscriptNav(props: TranscriptNavProps) {\n const { turns, query, onQuery, matches, matchIndex, onStepMatch, errorCount, onJumpError, onJumpTurn, focusToken } = props;\n const [outlineOpen, setOutlineOpen] = useState(false);\n const search = useRef<HTMLInputElement>(null);\n const outlineId = useId();\n const searchId = useId();\n const searching = query.trim().length > 0;\n\n useEffect(() => {\n if (focusToken > 0) {\n search.current?.focus();\n search.current?.select();\n }\n }, [focusToken]);\n\n // Close the outline on Escape from anywhere inside it.\n useEffect(() => {\n if (!outlineOpen) return;\n const onKey = (event: globalThis.KeyboardEvent) => {\n if (event.key === 'Escape') setOutlineOpen(false);\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [outlineOpen]);\n\n const listed = searching\n ? turns.filter((turn) => matches.some((m) => m.turnKey === turn.key))\n : turns;\n const snippetFor = (key: string) => matches.find((m) => m.turnKey === key)?.snippet ?? null;\n\n return (\n <div className={styles.nav}>\n <button type=\"button\" className={styles.navOutlineButton} aria-expanded={outlineOpen}\n aria-controls={outlineOpen ? outlineId : undefined} onClick={() => setOutlineOpen((v) => !v)}>\n <span className={styles.navChevron} data-open={outlineOpen ? 'true' : undefined} aria-hidden=\"true\">\n <ChevronIcon size={12} />\n </span>\n <span className={styles.navCount}>{turns.length}</span>\n <span className={styles.navWord}>turn{turns.length === 1 ? '' : 's'}</span>\n </button>\n\n <label className={styles.navSearch} htmlFor={searchId}>\n <span className={styles.navSearchIcon} aria-hidden=\"true\"><SearchIcon size={12} /></span>\n <span className=\"visually-hidden\">Search this chat</span>\n <input ref={search} id={searchId} type=\"search\" value={query} placeholder=\"Find in chat\" autoComplete=\"off\"\n onChange={(event) => onQuery(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n onStepMatch(event.shiftKey ? -1 : 1);\n } else if (event.key === 'Escape') {\n event.preventDefault();\n onQuery('');\n }\n }} />\n </label>\n\n {searching ? (\n <span className={styles.navMatches} role=\"status\">\n {matches.length === 0\n ? 'no matches'\n : `${matchIndex < 0 ? 1 : matchIndex + 1} of ${matches.length}`}\n </span>\n ) : null}\n {searching && matches.length > 0 ? (\n <span className={styles.navStep}>\n <button type=\"button\" onClick={() => onStepMatch(-1)} aria-label=\"Previous match\" title=\"Previous match (Shift+Enter)\">↑</button>\n <button type=\"button\" onClick={() => onStepMatch(1)} aria-label=\"Next match\" title=\"Next match (Enter)\">↓</button>\n </span>\n ) : null}\n\n <span className={styles.navSpacer} />\n\n {errorCount > 0 ? (\n <button type=\"button\" className={styles.navError} onClick={onJumpError}>\n <span className={styles.navErrorGlyph} aria-hidden=\"true\">!</span>\n {errorCount} error{errorCount === 1 ? '' : 's'}\n <span className=\"visually-hidden\"> — jump to the first one</span>\n </button>\n ) : null}\n\n {outlineOpen ? (\n <div id={outlineId} className={styles.outline} role=\"group\" aria-label=\"Turns in this chat\">\n {listed.length === 0 ? (\n <p className={styles.outlineEmpty}>No turn matches “{query.trim()}”.</p>\n ) : (\n <ol className={styles.outlineList}>\n {listed.map((turn) => {\n const index = turns.indexOf(turn) + 1;\n const snippet = snippetFor(turn.key);\n return (\n <li key={turn.key}>\n <button type=\"button\" className={styles.outlineRow} data-status={turn.status}\n onClick={() => { setOutlineOpen(false); onJumpTurn(turn.key); }}>\n <span className={styles.outlineIndex}>{index}</span>\n <span className={styles.outlineBody}>\n <span className={styles.outlineTitle}>{turnTitle(turn)}</span>\n {snippet ? <span className={styles.outlineSnippet}>{snippet}</span> : null}\n <span className={styles.outlineMeta}>\n {turn.toolCount > 0 ? `${turn.toolCount} tool${turn.toolCount === 1 ? '' : 's'}` : 'no tools'}\n {turn.files.length > 0 ? ` · ${turn.files.length} file${turn.files.length === 1 ? '' : 's'}` : ''}\n {turn.status !== 'ok' ? ` · ${STATUS_WORD[turn.status]}` : ''}\n </span>\n </span>\n {STATUS_GLYPH[turn.status] ? (\n <span className={styles.outlineStatus} aria-hidden=\"true\">{STATUS_GLYPH[turn.status]}</span>\n ) : null}\n </button>\n </li>\n );\n })}\n </ol>\n )}\n </div>\n ) : null}\n </div>\n );\n}\n","/*! @license DOMPurify 3.4.15 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.15/LICENSE */\n\nfunction _arrayLikeToArray(r, a) {\n (null == a || a > r.length) && (a = r.length);\n for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];\n return n;\n}\nfunction _arrayWithHoles(r) {\n if (Array.isArray(r)) return r;\n}\nfunction _iterableToArrayLimit(r, l) {\n var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"];\n if (null != t) {\n var e,\n n,\n i,\n u,\n a = [],\n f = true,\n o = false;\n try {\n if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);\n } catch (r) {\n o = true, n = r;\n } finally {\n try {\n if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;\n } finally {\n if (o) throw n;\n }\n }\n return a;\n }\n}\nfunction _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nfunction _slicedToArray(r, e) {\n return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();\n}\nfunction _unsupportedIterableToArray(r, a) {\n if (r) {\n if (\"string\" == typeof r) return _arrayLikeToArray(r, a);\n var t = {}.toString.call(r).slice(8, -1);\n return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;\n }\n}\n\nconst entries = Object.entries,\n setPrototypeOf = Object.setPrototypeOf,\n isFrozen = Object.isFrozen,\n getPrototypeOf = Object.getPrototypeOf,\n getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\nlet freeze = Object.freeze,\n seal = Object.seal,\n create = Object.create; // eslint-disable-line import/no-mutable-exports\nlet _ref = typeof Reflect !== 'undefined' && Reflect,\n apply = _ref.apply,\n construct = _ref.construct;\nif (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n}\nif (!seal) {\n seal = function seal(x) {\n return x;\n };\n}\nif (!apply) {\n apply = function apply(func, thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n args[_key - 2] = arguments[_key];\n }\n return func.apply(thisArg, args);\n };\n}\nif (!construct) {\n construct = function construct(Func) {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n return new Func(...args);\n };\n}\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst arraySplice = unapply(Array.prototype.splice);\nconst arrayIsArray = Array.isArray;\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\nconst numberToString = unapply(Number.prototype.toString);\nconst booleanToString = unapply(Boolean.prototype.toString);\nconst bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);\nconst symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst objectToString = unapply(Object.prototype.toString);\nconst regExpTest = unapply(RegExp.prototype.test);\nconst typeErrorCreate = unconstruct(TypeError);\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(func) {\n return function (thisArg) {\n if (thisArg instanceof RegExp) {\n thisArg.lastIndex = 0;\n }\n for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n args[_key3 - 1] = arguments[_key3];\n }\n return apply(func, thisArg, args);\n };\n}\n/**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction unconstruct(Func) {\n return function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return construct(Func, args);\n };\n}\n/**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n if (!arrayIsArray(array)) {\n return set;\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n}\n/**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n}\n/**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction clone(object) {\n const newObject = create(null);\n for (const _ref2 of entries(object)) {\n var _ref3 = _slicedToArray(_ref2, 2);\n const property = _ref3[0];\n const value = _ref3[1];\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (arrayIsArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n}\n/**\n * Convert non-node values into strings without depending on direct property access.\n *\n * @param value - The value to stringify.\n * @returns A string representation of the provided value.\n */\nfunction stringifyValue(value) {\n switch (typeof value) {\n case 'string':\n {\n return value;\n }\n case 'number':\n {\n return numberToString(value);\n }\n case 'boolean':\n {\n return booleanToString(value);\n }\n case 'bigint':\n {\n return bigintToString ? bigintToString(value) : '0';\n }\n case 'symbol':\n {\n return symbolToString ? symbolToString(value) : 'Symbol()';\n }\n case 'undefined':\n {\n return objectToString(value);\n }\n case 'function':\n case 'object':\n {\n if (value === null) {\n return objectToString(value);\n }\n const valueAsRecord = value;\n const valueToString = lookupGetter(valueAsRecord, 'toString');\n if (typeof valueToString === 'function') {\n const stringified = valueToString(valueAsRecord);\n return typeof stringified === 'string' ? stringified : objectToString(stringified);\n }\n return objectToString(value);\n }\n default:\n {\n return objectToString(value);\n }\n }\n}\n/**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n}\nfunction isRegex(value) {\n try {\n regExpTest(value, '');\n return true;\n } catch (_unused) {\n return false;\n }\n}\n\nconst html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\nconst svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\nconst svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nconst svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\nconst mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nconst mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\nconst text = freeze(['#text']);\n\nconst html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'command', 'commandfor', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns']);\nconst svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dominant-baseline', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'pointer-events', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-orientation', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'vector-effect', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\nconst mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lquote', 'lspace', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\nconst xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\nconst MUSTACHE_EXPR = seal(/{{[\\w\\W]*|^[\\w\\W]*}}/g);\nconst ERB_EXPR = seal(/<%[\\w\\W]*|^[\\w\\W]*%>/g);\nconst TMPLIT_EXPR = seal(/\\${[\\w\\W]*/g);\nconst DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\nconst ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nconst IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nconst IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nconst ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nconst DOCTYPE_NAME = seal(/^html$/i);\nconst CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n// Markup-significant character probes used by _sanitizeElements.\n// Shared module-level instances are safe despite the sticky /g flags:\n// unapply() resets lastIndex for RegExp receivers before every call.\nconst ELEMENT_MARKUP_PROBE = seal(/<[/\\w!]/g);\nconst COMMENT_MARKUP_PROBE = seal(/<[/\\w]/g);\nconst FALLBACK_TAG_CLOSE = seal(/<\\/no(script|embed|frames)/i);\nconst SELF_CLOSING_TAG = seal(/\\/>/i);\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n processingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n};\n/* HTML-namespace elements whose child text nodes are serialized *literally*\n (unescaped) by the HTML fragment-serialization algorithm. Two reparse-mXSS\n shapes ride on that literal serialization:\n (a) an element child - a tree the HTML parser can never build, but the DOM\n API and an XML/XHTML parse can - after which a `</tag>`-bearing text\n sibling breaks the element open on reparse; and\n (b) text-only content that already carries the element's OWN end tag, e.g.\n `<style>...</style><img onerror=x>` built as a node, which the literal\n serializer emits verbatim for the HTML parser to re-open.\n Shape (a) is handled by the firstElementChild branch in _isUnsafeNode; shape\n (b) by the LITERAL_TEXT_CLOSE probe. Both read textContent (the raw-serialized\n form for these elements) rather than innerHTML, because an XML/XHTML working\n document serializes innerHTML with `<` escaped, which silently blinds the\n innerHTML-based probes (rule 1's second probe and FALLBACK_TAG_CLOSE) there.\n `script` is never allow-listed, but is kept here so the guard matches the\n serializer's own literal-text list exactly. */\nconst LITERAL_TEXT_ELEMENT_NAMES = ['style', 'script', 'xmp', 'iframe', 'noembed', 'noframes', 'plaintext', 'noscript'];\nconst LITERAL_TEXT_ELEMENTS = freeze(addToSet({}, LITERAL_TEXT_ELEMENT_NAMES));\n/* Per-element end-tag matcher. On an HTML reparse the ONLY token that\n terminates a literal-text element's raw content is its own end tag; a foreign\n literal-text close (e.g. `</xmp>` sitting inside `<style>`) does not break\n out, so matching is per-element, not a shared alternation. The lookahead\n requires an HTML tag-name terminator (whitespace, `/` or `>`) so a longer\n name such as `</styles` is not mistaken for `</style`. */\nconst LITERAL_TEXT_CLOSE = function () {\n const map = {};\n arrayForEach(LITERAL_TEXT_ELEMENT_NAMES, name => {\n map[name] = seal(new RegExp('</' + name + '(?=[\\\\t\\\\n\\\\f\\\\r />])', 'i'));\n });\n return freeze(map);\n}();\nconst getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n};\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n};\nconst _createHooksMap = function _createHooksMap() {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: []\n };\n};\n/**\n * Resolve a set-valued configuration option: a fresh set built from\n * cfg[key] when it is an own array property (seeded with a clone of\n * options.base when given, case-normalized via options.transform),\n * the fallback set otherwise.\n *\n * @param cfg the cloned, prototype-free configuration object\n * @param key the configuration property to read\n * @param fallback the set to use when the option is absent or not an array\n * @param options transform and optional base set to merge into\n * @returns the resolved set\n */\nconst _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) {\n return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;\n};\n/**\n * Resolve an object-valued configuration option: a prototype-free clone\n * of cfg[key] when it is an own, truthy object property, else a fresh\n * fallback built by makeFallback (fresh on every parse, so a previous\n * parse can never leak state into the next one).\n *\n * @param cfg the cloned, prototype-free configuration object\n * @param key the configuration property to read\n * @param makeFallback builds the fallback value when the option is absent\n * @returns the resolved object\n */\nconst _resolveObjectOption = function _resolveObjectOption(cfg, key, makeFallback) {\n const value = objectHasOwnProperty(cfg, key) ? cfg[key] : undefined;\n return value && typeof value === 'object' ? clone(value) : makeFallback();\n};\nfunction createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n DOMPurify.version = '3.4.15';\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let document = window.document;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n window.DocumentFragment;\n const HTMLTemplateElement = window.HTMLTemplateElement,\n Node = window.Node,\n Element = window.Element,\n NodeFilter = window.NodeFilter,\n _window$NamedNodeMap = window.NamedNodeMap;\n _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap;\n window.HTMLFormElement;\n const DOMParser = window.DOMParser,\n trustedTypes = window.trustedTypes;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n // Clobber-safe Attr-node removal. On an HTMLFormElement a descendant named\n // \"removeAttributeNode\" shadows the prototype method via\n // [LegacyOverrideBuiltIns], so element.removeAttributeNode(attr) throws.\n // Calling the cached Element.prototype method with the element as the\n // receiver removes the exact live Attr node regardless of the shadowing.\n const removeAttributeNode = lookupGetter(ElementPrototype, 'removeAttributeNode');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n const getShadowRoot = lookupGetter(ElementPrototype, 'shadowRoot');\n const getAttributes = lookupGetter(ElementPrototype, 'attributes');\n const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;\n const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeName') : null;\n const getOwnerDocument = Node && Node.prototype ? lookupGetter(Node.prototype, 'ownerDocument') : null;\n /* Clobber-safe nodeType / nodeName reads through the cached Node.prototype\n getters, with a direct-property fallback for environments that lack\n Node.prototype. Sites that need a different fallback (e.g. _isClobbered\n returns early on a null name) intentionally keep their own reads. */\n const _readNodeType = function _readNodeType(node) {\n return getNodeType ? getNodeType(node) : node.nodeType;\n };\n const _readNodeName = function _readNodeName(node) {\n return getNodeName ? getNodeName(node) : node.nodeName;\n };\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n // The instance's own internal Trusted Types policy. Unlike a caller-supplied\n // `TRUSTED_TYPES_POLICY`, this is created at most once — Trusted Types throws\n // on duplicate policy names — and is the only policy allowed to persist\n // across configurations and survive `clearConfig()`.\n let defaultTrustedTypesPolicy;\n let defaultTrustedTypesPolicyResolved = false;\n // Tracks whether we are already inside a call to the configured Trusted Types\n // policy (`createHTML` or `createScriptURL`). If a supplied policy callback\n // itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would\n // re-enter the policy and recurse until the stack overflows. We detect that\n // re-entry and throw a clear, actionable error instead. The guard is shared\n // across both callbacks, because either one re-entering `sanitize` triggers\n // the same unbounded recursion.\n let IN_TRUSTED_TYPES_POLICY = 0;\n const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy() {\n if (IN_TRUSTED_TYPES_POLICY > 0) {\n throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or ' + 'createScriptURL) must not call DOMPurify.sanitize, as that causes ' + 'infinite recursion. Do not pass a policy whose callbacks wrap ' + 'DOMPurify as TRUSTED_TYPES_POLICY; see the \"DOMPurify and Trusted ' + 'Types\" section of the README.');\n }\n };\n const _createTrustedHTML = function _createTrustedHTML(html) {\n _assertNotInTrustedTypesPolicy();\n IN_TRUSTED_TYPES_POLICY++;\n try {\n return trustedTypesPolicy.createHTML(html);\n } finally {\n IN_TRUSTED_TYPES_POLICY--;\n }\n };\n const _createTrustedScriptURL = function _createTrustedScriptURL(scriptUrl) {\n _assertNotInTrustedTypesPolicy();\n IN_TRUSTED_TYPES_POLICY++;\n try {\n return trustedTypesPolicy.createScriptURL(scriptUrl);\n } finally {\n IN_TRUSTED_TYPES_POLICY--;\n }\n };\n // Lazily resolve (and cache) the instance's internal default policy.\n // Resolution is attempted at most once: a successful `createPolicy` cannot be\n // repeated (Trusted Types throws on duplicate names), and a failed or\n // unsupported attempt must not be retried on every parse.\n const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy() {\n if (!defaultTrustedTypesPolicyResolved) {\n defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n defaultTrustedTypesPolicyResolved = true;\n }\n return defaultTrustedTypesPolicy;\n };\n const _document = document,\n implementation = _document.implementation,\n createNodeIterator = _document.createNodeIterator,\n createDocumentFragment = _document.createDocumentFragment,\n getElementsByTagName = _document.getElementsByTagName;\n const importNode = originalDocument.importNode;\n let hooks = _createHooksMap();\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const MUSTACHE_EXPR$1 = MUSTACHE_EXPR,\n ERB_EXPR$1 = ERB_EXPR,\n TMPLIT_EXPR$1 = TMPLIT_EXPR,\n DATA_ATTR$1 = DATA_ATTR,\n ARIA_ATTR$1 = ARIA_ATTR,\n IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE$1 = ATTR_WHITESPACE,\n CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;\n let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */\n const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {\n tagCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n }\n }));\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n /* Decide if document with <html>... should be returned */\n let WHOLE_DOCUMENT = false;\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n /* Pristine allowlist bindings captured at setConfig() time. On the\n * persistent-config path sanitize() restores the sets from these before\n * the per-walk hook clone-guard, so a hook's in-call widening cannot\n * carry across calls. Null until setConfig() is called; reset by\n * clearConfig(). */\n let SET_CONFIG_ALLOWED_TAGS = null;\n let SET_CONFIG_ALLOWED_ATTR = null;\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script',\n // <selectedcontent> mirrors the selected <option>'s subtree, cloned by\n // the UA (customizable <select>) — including any on* handlers — and the\n // engine re-mirrors synchronously whenever a removal changes which\n // option/selectedcontent is current, even inside DOMPurify's inert\n // DOMParser document. Hoisting its children on removal re-inserts a fresh\n // mirror target ahead of the walk, which the engine refills, looping\n // forever (DoS) and amplifying output. Dropping its content on removal\n // (rather than hoisting) breaks that cascade; the content is a duplicate\n // of the option, which is sanitized on its own. See campaign-3 F1/F6.\n 'selectedcontent', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze(['mi', 'mo', 'mn', 'ms', 'mtext']);\n let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);\n const DEFAULT_HTML_INTEGRATION_POINTS = freeze(['annotation-xml']);\n let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n /**\n * _parseConfig\n *\n * @param cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n /* Set configuration parameters */\n ALLOWED_TAGS = _resolveSetOption(cfg, 'ALLOWED_TAGS', DEFAULT_ALLOWED_TAGS, {\n transform: transformCaseFunc\n });\n ALLOWED_ATTR = _resolveSetOption(cfg, 'ALLOWED_ATTR', DEFAULT_ALLOWED_ATTR, {\n transform: transformCaseFunc\n });\n ALLOWED_NAMESPACES = _resolveSetOption(cfg, 'ALLOWED_NAMESPACES', DEFAULT_ALLOWED_NAMESPACES, {\n transform: stringToString\n });\n URI_SAFE_ATTRIBUTES = _resolveSetOption(cfg, 'ADD_URI_SAFE_ATTR', DEFAULT_URI_SAFE_ATTRIBUTES, {\n transform: transformCaseFunc,\n base: DEFAULT_URI_SAFE_ATTRIBUTES\n });\n DATA_URI_TAGS = _resolveSetOption(cfg, 'ADD_DATA_URI_TAGS', DEFAULT_DATA_URI_TAGS, {\n transform: transformCaseFunc,\n base: DEFAULT_DATA_URI_TAGS\n });\n FORBID_CONTENTS = _resolveSetOption(cfg, 'FORBID_CONTENTS', DEFAULT_FORBID_CONTENTS, {\n transform: transformCaseFunc\n });\n FORBID_TAGS = _resolveSetOption(cfg, 'FORBID_TAGS', clone({}), {\n transform: transformCaseFunc\n });\n FORBID_ATTR = _resolveSetOption(cfg, 'FORBID_ATTR', clone({}), {\n transform: transformCaseFunc\n });\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === 'object' ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; // Default regexp\n NAMESPACE = typeof cfg.NAMESPACE === 'string' ? cfg.NAMESPACE : HTML_NAMESPACE; // Default HTML namespace\n MATHML_TEXT_INTEGRATION_POINTS = _resolveObjectOption(cfg, 'MATHML_TEXT_INTEGRATION_POINTS', () => addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS) // Default built-in map\n );\n HTML_INTEGRATION_POINTS = _resolveObjectOption(cfg, 'HTML_INTEGRATION_POINTS', () => addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS) // Default built-in map\n );\n const customElementHandling = _resolveObjectOption(cfg, 'CUSTOM_ELEMENT_HANDLING', () => create(null));\n CUSTOM_ELEMENT_HANDLING = create(null);\n if (objectHasOwnProperty(customElementHandling, 'tagNameCheck') && isRegexOrFunction(customElementHandling.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined\n }\n if (objectHasOwnProperty(customElementHandling, 'attributeNameCheck') && isRegexOrFunction(customElementHandling.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; // Default undefined\n }\n if (objectHasOwnProperty(customElementHandling, 'allowCustomizedBuiltInElements') && typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; // Default undefined\n }\n seal(CUSTOM_ELEMENT_HANDLING);\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = create(null);\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n /* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent\n * leaking across calls when switching from function to array config */\n EXTRA_ELEMENT_HANDLING.tagCheck = null;\n EXTRA_ELEMENT_HANDLING.attributeCheck = null;\n /* Merge configuration parameters */\n if (objectHasOwnProperty(cfg, 'ADD_TAGS')) {\n if (typeof cfg.ADD_TAGS === 'function') {\n EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;\n } else if (arrayIsArray(cfg.ADD_TAGS)) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n }\n if (objectHasOwnProperty(cfg, 'ADD_ATTR')) {\n if (typeof cfg.ADD_ATTR === 'function') {\n EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;\n } else if (arrayIsArray(cfg.ADD_ATTR)) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n }\n if (objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);\n }\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n // Re-derive the active Trusted Types policy from this configuration on\n // every parse. The active policy must never be sticky closure state that\n // outlives the config that set it: a caller-supplied policy left in place\n // after `clearConfig()` — or after a later call that supplied none, or\n // `TRUSTED_TYPES_POLICY: null` — could sign a subsequent \"default\"\n // `RETURN_TRUSTED_TYPE` result with a foreign, possibly unsafe policy.\n // See GHSA-vxr8-fq34-vvx9.\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n // A caller-supplied policy applies to this configuration only.\n const previousTrustedTypesPolicy = trustedTypesPolicy;\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n // Sign local variables required by `sanitize`. If the supplied policy's\n // `createHTML` is circular (i.e. it calls `DOMPurify.sanitize`), this\n // throws via the re-entrancy guard. Restore the previous policy first so\n // the instance is not left in a poisoned state. See #1422.\n try {\n emptyHTML = _createTrustedHTML('');\n } catch (error) {\n trustedTypesPolicy = previousTrustedTypesPolicy;\n throw error;\n }\n } else if (cfg.TRUSTED_TYPES_POLICY === null) {\n // Explicit opt-out for this call: perform no Trusted Types signing and\n // create nothing (so a strict `trusted-types` CSP that disallows a\n // `dompurify` policy can still call `sanitize` from inside its own\n // policy — see #1422). Resetting to `undefined` rather than a sticky\n // `null` also drops any previously retained caller policy, so it cannot\n // resurface on a later call, while still allowing the next config-less\n // call to restore the internal default policy. See GHSA-vxr8-fq34-vvx9.\n trustedTypesPolicy = undefined;\n emptyHTML = '';\n } else {\n // No policy supplied: keep the currently active policy if one is set — a\n // previously supplied policy is intentionally sticky across config-less\n // calls — otherwise fall back to the instance's own internal policy,\n // created at most once. (A policy supplied for a *single* call still\n // lingers by design; what must not linger is a policy whose configuration\n // has been torn down via `clearConfig()`, which restores the default.)\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _getDefaultTrustedTypesPolicy();\n }\n // Sign internal variables only when a policy is active. A falsy policy\n // (Trusted Types unsupported, creation failed, or an explicit opt-out)\n // leaves `emptyHTML` as a plain string, so we never call `.createHTML` on\n // a non-policy and throw. See #1422.\n if (trustedTypesPolicy && typeof emptyHTML === 'string') {\n emptyHTML = _createTrustedHTML('');\n }\n }\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n /**\n * Namespace rules for an element in the SVG namespace.\n *\n * @param tagName the element's lowercase tag name\n * @param parent the (possibly simulated) parent node\n * @param parentTagName the parent's lowercase tag name\n * @returns true if a spec-compliant parser could produce this element\n */\n const _checkSvgNamespace = function _checkSvgNamespace(tagName, parent, parentTagName) {\n // The only way to switch from HTML namespace to SVG\n // is via <svg>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n // The only way to switch from MathML to SVG is via <svg>\n // if the parent is either <annotation-xml> or a MathML\n // text integration point.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n };\n /**\n * Namespace rules for an element in the MathML namespace.\n *\n * @param tagName the element's lowercase tag name\n * @param parent the (possibly simulated) parent node\n * @param parentTagName the parent's lowercase tag name\n * @returns true if a spec-compliant parser could produce this element\n */\n const _checkMathMlNamespace = function _checkMathMlNamespace(tagName, parent, parentTagName) {\n // The only way to switch from HTML namespace to MathML\n // is via <math>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n // The only way to switch from SVG to MathML is via\n // <math> and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n };\n /**\n * Namespace rules for an element in the HTML namespace.\n *\n * @param tagName the element's lowercase tag name\n * @param parent the (possibly simulated) parent node\n * @param parentTagName the parent's lowercase tag name\n * @returns true if a spec-compliant parser could produce this element\n */\n const _checkHtmlNamespace = function _checkHtmlNamespace(tagName, parent, parentTagName) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n };\n /**\n * @param element a DOM element whose namespace is being checked\n * @returns Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n return _checkSvgNamespace(tagName, parent, parentTagName);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n return _checkMathMlNamespace(tagName, parent, parentTagName);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n return _checkHtmlNamespace(tagName, parent, parentTagName);\n }\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n /**\n * _forceRemove\n *\n * @param node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n getParentNode(node).removeChild(node);\n } catch (_) {\n /* The normal detach failed — this is reached for a parentless node\n (getParentNode() is null, so .removeChild throws). Element.prototype\n .remove() is itself a spec no-op on a parentless node, so a recorded\n \"removal\" would otherwise hand the caller back an intact,\n payload-bearing node (e.g. a detached IN_PLACE root the mXSS canary or\n the style-with-element-child rule decided to kill). Fail closed by\n throwing — exactly as a clobbered root does at the IN_PLACE entry —\n rather than trying to \"neutralize\" the node via its own methods.\n Neutralizing would mean calling getAttributeNames()/removeAttribute()\n on the node, both of which a <form> root can clobber via a named child\n (and _isClobbered does not even probe getAttributeNames), so the\n neutralize step could itself be silently defeated, leaving the payload\n intact. A throw touches only the cached, clobber-safe remove() and\n getParentNode(). Generalizes GHSA-r47g-fvhr-h676 (clobbered-form root)\n to every root-kill reason. REPORT-3.\n This lives inside the catch, so it never fires for a normally-removed\n in-tree node: those have a parent, removeChild() succeeds, and the\n catch is not entered. Only a kept (parentless) root reaches here. */\n remove(node);\n if (!getParentNode(node)) {\n throw typeErrorCreate('a node selected for removal could not be detached from its tree ' + 'and cannot be safely returned; refusing to sanitize in place');\n }\n }\n };\n /**\n * _stripAttributeNode\n *\n * Remove a single Attr node case/namespace-exactly on an attribute-teardown\n * path. Name-based removeAttribute() ASCII-lowercases its lookup key for an\n * HTML element in an HTML document and so silently misses a case-preserved\n * handler (e.g. `ONERROR` off an XML/XHTML import) - the same defect\n * _removeAttribute() was fixed for, which a name-based call would reintroduce\n * on these IN_PLACE teardown paths. Unlike _removeAttribute this does not\n * record into DOMPurify.removed: the neutralize passes intentionally do not\n * book-keep. A clobbered/detached node falls back to best-effort name-based\n * removal.\n *\n * @param element the element to strip the attribute from\n * @param attribute the Attr node to remove\n * @param name the attribute's name, for the fallback path\n */\n const _stripAttributeNode = function _stripAttributeNode(element, attribute, name) {\n try {\n removeAttributeNode(element, attribute);\n } catch (_) {\n try {\n element.removeAttribute(name);\n } catch (_) {}\n }\n };\n /**\n * _neutralizeRoot\n *\n * Fail-closed teardown of an in-place root after the sanitize walk aborts\n * (campaign-3 F2). An internal throw mid-walk — e.g. a page-registered\n * custom element's reaction detaches a node so `_forceRemove`'s deliberate\n * parentless guard throws, or any other re-entrant engine mutation — would\n * otherwise leave the caller's *live* tree half-sanitized, with everything\n * after the abort point still carrying its handlers. There is no safe way\n * to resume the walk (the tree mutated under us), so we strip the root bare:\n * remove every child and every attribute, then let the caller's catch see\n * the original error. Clobber-safe (cached `remove`/`childNodes`/`attributes`\n * getters; the root was already clobber-pre-flighted at the IN_PLACE entry).\n *\n * @param root the in-place root to empty\n */\n const _neutralizeRoot = function _neutralizeRoot(root) {\n /* Strip every disallowed attribute (on* handlers included) off the whole\n subtree BEFORE detaching anything. Detaching first would hand back\n handler-bearing originals (e.g. an already-loading `<img onerror>`)\n whose queued resource event still fires in page scope after we throw.\n Clobber-safe reads; a doomed clobbered node's own attributes are\n irrelevant while its non-clobbered descendants are reached and scrubbed. */\n _neutralizeSubtree(root);\n const childNodes = getChildNodes(root);\n if (childNodes) {\n const snapshot = [];\n arrayForEach(childNodes, child => {\n arrayPush(snapshot, child);\n });\n arrayForEach(snapshot, child => {\n try {\n remove(child);\n } catch (_) {\n /* Best-effort teardown; a still-attached child is handled below */\n }\n });\n }\n const attributes = getAttributes(root);\n if (attributes) {\n for (let i = attributes.length - 1; i >= 0; --i) {\n const attribute = attributes[i];\n const name = attribute && attribute.name;\n if (typeof name === 'string') {\n _stripAttributeNode(root, attribute, name);\n }\n }\n }\n };\n /**\n * _removeAttribute\n *\n * Name-based getAttributeNode()/removeAttribute() ASCII-lowercase their\n * lookup key for HTML elements in an HTML document, so they silently miss an\n * attribute whose stored qualified name still contains uppercase ASCII\n * letters. That happens when the node came from a case-preserving source\n * (an XML/XHTML document imported via importNode(), or createAttributeNS()),\n * where e.g. `ONERROR` survives the walk: the policy check lowercases to\n * `onerror` and rejects it, but `removeAttribute('ONERROR')` looks up\n * `onerror` and finds nothing. Remove the exact Attr node instead, which is\n * case- and namespace-exact, and fall back to name-based removal only when\n * the caller could not supply the node.\n *\n * @param name an Attribute name\n * @param element a DOM node\n * @param attr the exact Attr node to remove, when the caller has it\n */\n const _removeAttribute = function _removeAttribute(name, element, attr) {\n if (!attr) {\n try {\n attr = element.getAttributeNode(name);\n } catch (_) {\n attr = null;\n }\n }\n arrayPush(DOMPurify.removed, {\n attribute: attr || null,\n from: element\n });\n try {\n if (attr) {\n removeAttributeNode(element, attr);\n } else {\n element.removeAttribute(name);\n }\n } catch (_) {\n /* Clobbered or already-detached node - best-effort fall back to a\n name-based removal so the \"is\" handling below still runs. Note this\n fallback ASCII-lowercases its lookup key in an HTML document and so\n cannot reach a case-preserved attribute name; the cached\n removeAttributeNode() above is what removes those, and a clobbered\n form is already removed wholesale by _isClobbered() before reaching\n here. */\n try {\n element.removeAttribute(name);\n } catch (_) {}\n }\n // We void attribute values for unremovable \"is\" attributes\n if (name === 'is') {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(element);\n } catch (_) {}\n } else {\n try {\n element.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n /**\n * _stripDisallowedAttributes\n *\n * Removes every attribute the active configuration does not allow from a\n * single element, using the same allowlist as the main attribute pass (so\n * `on*` handlers go, but no `/^on/` blocklist is introduced). Used only to\n * neutralise nodes that are being discarded from an in-place tree.\n *\n * @param element the element to strip\n */\n const _stripDisallowedAttributes = function _stripDisallowedAttributes(element) {\n const attributes = getAttributes(element);\n if (!attributes) {\n return;\n }\n for (let i = attributes.length - 1; i >= 0; --i) {\n const attribute = attributes[i];\n const name = attribute && attribute.name;\n if (typeof name !== 'string' || ALLOWED_ATTR[transformCaseFunc(name)]) {\n continue;\n }\n _stripAttributeNode(element, attribute, name);\n }\n };\n /**\n * _neutralizeSubtree\n *\n * Completes the audit-5 F1 fix across every removal path. The KEEP_CONTENT\n * move-hoist neutralises only disallowed-tag removals; clobber, mXSS-canary,\n * namespace, comment, processing-instruction and KEEP_CONTENT:false removals\n * all drop their subtree wholesale via `_forceRemove`. On the IN_PLACE path\n * those dropped nodes are detached from the caller's LIVE tree but a\n * handler-bearing original among them (an `<img onerror>`/`<video>` that was\n * loading) keeps its queued resource event, which fires in page scope after\n * sanitize returns. This walks a removed subtree and strips every attribute\n * the active configuration does not allow — so `on*` handlers are cancelled\n * through the SAME allowlist that governs kept nodes, not a separate `/^on/`\n * blocklist. Run synchronously before sanitize returns, i.e. before any\n * queued event can fire. Hook-free by design: these nodes leave the output,\n * so firing attribute hooks for them would be surprising. Clobber-safe reads;\n * a doomed clobbered node may shadow `removeAttribute` (its own attributes are\n * irrelevant — it is discarded — while its non-clobbered descendants, e.g.\n * the `<img>`, are reached and scrubbed).\n *\n * @param root the root of a removed subtree to neutralise\n */\n const _neutralizeSubtree = function _neutralizeSubtree(root) {\n const stack = [root];\n while (stack.length > 0) {\n const node = stack.pop();\n const nodeType = _readNodeType(node);\n if (nodeType === NODE_TYPE.element) {\n _stripDisallowedAttributes(node);\n }\n const childNodes = getChildNodes(node);\n if (childNodes) {\n for (let i = childNodes.length - 1; i >= 0; --i) {\n stack.push(childNodes[i]);\n }\n }\n }\n };\n /**\n * _neutralizePatchLinkage\n *\n * IN_PLACE entry pre-pass (declarative-partial-updates / streaming\n * hardening, https://github.com/WICG/declarative-partial-updates).\n *\n * The main walk strips patch linkage (`for`/`patchsrc`) and removes range\n * markers (PIs / markup comments) node-by-node, in document order, AS it\n * reaches each node. On a live in-place root that leaves a window: from the\n * moment the root is connected until the walk arrives at a given node, that\n * node's linkage is live. A patch applied on connection/stream can fire as\n * a microtask during the walk and inject or teleport an unsanitized DOM\n * range into a region the iterator has already passed and will not revisit,\n * so the post-return \"tree is sanitized\" contract is violated. Sweep the\n * whole tree once up front and sever every linkage before the walk begins,\n * closing that window.\n *\n * This CANNOT undo a patch that already fired before sanitize ran — that is\n * the irreducible \"do not IN_PLACE a live-connected attacker tree\" caveat —\n * but it closes everything from sanitize-start onward. Gated on SAFE_FOR_XML\n * to group with the rest of the declarative-partial-updates handling and\n * stay overridable, consistent with the codebase.\n *\n * Clobber-safe traversal (cached childNodes getter); per-node try/catch so a\n * clobbered root cannot defeat the sweep of its non-clobbered descendants.\n *\n * NOTE (pending real-Chrome confirmation, see test/declarative-patch-probe\n * .html Q1): this mirrors the existing policy of keeping `for` on\n * <label>/<output>. If the shipping feature can drive a patch through a\n * surviving `for`-on-label/output + `id` pair, this pre-pass and the\n * attribute check at _isBasicCustomElement's caller must additionally drop\n * that pair on the IN_PLACE path. Left as-is until the taxonomy is verified.\n *\n * @param root the in-place root to sweep\n */\n /**\n * Central policy for declarative-partial-updates patch-linkage attributes,\n * shared by the _neutralizePatchLinkage pre-pass and _isValidAttribute so\n * the two sites cannot drift: `patchsrc` always links, `for` links\n * everywhere except on <label>/<output>, and the whole policy is gated on\n * SAFE_FOR_XML (see the rationale block in _isValidAttribute).\n *\n * @param lcName the transformCaseFunc'd attribute name\n * @param lcTag the transformCaseFunc'd tag name of the carrying element\n * @return true if the attribute is patch linkage and must be dropped\n */\n const _isPatchLinkageAttribute = function _isPatchLinkageAttribute(lcName, lcTag) {\n if (!SAFE_FOR_XML) {\n return false;\n }\n if (lcName === 'patchsrc') {\n return true;\n }\n return lcName === 'for' && lcTag !== 'label' && lcTag !== 'output';\n };\n const _neutralizePatchLinkage = function _neutralizePatchLinkage(root) {\n if (!SAFE_FOR_XML) {\n return;\n }\n const stack = [root];\n while (stack.length > 0) {\n const node = stack.pop();\n const nodeType = _readNodeType(node);\n /* Remove range markers (the target side of a patch linkage): every\n processing instruction, and any markup-bearing comment. */\n if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) {\n try {\n remove(node);\n } catch (_) {\n /* Best-effort */\n }\n continue;\n }\n /* Strip patch-source attributes (the source side) off elements. */\n if (nodeType === NODE_TYPE.element) {\n const element = node;\n const lcTag = transformCaseFunc(_readNodeName(node));\n try {\n if (element.hasAttribute && element.hasAttribute('patchsrc')) {\n element.removeAttribute('patchsrc');\n }\n if (element.hasAttribute && element.hasAttribute('for') && _isPatchLinkageAttribute('for', lcTag)) {\n element.removeAttribute('for');\n }\n } catch (_) {\n /* Clobbered removeAttribute/hasAttribute on a doomed node — ignore */\n }\n }\n const childNodes = getChildNodes(node);\n if (childNodes) {\n for (let i = childNodes.length - 1; i >= 0; --i) {\n stack.push(childNodes[i]);\n }\n }\n }\n };\n /**\n * _initDocument\n *\n * @param dirty - a string of dirty markup\n * @return a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '<remove></remove>' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>' + dirty + '</body></html>';\n }\n const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param root The root element or node to start traversing on.\n * @return The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n /* Read ownerDocument through the cached Node.prototype getter, never the\n direct property. HTMLFormElement has [LegacyOverrideBuiltIns], so a\n clobbering child (<input name=\"ownerDocument\"> or a form-associated\n external input) shadows the prototype getter and makes a direct read\n return that <input>. createNodeIterator.call(<input>, ...) then throws\n \"Illegal invocation\", and on the IN_PLACE path that throw lands before\n the walk's fail-closed barrier - leaving the caller's live tree, with\n any already-armed handler in it, un-neutralized. The cached getter\n returns the real Document regardless of the clobber. */\n const doc = getOwnerDocument ? getOwnerDocument(root) : root.ownerDocument;\n return createNodeIterator.call(doc || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n /**\n * Replace template expression syntax (mustache, ERB, template\n * literal) with a space; shared by all SAFE_FOR_TEMPLATES scrub\n * sites. Order matters: mustache, then ERB, then template literal.\n *\n * @param value the string to scrub\n * @returns the scrubbed string\n */\n const _stripTemplateExpressions = function _stripTemplateExpressions(value) {\n value = stringReplace(value, MUSTACHE_EXPR$1, ' ');\n value = stringReplace(value, ERB_EXPR$1, ' ');\n value = stringReplace(value, TMPLIT_EXPR$1, ' ');\n return value;\n };\n /**\n * Strip template-engine expressions ({{...}}, ${...}, <%...%>) from the\n * character data of an element subtree. Used as the final safety net for\n * SAFE_FOR_TEMPLATES on every DOM-returning code path so that expressions\n * which only form after text-node normalization (e.g. fragments split across\n * stripped elements) cannot survive into a template-evaluating framework.\n *\n * Walks text/comment/CDATA/processing-instruction nodes and mutates `.data`\n * in place rather than round-tripping through innerHTML. This preserves\n * descendant node references (important for IN_PLACE callers), avoids a\n * serialize/reparse cycle, and reads literal character data — which means\n * `<%...%>` in text content matches the ERB regex against its real bytes\n * instead of the HTML-entity-escaped form innerHTML would produce.\n *\n * Attribute values are not visited here; SAFE_FOR_TEMPLATES handling for\n * attributes is performed during the per-node `_sanitizeAttributes` pass.\n *\n * @param node The root element whose character data should be scrubbed.\n */\n const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) {\n var _node$querySelectorAl;\n node.normalize();\n /* Clobber-safe ownerDocument read, same reasoning as _createNodeIterator:\n under SAFE_FOR_TEMPLATES this runs on the live IN_PLACE root, which may\n carry a form-named-getter override of ownerDocument. */\n const doc = getOwnerDocument ? getOwnerDocument(node) : node.ownerDocument;\n const walker = createNodeIterator.call(doc || node, node,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null);\n let currentNode = walker.nextNode();\n while (currentNode) {\n currentNode.data = _stripTemplateExpressions(currentNode.data);\n currentNode = walker.nextNode();\n }\n // NodeIterator does not descend into <template>.content per the DOM spec,\n // so we must explicitly recurse into each template's content fragment,\n // mirroring the approach used by _sanitizeShadowDOM.\n const templates = (_node$querySelectorAl = node.querySelectorAll) === null || _node$querySelectorAl === void 0 ? void 0 : _node$querySelectorAl.call(node, 'template');\n if (templates) {\n arrayForEach(templates, tmpl => {\n if (_isDocumentFragment(tmpl.content)) {\n _scrubTemplateExpressions2(tmpl.content);\n }\n });\n }\n };\n /**\n * _isClobbered\n *\n * Detect DOM-clobbering on HTMLFormElement nodes. Form is the only HTML\n * interface with [LegacyOverrideBuiltIns]; a descendant element with a\n * `name` attribute matching a prototype property shadows that property\n * on direct reads. We use this check at the IN_PLACE entry-point and\n * during attribute sanitization to refuse clobbered forms.\n *\n * @param element element to check for clobbering attacks\n * @return true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(element) {\n // Realm-independent tag-name probe. If we can't determine the tag\n // name at all, we can't reason about clobbering — return false\n // (the caller's other defences still apply).\n const realTagName = getNodeName ? getNodeName(element) : null;\n if (typeof realTagName !== 'string') {\n return false;\n }\n if (transformCaseFunc(realTagName) !== 'form') {\n return false;\n }\n return typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' ||\n // Realm-safe NamedNodeMap detection: equality against the cached\n // prototype getter. Clobbered .attributes (e.g. <input name=\"attributes\">)\n // makes the direct read diverge from the cached read; a clean form\n // (same-realm OR foreign-realm) has both reads pointing at the same\n // canonical NamedNodeMap.\n element.attributes !== getAttributes(element) || typeof element.removeAttribute !== 'function' ||\n // A form descendant named \"removeAttributeNode\" or \"getAttributeNode\"\n // shadows these Attr-node methods via [LegacyOverrideBuiltIns].\n // _removeAttribute() / _stripAttributeNode() reach for\n // element.removeAttributeNode(attr) first; when it is shadowed the call\n // throws and the name-based fallback element.removeAttribute(name)\n // ASCII-lowercases its lookup key in an HTML document, silently missing\n // a case-preserved event-handler attribute (e.g. an ONANIMATIONSTART\n // that reached the sanitizer through an XML/XHTML parse). Flag the form\n // so it is removed wholesale, exactly as for the other shadowed methods.\n typeof element.removeAttributeNode !== 'function' || typeof element.getAttributeNode !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function' ||\n // NodeType clobbering probe. Cached Node.prototype.nodeType getter\n // returns the integer 1 for any Element regardless of realm; direct\n // read on a clobbered form (e.g. <input name=\"nodeType\">) returns\n // the named child element. Cheap addition — nodeType is read from\n // an internal slot, no serialization cost — and removes a residual\n // clobbering surface used by several mXSS / PI / comment branches\n // in _sanitizeElements that compare currentNode.nodeType directly.\n element.nodeType !== getNodeType(element) ||\n // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named\n // \"childNodes\" shadows the prototype getter. Direct reads of\n // form.childNodes from a clobbered form return the named child\n // instead of the real NodeList, so any walk that reads it directly\n // skips the form's real children. Compare the direct read to the\n // cached Node.prototype getter — when the form's named-property\n // getter intercepts the read, the two values differ and we flag\n // the form. This catches every clobbering child type (input,\n // select, etc.) regardless of whether the named child happens to\n // carry a numeric .length, which a typeof-based probe would miss\n // (e.g. HTMLSelectElement.length is a defined unsigned-long).\n element.childNodes !== getChildNodes(element);\n };\n /**\n * Checks whether the given value is a DocumentFragment from any realm.\n *\n * The realm-independent replacement reads `nodeType` through the cached\n * Node.prototype getter and compares to the DOCUMENT_FRAGMENT_NODE\n * constant (11). nodeType is a numeric value resolved from the node's\n * internal slot, identical across realms for the same kind of node.\n *\n * @param value object to check\n * @return true if value is a DocumentFragment-shaped node from any realm\n */\n const _isDocumentFragment = function _isDocumentFragment(value) {\n if (!getNodeType || typeof value !== 'object' || value === null) {\n return false;\n }\n try {\n return getNodeType(value) === NODE_TYPE.documentFragment;\n } catch (_) {\n return false;\n }\n };\n /**\n * Checks whether the given object is a DOM node, including nodes that\n * originate from a different window/realm (e.g. an iframe's\n * contentDocument). The previous `value instanceof Node` check was\n * realm-bound: nodes from a different window failed it, causing\n * sanitize() to silently stringify them and reset IN_PLACE to false,\n * returning the original node unsanitized. See GHSA-4w3q-35jp-p934.\n *\n * @param value object to check whether it's a DOM node\n * @return true if value is a DOM node from any realm\n */\n const _isNode = function _isNode(value) {\n if (!getNodeType || typeof value !== 'object' || value === null) {\n return false;\n }\n try {\n return typeof getNodeType(value) === 'number';\n } catch (_) {\n return false;\n }\n };\n function _executeHooks(hooks, currentNode, data) {\n if (hooks.length === 0) {\n return;\n }\n arrayForEach(hooks, hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n }\n /**\n * Structural-threat checks that condemn a node regardless of the\n * allowlists: mXSS via namespace confusion, risky CSS construction,\n * processing instructions, markup-bearing comments. Pure predicate;\n * the caller removes. Check order is load-bearing.\n *\n * @param currentNode the node to inspect\n * @param tagName the node's transformCaseFunc'd tag name\n * @return true if the node must be removed\n */\n const _isUnsafeNode = function _isUnsafeNode(currentNode, tagName) {\n /* Detect mXSS attempts abusing namespace confusion */\n if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) {\n return true;\n }\n /* Remove rawtext/literal-text elements whose literal serialization\n re-opens markup on an HTML reparse - shapes (a) and (b) documented at\n LITERAL_TEXT_ELEMENTS. Both are invisible to rule 1 above (which\n self-disables once there is an element child, and whose second probe\n reads the innerHTML an XML/XHTML document serializes escaped), which\n is why both probes here read textContent instead. Previously only\n `style`-with-element-child was covered; every element in\n LITERAL_TEXT_ELEMENTS shares this literal serialization and is\n equally affected. */\n if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && LITERAL_TEXT_ELEMENTS[tagName] && (_isNode(currentNode.firstElementChild) || typeof currentNode.textContent === 'string' && regExpTest(LITERAL_TEXT_CLOSE[tagName], currentNode.textContent))) {\n return true;\n }\n /* Remove any occurrence of processing instructions */\n if (currentNode.nodeType === NODE_TYPE.processingInstruction) {\n return true;\n }\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) {\n return true;\n }\n return false;\n };\n /**\n * Evaluate a CUSTOM_ELEMENT_HANDLING check (a RegExp or a predicate\n * function, per the validation in _parseConfig) against a name.\n * Additional arguments are forwarded to predicate functions - the\n * attributeNameCheck predicate receives the tag name as its second\n * argument. A null/absent check never matches.\n *\n * @param check the configured tagNameCheck / attributeNameCheck value\n * @param name the name to test\n * @param args extra arguments forwarded to a predicate function\n * @return true if the check matches the name\n */\n const _matchesNameCheck = function _matchesNameCheck(check, name) {\n if (check instanceof RegExp) {\n return regExpTest(check, name);\n }\n if (check instanceof Function) {\n for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n args[_key - 2] = arguments[_key];\n }\n return Boolean(check(name, ...args));\n }\n return false;\n };\n /**\n * Handle a node whose tag is forbidden or not allowlisted: keep\n * allowed custom elements (false return exits _sanitizeElements\n * early - the namespace and fallback-tag removal checks are\n * intentionally skipped for kept custom elements), else hoist\n * content per KEEP_CONTENT and remove.\n *\n * A kept custom element is the ONLY case in which this function\n * returns false, so the caller uses that return value to run the\n * afterSanitizeElements hook on the kept element and keep the\n * element-hook lifecycle consistent with normal allowlisted\n * elements (GHSA-c2j3-45gr-mqc4).\n *\n * @param currentNode the disallowed node\n * @param tagName the node's transformCaseFunc'd tag name\n * @return true if the node was removed, false if kept\n */\n const _sanitizeDisallowedNode = function _sanitizeDisallowedNode(currentNode, tagName, root) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n /* Keep content except for bad-listed elements.\n Use the cached prototype getters exclusively — the previous code\n had `|| currentNode.parentNode` / `|| currentNode.childNodes`\n fallbacks, but the cached getters always return the canonical\n value (or null for a real parent-less node), so the fallback\n path was dead in safe cases and a clobbering surface in unsafe\n ones. Falsy cached results stay falsy; the `if (childNodes &&\n parentNode)` check already gates correctly. */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode);\n const childNodes = getChildNodes(currentNode);\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n /* Hoist by moving each child up one level rather than deep-cloning\n it. Moving transfers every descendant exactly once, so a chain of\n nested disallowed elements costs O(n) instead of the O(n^2) that\n re-cloning the shrinking subtree at each level produced; it also\n empties the removed original, so `DOMPurify.removed` no longer\n pins whole subtrees. Moving preserves the in-place guarantee too:\n an original carrying already-queued resource events (`<img\n onerror>`, `<video>`/`<audio>` error, lazy/`onload`, …) is\n relocated and sanitised rather than left detached but still armed.\n The sole case that must clone is removing the walk root itself.\n The result is serialised from the root's subtree, so a restrictive\n ALLOWED_TAGS that strips the root (`body` on the string path) must\n leave the content inside it, which only cloning does. In IN_PLACE\n the root is pre-validated as an allowed tag and so is never removed\n here, so that path always takes the move branch.\n `childNodes` is live; a tail-to-head walk keeps `childNodes[i]`\n valid whether we move (drops the trailing entry) or clone (leaves\n the list intact). */\n for (let i = childCount - 1; i >= 0; --i) {\n const hoisted = currentNode === root ? cloneNode(childNodes[i], true) : childNodes[i];\n parentNode.insertBefore(hoisted, getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n };\n /**\n * Fork a hook-mutable allowlist off its shared binding the first time a\n * (possibly lazily-installed) uponSanitize* hook is about to see it, so the\n * hook cannot widen the per-instance default or the setConfig binding by\n * reference and leak past the call. Returns the set unchanged once it is\n * already call-local, so repeated calls across elements are idempotent.\n *\n * @param hookList the uponSanitize* hook array for this event\n * @param set the current ALLOWED_TAGS / ALLOWED_ATTR binding\n * @param defaultSet the per-instance DEFAULT_ALLOWED_* constant\n * @param setConfigSet the captured setConfig() binding, or null\n * @return a call-local clone if a hook is present and set is still shared,\n * else set unchanged\n */\n const _forkSharedAllowlist = function _forkSharedAllowlist(hookList, set, defaultSet, setConfigSet) {\n if (hookList.length === 0) {\n return set;\n }\n return set === defaultSet || set === setConfigSet ? clone(set) : set;\n };\n /**\n * Shared guard for a node that a hook has detached from the walk tree,\n * used after each element-hook site in _sanitizeElements. Detaching is a\n * long-standing user pattern (issue #469; draw.io-style foreignObject\n * filtering). Per the cached, unclobberable parentNode getter the node is\n * genuinely out of the tree, so it can reach neither the serialized\n * output nor an IN_PLACE live tree; treat it as removed and stop\n * processing it. Without this guard, the unsafe-node / namespace checks\n * would call _forceRemove on a parentless node and hit the REPORT-3\n * fail-closed throw — which exists for nodes DOMPurify wants gone but\n * *cannot* detach (clobbered / parentless roots), the opposite of a node\n * that is already safely gone. The walk root is exempt: a detached\n * IN_PLACE root is legitimate input and must still be fully sanitized,\n * and a kill-decision on it must keep hitting the REPORT-3 throw.\n *\n * Nodes detached by hooks stay the hook's responsibility for placement:\n * they are not recorded in DOMPurify.removed, so the post-walk IN_PLACE\n * pass (which iterates DOMPurify.removed) does not reach them. But a\n * hook-detached subtree can still hold a queued resource-event handler -\n * e.g. an <img onload> that began loading when the caller built the live\n * tree - which fires in page scope after sanitize returns even though the\n * handler never reached the returned tree. That is the audit-5 F1 hazard,\n * and the documented node.remove() hook pattern walks straight into it.\n * So on the IN_PLACE path we neutralize the detached subtree inline,\n * stripping its non-allow-listed attributes before returning, exactly as\n * the post-walk pass does for _forceRemove'd subtrees.\n *\n * @param currentNode the node a hook may have detached\n * @param root the current walk root\n * @return true if the node is detached and now handled, false otherwise\n */\n const _handleHookDetachedNode = function _handleHookDetachedNode(currentNode, root) {\n if (currentNode === root || getParentNode(currentNode) !== null) {\n return false;\n }\n if (IN_PLACE) {\n _neutralizeSubtree(currentNode);\n }\n return true;\n };\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n * @param currentNode to check for permission to exist\n * @return true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode, root) {\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeElements, currentNode, null);\n /* A hook may have detached the node - treat it as removed (see\n _handleHookDetachedNode for the full rationale). */\n if (_handleHookDetachedNode(currentNode, root)) {\n return true;\n }\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(_readNodeName(currentNode));\n /* Close the pre-walk clone-guard's timing gap: an uponSanitizeElement\n hook may have been installed after that guard sampled the hook arrays\n (e.g. lazily from beforeSanitizeElements), leaving ALLOWED_TAGS still\n aliasing a shared binding that a widening hook would mutate by\n reference. Fork it before exposing it to the hook. */\n ALLOWED_TAGS = _forkSharedAllowlist(hooks.uponSanitizeElement, ALLOWED_TAGS, DEFAULT_ALLOWED_TAGS, SET_CONFIG_ALLOWED_TAGS);\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeElement, currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n /* The uponSanitizeElement hook may have detached the node, exactly as\n above (see _handleHookDetachedNode for the full rationale). */\n if (_handleHookDetachedNode(currentNode, root)) {\n return true;\n }\n /* Remove mXSS vectors, processing instructions and risky comments */\n if (_isUnsafeNode(currentNode, tagName)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove element if anything forbids its presence */\n if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {\n const removed = _sanitizeDisallowedNode(currentNode, tagName, root);\n /* A false return means the node is a custom element kept via\n CUSTOM_ELEMENT_HANDLING - the only keep path through\n _sanitizeDisallowedNode. Run afterSanitizeElements on it so the\n element-hook lifecycle matches normal allowlisted elements: a\n security policy applied in this hook (e.g. stripping an attribute\n from every surviving element) must not silently skip kept custom\n elements (GHSA-c2j3-45gr-mqc4). This mirrors the normal-element\n tail below - the hook runs, then the walker's subsequent\n _sanitizeAttributes pass sanitizes the element's attributes. The\n deliberately skipped namespace and fallback-tag removal checks stay\n skipped; they are removal decisions, not the hook contract. */\n if (removed === false) {\n _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n }\n return removed;\n }\n /* Check whether element has a valid namespace.\n Realm-safe check (GHSA-hpcv-96wg-7vj8): use the cached Node.prototype\n nodeType getter rather than `instanceof Element`, which is realm-\n bound and short-circuits to false for any node minted in a different\n realm — letting a foreign-realm element with a forbidden namespace\n slip past the namespace check entirely. */\n const nt = _readNodeType(currentNode);\n if (nt === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(FALLBACK_TAG_CLOSE, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {\n /* Get the element's text content */\n const content = _stripTemplateExpressions(currentNode.textContent);\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n return false;\n };\n /**\n * _isValidAttribute\n *\n * @param lcTag Lowercase tag name of containing element.\n * @param lcName Lowercase attribute name.\n * @param value Attribute value.\n * @return Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */\n if (FORBID_ATTR[lcName]) {\n return false;\n }\n /* Reject declarative-partial-updates patch-linkage attributes\n (https://github.com/WICG/declarative-partial-updates).\n Empirical note (Chrome 150, verified — see\n test/declarative-patch-probe-v3.html): expansion is NOT applied after\n sanitization. For the string path it fires during sanitize()'s own\n parse, so the walk sees and sanitizes the fully materialized expanded\n tree — teleports into MathML/SVG integration points included; a\n weaponized `<template for>`->`<img onerror>` comes back with the handler\n stripped. For the IN_PLACE path it fires on connection, before the walk.\n Either way DOMPurify is NOT blind to the patch.\n This removal is therefore defense-in-depth rather than the sole barrier:\n it prevents live linkage from surviving into the OUTPUT and re-expanding\n in the caller's context, and keeps behaviour deterministic if a future\n engine defers expansion. `for` is legitimate only on <label>/<output>;\n anywhere else (notably <template for>) it links the element to a patch\n target and teleports or removes an arbitrary DOM range by id/marker name.\n `patchsrc` fetches remote markup and is treated as a script-loading\n mechanism (CSP). Gated on SAFE_FOR_XML so the removal groups with the\n other structural-threat checks and stays overridable, consistent with\n the rest of the codebase. PI range markers are already removed by\n _isUnsafeNode. */\n if (_isPatchLinkageAttribute(lcName, lcTag)) {\n return false;\n }\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n return false;\n }\n const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) {\n return true;\n }\n /* Allow valid aria-* attributes, the value is always URI safe */\n if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) {\n return true;\n }\n /* A name outside the allowlist is acceptable on custom-element terms\n only. The value checks below are intentionally skipped in that case:\n if the user supplied a tagNameCheck we also allow derived custom\n elements using the same test, and attributes passing the configured\n attributeNameCheck are allowed as custom elements define these at\n their own discretion. */\n if (!nameIsPermitted) {\n return (\n // Condition a) covers a basically valid custom element tag name whose\n // tag passes the configured tagNameCheck and whose attribute name\n // passes the configured attributeNameCheck ...\n _isBasicCustomElement(lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName, lcTag) ||\n // Condition b) covers an `is` attribute whose value passes the\n // configured tagNameCheck while customized built-in elements are\n // allowed.\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value)\n );\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n if (URI_SAFE_ATTRIBUTES[lcName]) {\n return true;\n }\n /* Check no script, data or unknown possibly unsafe URI\n unless we know URI values are safe for that attribute */\n if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) {\n return true;\n }\n /* Keep image data URIs alive if src/xlink:href is allowed */\n /* Further prevent gadget XSS for dynamically built script tags */\n if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {\n return true;\n }\n /* Allow unknown protocols: This provides support for links that\n are handled by protocol handlers which may be unknown ahead of\n time, e.g. fb:, spotify: */\n if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) {\n return true;\n }\n /* Only an empty (binary) value remains safe at this point;\n anything else is presumed unsafe, do not add it back */\n return !value;\n };\n /* Names the HTML spec reserves from valid-custom-element-name; these must\n * never be treated as basic custom elements even when a permissive\n * CUSTOM_ELEMENT_HANDLING.tagNameCheck is configured. */\n const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, ['annotation-xml', 'color-profile', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'missing-glyph']);\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param tagName name of the tag of the node to sanitize\n * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);\n };\n /**\n * Wrap an attribute value in the matching Trusted Types object when\n * the active policy requires it. Namespaced attributes pass through\n * unchanged (no TT support yet, see\n * https://bugs.chromium.org/p/chromium/issues/detail?id=1305293).\n *\n * @param lcTag lowercase tag name of the containing element\n * @param lcName lowercase attribute name\n * @param namespaceURI the attribute's namespace, if any\n * @param value the attribute value to wrap\n * @return the value, wrapped when Trusted Types demand it\n */\n const _applyTrustedTypesToAttribute = function _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value) {\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function' && !namespaceURI) {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n return _createTrustedHTML(value);\n }\n case 'TrustedScriptURL':\n {\n return _createTrustedScriptURL(value);\n }\n }\n }\n return value;\n };\n /**\n * Write a modified attribute value back onto the element. On\n * success, re-probe for clobbering introduced by the new value and\n * remove the element when found; otherwise, when this writeback is the\n * recreate half of the SANITIZE_NAMED_PROPS remove-and-recreate, pop the\n * removal entry that path recorded so it does not show as removed. On\n * failure, remove the attribute instead.\n *\n * Returns true only on a clean write (the value was set and the new value\n * introduced no clobbering). The caller uses that, together with its own\n * knowledge of whether this attribute pushed a DOMPurify.removed record, to\n * decide whether to pop that record. The pop must happen ONLY for the\n * named-prop remove-and-recreate; popping on any other value change (trim,\n * template scrubbing, Trusted Types) would consume an unrelated _forceRemove\n * subtree-cleanup record and let that detached subtree keep a live event\n * handler through the IN_PLACE neutralization pass (SO-001).\n *\n * @param currentNode the element carrying the attribute\n * @param name the attribute name as present on the element\n * @param namespaceURI the attribute's namespace, if any\n * @param value the new attribute value\n * @return true if the value was written without introducing clobbering\n */\n const _setAttributeValue = function _setAttributeValue(currentNode, name, namespaceURI, value) {\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return false;\n }\n return true;\n } catch (_) {\n _removeAttribute(name, currentNode);\n return false;\n }\n };\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param currentNode to sanitize\n */\n // eslint-disable-next-line complexity\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);\n const attributes = currentNode.attributes;\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes || _isClobbered(currentNode)) {\n return;\n }\n /* Same lazy-install guard as uponSanitizeElement (see there): fork the\n attribute allowlist off its shared binding before a hook can see it. */\n ALLOWED_ATTR = _forkSharedAllowlist(hooks.uponSanitizeAttribute, ALLOWED_ATTR, DEFAULT_ALLOWED_ATTR, SET_CONFIG_ALLOWED_ATTR);\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR,\n forceKeepAttr: undefined\n };\n let l = attributes.length;\n const lcTag = transformCaseFunc(currentNode.nodeName);\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const name = attr.name,\n namespaceURI = attr.namespaceURI,\n attrValue = attr.value;\n const lcName = transformCaseFunc(name);\n const initValue = attrValue;\n let value = name === 'value' ? initValue : stringTrim(initValue);\n /* Tracks whether this specific attribute pushed a DOMPurify.removed\n record that a later _setAttributeValue() writeback is expected to pop\n back off (the SANITIZE_NAMED_PROPS remove-and-recreate below is the\n only path that does). A value that merely changed via trim, template\n scrubbing, or Trusted Types pushes no such record, so its writeback\n must NOT pop — otherwise it consumes an unrelated _forceRemove subtree\n record and that detached subtree escapes the IN_PLACE handler-\n neutralization pass (SO-001). */\n let recreatedNamedProp = false;\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name') && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode, attr);\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n // This attribute owns the record just pushed; its recreate writeback\n // is the one allowed to pop it back off.\n recreatedNamedProp = true;\n }\n // Else: already prefixed, leave the attribute alone — the prefix is\n // itself the clobbering protection, and re-applying it is incorrect.\n /* Work around a security issue with comments inside attributes */\n if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {\n _removeAttribute(name, currentNode, attr);\n continue;\n }\n /* Make sure we cannot easily use animated hrefs, even if animations are allowed */\n if (lcName === 'attributename' && stringMatch(value, 'href')) {\n _removeAttribute(name, currentNode, attr);\n continue;\n }\n /* Did the hooks force-keep the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n _removeAttribute(name, currentNode, attr);\n continue;\n }\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {\n _removeAttribute(name, currentNode, attr);\n continue;\n }\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n value = _stripTemplateExpressions(value);\n }\n /* Is `value` valid for this attribute? */\n if (!_isValidAttribute(lcTag, lcName, value)) {\n _removeAttribute(name, currentNode, attr);\n continue;\n }\n /* Handle attributes that require Trusted Types */\n value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);\n /* Handle invalid data-* attribute set by try-catching it */\n if (value !== initValue) {\n const cleanWrite = _setAttributeValue(currentNode, name, namespaceURI, value);\n /* Only the named-prop remove-and-recreate owns a DOMPurify.removed\n record to pop; a plain trim/template/Trusted-Types writeback owns\n none, so popping here would drop an unrelated subtree's cleanup\n record (SO-001). */\n if (cleanWrite && recreatedNamedProp) {\n arrayPop(DOMPurify.removed);\n }\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);\n };\n /**\n * _sanitizeShadowDOM\n *\n * @param fragment to iterate over recursively\n */\n const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);\n /* Sanitize tags and elements */\n _sanitizeElements(shadowNode, fragment);\n /* Check attributes next */\n _sanitizeAttributes(shadowNode);\n /* Deep shadow DOM detected.\n Realm-safe check (GHSA-hpcv-96wg-7vj8): use nodeType against the\n DOCUMENT_FRAGMENT_NODE constant rather than instanceof, so we\n recurse into <template>.content from foreign realms too. */\n if (_isDocumentFragment(shadowNode.content)) {\n _sanitizeShadowDOM2(shadowNode.content);\n }\n /* An element iterated here may itself host an attached\n shadow root. The default NodeIterator does not enter shadow\n trees, so a shadow root nested inside template.content was\n previously reached by no walk at all (the pre-pass at\n _sanitizeAttachedShadowRoots descends via childNodes, which\n doesn't enter template.content; the template-content recursion\n above iterates the content but never inspected shadowRoot).\n Walk it explicitly. The nodeType guard avoids reading\n shadowRoot off text / comment / CDATA / PI nodes that the\n iterator also surfaces. */\n if (_readNodeType(shadowNode) === NODE_TYPE.element) {\n const innerSr = getShadowRoot(shadowNode);\n if (_isDocumentFragment(innerSr)) {\n _sanitizeAttachedShadowRoots(innerSr);\n _sanitizeShadowDOM2(innerSr);\n }\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);\n };\n /**\n * _sanitizeAttachedShadowRoots\n *\n * Walks `root` and feeds every attached shadow root we encounter into\n * the existing _sanitizeShadowDOM pipeline. The default node iterator\n * does not descend into shadow trees, so nodes inside an attached\n * shadow root would otherwise be skipped entirely.\n *\n * Two real input paths put attached shadow roots in front of us:\n * 1. IN_PLACE on a DOM node that already has shadow roots attached.\n * 2. DOM-node input where importNode(dirty, true) deep-clones the\n * shadow root because it was created with `clonable: true`.\n *\n * This pass runs once, up front, so the main iteration loop (and the\n * existing _sanitizeShadowDOM template-content recursion) stay\n * untouched — string-input paths are not affected.\n *\n * @param root the subtree root to walk for attached shadow roots\n */\n const _sanitizeAttachedShadowRoots = function _sanitizeAttachedShadowRoots(root) {\n /* Iterative (explicit stack) rather than per-child recursion. DOM APIs\n impose no depth cap, so an attacker-shaped tree (JSON/CRDT/editor data\n built straight into the DOM — the IN_PLACE surface) deeper than the JS\n call-stack budget would otherwise overflow native recursion here and\n throw at the IN_PLACE entry pre-pass, before a single node is\n sanitized, leaving the caller's live tree untouched (fail-open). See\n campaign-3 F4. A heap stack keeps depth off the call stack.\n Each work item is either a node to descend into, or a deferred\n `_sanitizeShadowDOM` for an already-walked shadow root. The deferred\n form preserves the original post-order discipline: a shadow root's\n nested shadow roots are discovered before the outer shadow is\n sanitized (which may remove hosts). Pushes are in reverse of the\n desired processing order (LIFO): template content, then children, then\n the shadow-sanitize, then the shadow walk — so the order matches the\n previous recursion exactly. */\n const stack = [{\n node: root,\n shadow: null\n }];\n while (stack.length > 0) {\n const item = stack.pop();\n /* Deferred shadow-DOM sanitisation: runs after its subtree was walked. */\n if (item.shadow) {\n _sanitizeShadowDOM2(item.shadow);\n continue;\n }\n const node = item.node;\n const nodeType = _readNodeType(node);\n const isElement = nodeType === NODE_TYPE.element;\n /* (pushed last → processed first) Children, snapshotted in reverse so\n the first child is processed first. Snapshotting matters because a\n hook may detach siblings mid-walk. */\n const childNodes = getChildNodes(node);\n if (childNodes) {\n for (let i = childNodes.length - 1; i >= 0; --i) {\n stack.push({\n node: childNodes[i],\n shadow: null\n });\n }\n }\n /* (pushed before children → processed after them, matching the old\n \"template content last\" order) When the node is a <template>,\n descend into its content. */\n if (isElement) {\n const rootName = getNodeName ? getNodeName(node) : null;\n if (typeof rootName === 'string' && transformCaseFunc(rootName) === 'template') {\n const content = node.content;\n if (_isDocumentFragment(content)) {\n stack.push({\n node: content,\n shadow: null\n });\n }\n }\n }\n /* Shadow root (processed first): walk its subtree, then sanitise it.\n Realm-safe check (GHSA-hpcv-96wg-7vj8): nodeType-based detection\n rather than `instanceof DocumentFragment`, which is realm-bound and\n silently skipped foreign-realm shadow roots (e.g.\n iframe.contentDocument attachShadow). */\n if (isElement) {\n const sr = getShadowRoot(node);\n if (_isDocumentFragment(sr)) {\n /* Push the deferred sanitise first so it pops after the shadow\n walk we push next, i.e. nested shadow roots are discovered\n before this one is sanitised. */\n stack.push({\n node: null,\n shadow: sr\n }, {\n node: sr,\n shadow: null\n });\n }\n }\n }\n };\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '<!-->';\n }\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n dirty = stringifyValue(dirty);\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n }\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n /* Assign config vars */\n if (SET_CONFIG) {\n /* Persistent setConfig() path: _parseConfig is skipped, so the sets are\n * not re-derived per call. Restore them from the pristine bindings\n * captured at setConfig() time so a previous call's hook clone (mutated\n * below) does not carry over. */\n ALLOWED_TAGS = SET_CONFIG_ALLOWED_TAGS;\n ALLOWED_ATTR = SET_CONFIG_ALLOWED_ATTR;\n } else {\n _parseConfig(cfg);\n }\n /* Clone the hook-mutable allowlists before the walk whenever an\n * uponSanitize* hook is registered. The hook event exposes ALLOWED_TAGS\n * and ALLOWED_ATTR by reference (as allowedTags / allowedAttributes), so\n * a hook that widens them would otherwise mutate the shared set\n * permanently: across later calls and across every element. Cloning per\n * walk keeps documented in-call widening working while scoping it to the\n * call. A single guard for both config paths - the per-call path rebinds\n * the sets in _parseConfig each call, the persistent path restores them\n * from the captured bindings just above - so the two cannot diverge. */\n if (hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n if (hooks.uponSanitizeAttribute.length > 0) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n /* Clean up removed elements */\n DOMPurify.removed = [];\n /* Resolve IN_PLACE for this call without mutating persistent config.\n Writing the IN_PLACE closure variable here leaks under setConfig(),\n where _parseConfig is skipped on later calls: a single string call would\n disable in-place mode for every subsequent node call, returning a\n sanitized copy while leaving the caller's node — which in-place callers\n keep using and whose return value they ignore — unsanitized. REPORT-2. */\n const inPlace = IN_PLACE && typeof dirty !== 'string' && _isNode(dirty);\n if (inPlace) {\n /* Declarative-partial-updates / streaming pre-pass: sever every patch\n linkage across the live tree BEFORE the walk, so no patch can fire\n mid-walk and inject into an already-processed region. Runs first, so\n it also covers the forbidden/clobbered roots that throw below. */\n _neutralizePatchLinkage(dirty);\n /* Do some early pre-sanitization to avoid unsafe root nodes.\n Read nodeName through the cached prototype getter — a clobbering\n child named \"nodeName\" on the form root would otherwise shadow\n the property and let this check skip the root-allowlist\n validation entirely. */\n const nn = _readNodeName(dirty);\n if (typeof nn === 'string') {\n const tagName = transformCaseFunc(nn);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n /* Fail closed on a live root: neutralize handlers/children before\n throwing, exactly as the mid-walk abort path does. */\n _neutralizeRoot(dirty);\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n /* Pre-flight the root through _isClobbered. The iterator-driven\n removal path can not detach a parent-less root: _forceRemove\n falls through to Element.prototype.remove(), which per spec\n is a no-op on a node with no parent. A clobbered root would\n then survive the main loop with its attributes uninspected,\n because _sanitizeAttributes early-returns on _isClobbered. The\n result would be an attacker-controlled form, complete with any\n event-handler attributes the caller passed in, handed back to\n the application unsanitized. Refuse to sanitize such a root\n the same way we refuse a forbidden tag. GHSA-r47g-fvhr-h676. */\n if (_isClobbered(dirty)) {\n /* Fail closed on a live clobbered root before throwing.\n _neutralizeRoot's reads are clobber-safe (cached getters); the\n form's non-clobbered descendants, e.g. an armed <img>, are scrubbed. */\n _neutralizeRoot(dirty);\n throw typeErrorCreate('root node is clobbered and cannot be sanitized in-place');\n }\n /* Sanitize attached shadow roots before the main iterator runs.\n The iterator does not descend into shadow trees. Same fail-closed\n barrier as the main walk (campaign-3 F2): a custom-element reaction\n inside a shadow root could abort this pre-pass before the walk runs,\n which would otherwise leave the entire live tree unsanitized. */\n try {\n _sanitizeAttachedShadowRoots(dirty);\n } catch (error) {\n _neutralizeRoot(dirty);\n throw error;\n }\n } else if (_isNode(dirty)) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('<!---->');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n /* Clonable shadow roots are deep-cloned by importNode(); sanitize\n them before the main iterator runs, since the iterator does not\n descend into shadow trees. The walk routes every read through a\n cached prototype getter so clobbering descendants on a form root\n cannot hide a shadow host from this pass.\n Traverse from `body`, not `importedNode`: when importedNode is a\n DocumentFragment, the appendChild() above moves its children into\n `body` and leaves the fragment empty, so walking importedNode would\n scan nothing and miss every attached shadow host now under `body`\n (SO-003). In the BODY/HTML branches `body === importedNode`, so this\n is equivalent there; in the element branch `body` contains the\n appended element and its descendants. `body` covers all three. */\n _sanitizeAttachedShadowRoots(body);\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;\n }\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n /* Get node iterator */\n const walkRoot = inPlace ? dirty : body;\n /* Now start iterating over the created document.\n The walk runs inside an exception barrier (campaign-3 F2): a re-entrant\n engine/custom-element mutation can detach a node mid-walk so\n `_forceRemove`'s parentless guard throws, aborting the loop. Without the\n barrier the caller's in-place tree would be left half-sanitized with the\n unvisited tail still armed. _createNodeIterator itself is inside the\n barrier too: constructing the iterator dereferences the root's document,\n and any failure there (e.g. an exotic/clobbered root) must still fail\n closed rather than skip the neutralize. On any throw we fail closed -\n strip the in-place root bare - then rethrow so the existing throw\n contract is preserved. (String/DOM-copy paths never return the partial\n body, so the propagating throw is already fail-closed there.) */\n try {\n const nodeIterator = _createNodeIterator(walkRoot);\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n _sanitizeElements(currentNode, walkRoot);\n /* Check attributes next */\n _sanitizeAttributes(currentNode);\n /* Shadow DOM detected, sanitize it.\n Realm-safe check (GHSA-hpcv-96wg-7vj8): nodeType-based detection\n instead of instanceof, so foreign-realm <template>.content is\n walked correctly. */\n if (_isDocumentFragment(currentNode.content)) {\n _sanitizeShadowDOM2(currentNode.content);\n }\n }\n } catch (error) {\n if (inPlace) {\n _neutralizeRoot(dirty);\n /* Nodes _forceRemove'd earlier in the aborted walk are already\n detached from the root, so _neutralizeRoot's subtree pass does not\n reach them. Defuse them too, mirroring the success-path loop below. */\n arrayForEach(DOMPurify.removed, entry => {\n if (entry.element) {\n _neutralizeSubtree(entry.element);\n }\n });\n }\n throw error;\n }\n /* If we sanitized `dirty` in-place, return it. */\n if (inPlace) {\n /* Fail-closed completion of the audit-5 F1 fix: every node removed from\n the caller's live tree is detached but may still hold a queued\n resource-event handler that fires in page scope after we return. The\n move-hoist covers only disallowed-tag KEEP_CONTENT removals; strip the\n non-allow-listed attributes off every other removed subtree (clobber,\n mXSS, namespace, comments, KEEP_CONTENT:false, …) so those handlers are\n cancelled before any event can fire. Runs synchronously, pre-return. */\n arrayForEach(DOMPurify.removed, entry => {\n if (entry.element) {\n _neutralizeSubtree(entry.element);\n }\n });\n if (SAFE_FOR_TEMPLATES) {\n _scrubTemplateExpressions2(dirty);\n }\n return dirty;\n }\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (SAFE_FOR_TEMPLATES) {\n _scrubTemplateExpressions2(body);\n }\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\\n' + serializedHTML;\n }\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n serializedHTML = _stripTemplateExpressions(serializedHTML);\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;\n };\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n SET_CONFIG_ALLOWED_TAGS = ALLOWED_TAGS;\n SET_CONFIG_ALLOWED_ATTR = ALLOWED_ATTR;\n };\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n SET_CONFIG_ALLOWED_TAGS = null;\n SET_CONFIG_ALLOWED_ATTR = null;\n // Drop any caller-supplied Trusted Types policy so it cannot poison later\n // `RETURN_TRUSTED_TYPE` output. The internal default policy (cached, and\n // never recreated — Trusted Types throws on duplicate names) is restored by\n // the next `_parseConfig`. See GHSA-vxr8-fq34-vvx9.\n trustedTypesPolicy = defaultTrustedTypesPolicy;\n emptyHTML = '';\n };\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n /* Reject unknown entry points. Without this, a non-hook key (e.g.\n * '__proto__') indexes off the prototype chain rather than a real\n * hook array, and arrayPush then writes to Object.prototype. Guard\n * with an own-property check against the known hook names. */\n if (!objectHasOwnProperty(hooks, entryPoint)) {\n return;\n }\n arrayPush(hooks[entryPoint], hookFunction);\n };\n DOMPurify.removeHook = function (entryPoint, hookFunction) {\n if (!objectHasOwnProperty(hooks, entryPoint)) {\n return undefined;\n }\n if (hookFunction !== undefined) {\n const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);\n return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];\n }\n return arrayPop(hooks[entryPoint]);\n };\n DOMPurify.removeHooks = function (entryPoint) {\n if (!objectHasOwnProperty(hooks, entryPoint)) {\n return;\n }\n hooks[entryPoint] = [];\n };\n DOMPurify.removeAllHooks = function () {\n hooks = _createHooksMap();\n };\n return DOMPurify;\n}\nvar purify = createDOMPurify();\n\nexport { purify as default };\n//# sourceMappingURL=purify.es.mjs.map\n","/**\n * marked v18.0.10 - a markdown parser\n * Copyright (c) 2018-2026, MarkedJS. (MIT License)\n * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT License)\n * https://github.com/markedjs/marked\n */\n\n/**\n * DO NOT EDIT THIS FILE\n * The code in this file is generated from files in ./src/\n */\n\nfunction C(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var R=C();function j(l){R=l}var z={exec:()=>null};function A(l){let e=[];return t=>{let n=Math.max(0,Math.min(3,t-1)),s=e[n];return s||(s=l(n),e[n]=s),s}}function d(l,e=\"\"){let t=typeof l==\"string\"?l:l.source,n={replace:(s,r)=>{let i=typeof r==\"string\"?r:r.source;return i=i.replace(m.caret,\"$1\"),t=t.replace(s,i),n},getRegex:()=>new RegExp(t,e)};return n}var Te=((l=\"\")=>{try{return!!new RegExp(\"(?<=1)(?<!1)\"+l)}catch{return!1}})(),m={codeRemoveIndent:/^(?: {1,4}| {0,3}\\t)/gm,outputLinkReplace:/\\\\([\\[\\]])/g,indentCodeCompensation:/^(\\s+)(?:```)/,beginningSpace:/^\\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\\n/g,tabCharGlobal:/\\t/g,multipleSpaceGlobal:/\\s+/g,blankLine:/^[ \\t]*$/,doubleBlankLine:/\\n[ \\t]*\\n[ \\t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \\t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\\[[ xX]\\] +\\S/,listReplaceTask:/^\\[[ xX]\\] +/,listTaskCheckbox:/\\[[ xX]\\]/,anyLine:/\\n.*\\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\\||\\| *$/g,tableRowBlankLine:/\\n[ \\t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\\s|>)/i,endPreScriptTag:/^<\\/(pre|code|kbd|script)(\\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/,unicodeAlphaNumeric:/[\\p{L}\\p{N}]/u,escapeTest:/[&<>\"']/,escapeReplace:/[&<>\"']/g,escapeTestNoEncode:/[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,escapeReplaceNoEncode:/[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,caret:/(^|[^\\[])\\^/g,percentDecode:/%25/g,findPipe:/\\|/g,splitPipe:/ \\|/,slashPipe:/\\\\\\|/g,carriageReturn:/\\r\\n|\\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\\S*/,endingNewline:/\\n$/,listItemRegex:l=>new RegExp(`^( {0,3}${l})((?:[\t ][^\\\\n]*)?(?:\\\\n|$))`),nextBulletRegex:A(l=>new RegExp(`^ {0,${l}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ \t][^\\\\n]*)?(?:\\\\n|$))`)),hrRegex:A(l=>new RegExp(`^ {0,${l}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`)),fencesBeginRegex:A(l=>new RegExp(`^ {0,${l}}(?:\\`\\`\\`|~~~)`)),headingBeginRegex:A(l=>new RegExp(`^ {0,${l}}#`)),htmlBeginRegex:A(l=>new RegExp(`^ {0,${l}}<(?:[a-z].*>|!--)`,\"i\")),blockquoteBeginRegex:A(l=>new RegExp(`^ {0,${l}}>`))},Oe=/^(?:[ \\t]*(?:\\n|$))+/,we=/^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/,ye=/^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/,q=/^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/,Pe=/^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/,U=/ {0,3}(?:[*+-]|\\d{1,9}[.)])/,oe=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,ae=d(oe).replace(/bull/g,U).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\\s|$)/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/\\|table/g,\"\").getRegex(),Se=d(oe).replace(/bull/g,U).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}(?:\\s|$)/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/table/g,/ {0,3}\\|?(?:[:\\- ]*\\|)+[\\:\\- ]*\\n/).getRegex(),K=/^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table|[ \\t]+\\n)[^\\n]+)*)/,_e=/^[^\\n]+/,W=/(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/,$e=d(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/).replace(\"label\",W).replace(\"title\",/(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/).getRegex(),Le=d(/^(bull)([ \\t][^\\n]*?)?(?:\\n|$)/).replace(/bull/g,U).getRegex(),Q=\"address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul\",X=/<!--(?:-?>|[\\s\\S]*?(?:-->|$))/,Me=d(\"^ {0,3}(?:<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:</\\\\1>[^\\\\n]*\\\\n*|$)|comment[^\\\\n]*(\\\\n+|$)|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>[^\\\\n]*\\\\n*|$)|<![A-Z][\\\\s\\\\S]*?(?:>[^\\\\n]*\\\\n*|$)|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?(?:\\\\]\\\\]>[^\\\\n]*\\\\n*|$)|</?(tag)(?: +|\\\\n|/?>)[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$)|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$)|</(?!script|pre|style|textarea)[a-z][\\\\w-]*\\\\s*>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$))\",\"i\").replace(\"comment\",X).replace(\"tag\",Q).replace(\"attribute\",/ +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/).getRegex(),le=l=>d(K).replace(\"hr\",q).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"|lheading\",\"\").replace(\"|table\",\"\").replace(\"blockquote\",\" {0,3}>\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*(?:\\\\n|$))|~~~)[^\\\\n]*(?:\\\\n|$)\").replace(\"list\",l).replace(\"html\",\"</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",Q).getRegex(),ze=le(/ {0,3}(?:[*+-]|1[.)])[ \\t]+[^ \\t\\n]/),Ee=le(/ {0,3}(?:[*+-]|\\d{1,9}[.)])(?:[ \\t]|\\n|$)/),Ce=d(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/).replace(\"paragraph\",Ee).getRegex(),J={blockquote:Ce,code:we,def:$e,fences:ye,heading:Pe,hr:q,html:Me,lheading:ae,list:Le,newline:Oe,paragraph:ze,table:z,text:_e},se=d(\"^ *([^\\\\n ].*)\\\\n {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)\").replace(\"hr\",q).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"blockquote\",\" {0,3}>\").replace(\"code\",\"(?: {4}| {0,3}\t)[^\\\\n]\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*(?:\\\\n|$))|~~~)[^\\\\n]*(?:\\\\n|$)\").replace(\"list\",\" {0,3}(?:[*+-]|1[.)])[ \\\\t]\").replace(\"html\",\"</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",Q).getRegex(),Ae={...J,lheading:Se,table:se,paragraph:d(K).replace(\"hr\",q).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"|lheading\",\"\").replace(\"table\",se).replace(\"blockquote\",\" {0,3}>\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*(?:\\\\n|$))|~~~)[^\\\\n]*(?:\\\\n|$)\").replace(\"list\",\" {0,3}(?:[*+-]|1[.)])[ \\\\t]+[^ \\\\t\\\\n]\").replace(\"html\",\"</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",Q).getRegex()},Ie={...J,html:d(`^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)|<tag(?:\"[^\"]*\"|'[^']*'|\\\\s[^'\"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))`).replace(\"comment\",X).replace(/tag/g,\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b\").getRegex(),def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/,heading:/^(#{1,6})(.*)(?:\\n+|$)/,fences:z,lheading:/^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,paragraph:d(K).replace(\"hr\",q).replace(\"heading\",` *#{1,6} *[^\n]`).replace(\"lheading\",ae).replace(\"|table\",\"\").replace(\"blockquote\",\" {0,3}>\").replace(\"|fences\",\"\").replace(\"|list\",\"\").replace(\"|html\",\"\").replace(\"|tag\",\"\").getRegex()},Be=/^\\\\([!\"#$%&'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/,De=/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,pe=/^( {2,}|\\\\)\\n(?!\\s*$)/,qe=/^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/,_=/[\\p{P}\\p{S}]/u,I=/[\\s\\p{P}\\p{S}]/u,v=/[^\\s\\p{P}\\p{S}]/u,ve=d(/^((?![*_])punctSpace)/,\"u\").replace(/punctSpace/g,I).getRegex(),He=/[\\p{Pi}\\p{Ps}\"']/u,ue=/(?!~)[\\p{P}\\p{S}]/u,Ze=/(?!~)[\\s\\p{P}\\p{S}]/u,Ge=/(?:[^\\s\\p{P}\\p{S}]|~)/u,Qe=d(/link|precode-code|html/,\"g\").replace(\"link\",/\\[(?:[^\\[\\]`]|(?<a>`+)[^`]+\\k<a>(?!`))*?\\]\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)]|\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)])*\\))*\\)/).replace(\"precode-\",Te?\"(?<!`)()\":\"(^^|[^`])\").replace(\"code\",/(?<b>`+)[^`]+\\k<b>(?!`)/).replace(\"html\",/<(?! )[^<>]*?>/).getRegex(),ce=/^(?:\\*+(?:((?!\\*)punct)|([^\\s*]))?)|^_+(?:((?!_)punct)|([^\\s_]))?/,Ne=d(ce,\"u\").replace(/punct/g,_).getRegex(),je=d(ce,\"u\").replace(/punct/g,ue).getRegex(),Fe=/^(?:\\*+(?:((?!\\*)(?!openQuote)punct)|([^\\s*]))?)|^_+(?:((?!_)(?!openQuote)punct)|([^\\s_]))?/,Ue=d(Fe,\"u\").replace(/openQuote/g,He).replace(/punct/g,_).getRegex(),he=\"^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|notPunctSpace(\\\\*+)(?=notPunctSpace)\",Ke=d(he,\"gu\").replace(/notPunctSpace/g,v).replace(/punctSpace/g,I).replace(/punct/g,_).getRegex(),We=d(he,\"gu\").replace(/notPunctSpace/g,Ge).replace(/punctSpace/g,Ze).replace(/punct/g,ue).getRegex(),Xe=\"^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)[\\\\s](\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|(?:(?!\\\\*)punct|notPunctSpace)(\\\\*+)(?!\\\\*)(?=notPunctSpace)\",Je=d(Xe,\"gu\").replace(/notPunctSpace/g,v).replace(/punctSpace/g,I).replace(/punct/g,_).getRegex(),Ve=d(\"^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)\",\"gu\").replace(/notPunctSpace/g,v).replace(/punctSpace/g,I).replace(/punct/g,_).getRegex(),Ye=\"^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)[\\\\s](_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)|(?:(?!_)punct|notPunctSpace)(_+)(?!_)(?=notPunctSpace)\",et=d(Ye,\"gu\").replace(/notPunctSpace/g,v).replace(/punctSpace/g,I).replace(/punct/g,_).getRegex(),tt=d(/^~~?(?:((?!~)punct)|[^\\s~])/,\"u\").replace(/punct/g,_).getRegex(),nt=\"^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)\",rt=d(nt,\"gu\").replace(/notPunctSpace/g,v).replace(/punctSpace/g,I).replace(/punct/g,_).getRegex(),st=d(/\\\\(punct)/,\"gu\").replace(/punct/g,_).getRegex(),it=d(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/).replace(\"scheme\",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace(\"email\",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),ot=d(X).replace(\"(?:-->|$)\",\"-->\").getRegex(),at=d(\"^comment|^</[a-zA-Z][\\\\w:-]*\\\\s*>|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>|^<\\\\?[\\\\s\\\\S]*?\\\\?>|^<![a-zA-Z]+\\\\s[\\\\s\\\\S]*?>|^<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>\").replace(\"comment\",ot).replace(\"attribute\",/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/).getRegex(),G=/(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\\])|[^\\[\\]\\\\`])*?/,lt=d(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]+(?:\\n[ \\t]*)?|\\n[ \\t]*)(title))?\\s*\\)/).replace(\"label\",G).replace(\"href\",/<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]+|(?=\\))/).replace(\"title\",/\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/).getRegex(),de=d(/^!?\\[(label)\\]\\[(ref)\\]/).replace(\"label\",G).replace(\"ref\",W).getRegex(),ke=d(/^!?\\[(ref)\\](?:\\[\\])?/).replace(\"ref\",W).getRegex(),pt=d(\"reflink|nolink(?!\\\\()\",\"g\").replace(\"reflink\",de).replace(\"nolink\",ke).getRegex(),ie=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,V={_backpedal:z,anyPunctuation:st,autolink:it,blockSkip:Qe,br:pe,code:De,del:z,delLDelim:z,delRDelim:z,emStrongLDelim:Ne,emStrongRDelimAst:Ke,emStrongRDelimUnd:Ve,escape:Be,link:lt,nolink:ke,punctuation:ve,reflink:de,reflinkSearch:pt,tag:at,text:qe,url:z},ut={...V,emStrongLDelim:Ue,emStrongRDelimAst:Je,emStrongRDelimUnd:et,link:d(/^!?\\[(label)\\]\\((.*?)\\)/).replace(\"label\",G).getRegex(),reflink:d(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace(\"label\",G).getRegex()},F={...V,emStrongRDelimAst:We,emStrongLDelim:je,delLDelim:tt,delRDelim:rt,url:d(/^((?:protocol):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/).replace(\"protocol\",ie).replace(\"email\",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'\"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'\"~)]+(?!$))+/,del:/^(~~?)(?=[^\\s~])((?:\\\\[\\s\\S]|[^\\\\])*?(?:\\\\[\\s\\S]|[^\\s~\\\\]))\\1(?=[^~]|$)/,text:d(/^(`+|~+|[^`~])(?:(?=[`~])|(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|protocol:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)))/).replace(\"protocol\",ie).getRegex()},ct={...F,br:d(pe).replace(\"{2,}\",\"*\").getRegex(),text:d(F.text).replace(\"\\\\b_\",\"\\\\b_| {2,}\\\\n\").replace(/\\{2,\\}/g,\"*\").getRegex()},H={normal:J,gfm:Ae,pedantic:Ie},B={normal:V,gfm:F,breaks:ct,pedantic:ut};var ht={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"},ge=l=>ht[l];function O(l,e){if(e){if(m.escapeTest.test(l))return l.replace(m.escapeReplace,ge)}else if(m.escapeTestNoEncode.test(l))return l.replace(m.escapeReplaceNoEncode,ge);return l}function Y(l){try{l=encodeURI(l).replace(m.percentDecode,\"%\")}catch{return null}return l}function ee(l,e){let t=l.replace(m.findPipe,(r,i,o)=>{let p=!1,a=i;for(;--a>=0&&o[a]===\"\\\\\";)p=!p;return p?\"|\":\" |\"}),n=t.split(m.splitPipe),s=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length<e;)n.push(\"\");for(;s<n.length;s++)n[s]=n[s].trim().replace(m.slashPipe,\"|\");return n}function $(l,e,t){let n=l.length;if(n===0)return\"\";let s=0;for(;s<n;){let r=l.charAt(n-s-1);if(r===e&&!t)s++;else if(r!==e&&t)s++;else break}return l.slice(0,n-s)}function te(l){let e=l.split(`\n`),t=e.length-1;for(;t>=0&&m.blankLine.test(e[t]);)t--;return e.length-t<=2?l:e.slice(0,t+1).join(`\n`)}function fe(l,e){if(l.indexOf(e[1])===-1)return-1;let t=0;for(let n=0;n<l.length;n++)if(l[n]===\"\\\\\")n++;else if(l[n]===e[0])t++;else if(l[n]===e[1]&&(t--,t<0))return n;return t>0?-2:-1}function me(l,e=0){let t=e,n=\"\";for(let s of l)if(s===\"\t\"){let r=4-t%4;n+=\" \".repeat(r),t+=r}else n+=s,t++;return n}function xe(l,e,t,n,s){let r=e.href,i=e.title||null,o=l[1].replace(s.other.outputLinkReplace,\"$1\");n.state.inLink=!0;let p={type:l[0].charAt(0)===\"!\"?\"image\":\"link\",raw:t,href:r,title:i,text:o,tokens:n.inlineTokens(o)};return n.state.inLink=!1,p}function dt(l,e,t){let n=l.match(t.other.indentCodeCompensation);if(n===null)return e;let s=n[1];return e.split(`\n`).map(r=>{let i=r.match(t.other.beginningSpace);if(i===null)return r;let[o]=i;return o.length>=s.length?r.slice(s.length):r}).join(`\n`)}var y=class{options;rules;lexer;constructor(e){this.options=e||R}space(e){let t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:\"space\",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=this.options.pedantic?t[0]:te(t[0]),s=n.replace(this.rules.other.codeRemoveIndent,\"\");return{type:\"code\",raw:n,codeBlockStyle:\"indented\",text:s}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],s=dt(n,t[3]||\"\",this.rules);return{type:\"code\",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,\"$1\"):t[2],text:s}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let s=$(n,\"#\");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim())}return{type:\"heading\",raw:$(t[0],`\n`),depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){let t=this.rules.block.hr.exec(e);if(t)return{type:\"hr\",raw:$(t[0],`\n`)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=$(t[0],`\n`).split(`\n`),s=\"\",r=\"\",i=[];for(;n.length>0;){let o=!1,p=[],a;for(a=0;a<n.length;a++)if(this.rules.other.blockquoteStart.test(n[a]))p.push(n[a]),o=!0;else if(!o)p.push(n[a]);else break;n=n.slice(a);let u=p.join(`\n`),c=u.replace(this.rules.other.blockquoteSetextReplace,`\n $1`).replace(this.rules.other.blockquoteSetextReplace2,\"\");s=s?`${s}\n${u}`:u,r=r?`${r}\n${c}`:c;let h=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(c,i,!0),this.lexer.state.top=h,n.length===0)break;let k=i.at(-1);if(k?.type===\"code\")break;if(k?.type===\"blockquote\"){let T=k,g=n.join(`\n`),w=T.raw+`\n`+g.replace(this.rules.other.blockquoteSetextReplace2,\"\"),M=this.blockquote(w);i[i.length-1]=M,s=`${s}\n${g}`,r=r.substring(0,r.length-T.text.length)+M.text;break}else if(k?.type===\"list\"){let T=k,g=T.raw+`\n`+n.join(`\n`),w=this.list(g);i[i.length-1]=w,s=s.substring(0,s.length-k.raw.length)+w.raw,r=r.substring(0,r.length-T.raw.length)+w.raw,n=g.substring(i.at(-1).raw.length).split(`\n`);continue}}return{type:\"blockquote\",raw:s,tokens:i,text:r}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim(),s=n.length>1,r={type:\"list\",raw:\"\",ordered:s,start:s?+n.slice(0,-1):\"\",loose:!1,items:[]};n=s?`\\\\d{1,9}\\\\${n.slice(-1)}`:`\\\\${n}`,this.options.pedantic&&(n=s?n:\"[*+-]\");let i=this.rules.other.listItemRegex(n),o=!1;for(;e;){let a=!1,u=\"\",c=\"\";if(!(t=i.exec(e))||this.rules.block.hr.test(e))break;u=t[0],e=e.substring(u.length);let h=me(t[2].split(`\n`,1)[0],t[1].length),k=e.split(`\n`,1)[0],T=!h.trim(),g=0;if(this.options.pedantic?(g=2,c=h.trimStart()):T?g=t[1].length+1:(g=h.search(this.rules.other.nonSpaceChar),g=g>4?1:g,c=h.slice(g),g+=t[1].length),T&&this.rules.other.blankLine.test(k)&&(u+=k+`\n`,e=e.substring(k.length+1),a=!0),!a){let w=this.rules.other.nextBulletRegex(g),M=this.rules.other.hrRegex(g),ne=this.rules.other.fencesBeginRegex(g),re=this.rules.other.headingBeginRegex(g),be=this.rules.other.htmlBeginRegex(g),Re=this.rules.other.blockquoteBeginRegex(g);for(;e;){let N=e.split(`\n`,1)[0],D;if(k=N,this.options.pedantic?(k=k.replace(this.rules.other.listReplaceNesting,\" \"),D=k):D=k.replace(this.rules.other.tabCharGlobal,\" \"),ne.test(k)||re.test(k)||be.test(k)||Re.test(k)||w.test(k)||M.test(k))break;if(D.search(this.rules.other.nonSpaceChar)>=g||!k.trim())c+=`\n`+D.slice(g);else{if(T||h.replace(this.rules.other.tabCharGlobal,\" \").search(this.rules.other.nonSpaceChar)>=4||ne.test(h)||re.test(h)||M.test(h))break;c+=`\n`+k}T=!k.trim(),u+=N+`\n`,e=e.substring(N.length+1),h=D.slice(g)}}r.loose||(o?r.loose=!0:this.rules.other.doubleBlankLine.test(u)&&(o=!0)),r.items.push({type:\"list_item\",raw:u,task:!!this.options.gfm&&this.rules.other.listIsTask.test(c),loose:!1,text:c,tokens:[]}),r.raw+=u}let p=r.items.at(-1);if(p)p.raw=p.raw.trimEnd(),p.text=p.text.trimEnd();else return;r.raw=r.raw.trimEnd();for(let a of r.items)if(this.lexer.state.top=!1,a.tokens=this.lexer.blockTokens(a.text,[]),!r.loose){let u=a.tokens.filter(h=>h.type===\"space\"),c=u.length>0&&u.some(h=>this.rules.other.anyLine.test(h.raw));r.loose=c}for(let a of r.items){let u=a.tokens[0];if(a.task&&(u?.type===\"text\"||u?.type===\"paragraph\")){a.text=a.text.replace(this.rules.other.listReplaceTask,\"\"),u.raw=u.raw.replace(this.rules.other.listReplaceTask,\"\"),u.text=u.text.replace(this.rules.other.listReplaceTask,\"\");for(let h=this.lexer.inlineQueue.length-1;h>=0;h--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[h].src)){this.lexer.inlineQueue[h].src=this.lexer.inlineQueue[h].src.replace(this.rules.other.listReplaceTask,\"\");break}let c=this.rules.other.listTaskCheckbox.exec(a.raw);if(c){let h={type:\"checkbox\",raw:c[0]+\" \",checked:c[0]!==\"[ ]\"};a.checked=h.checked,r.loose?a.tokens[0]&&[\"paragraph\",\"text\"].includes(a.tokens[0].type)&&\"tokens\"in a.tokens[0]&&a.tokens[0].tokens?(a.tokens[0].raw=h.raw+a.tokens[0].raw,a.tokens[0].text=h.raw+a.tokens[0].text,a.tokens[0].tokens.unshift(h)):a.tokens.unshift({type:\"paragraph\",raw:h.raw,text:h.raw,tokens:[h]}):a.tokens.unshift(h)}}else a.task&&(a.task=!1)}if(r.loose)for(let a of r.items){a.loose=!0;for(let u of a.tokens)u.type===\"text\"&&(u.type=\"paragraph\")}return r}}html(e){let t=this.rules.block.html.exec(e);if(t){let n=te(t[0]);return{type:\"html\",block:!0,raw:n,pre:t[1]===\"pre\"||t[1]===\"script\"||t[1]===\"style\",text:n}}}def(e){let t=this.rules.block.def.exec(e);if(t){let n=t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal,\" \"),s=t[2]?t[2].replace(this.rules.other.hrefBrackets,\"$1\").replace(this.rules.inline.anyPunctuation,\"$1\"):\"\",r=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,\"$1\"):t[3];return{type:\"def\",tag:n,raw:$(t[0],`\n`),href:s,title:r}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=ee(t[1]),s=t[2].replace(this.rules.other.tableAlignChars,\"\").split(\"|\"),r=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,\"\").split(`\n`):[],i={type:\"table\",raw:$(t[0],`\n`),header:[],align:[],rows:[]};if(n.length===s.length){for(let o of s)this.rules.other.tableAlignRight.test(o)?i.align.push(\"right\"):this.rules.other.tableAlignCenter.test(o)?i.align.push(\"center\"):this.rules.other.tableAlignLeft.test(o)?i.align.push(\"left\"):i.align.push(null);for(let o=0;o<n.length;o++)i.header.push({text:n[o],tokens:this.lexer.inline(n[o]),header:!0,align:i.align[o]});for(let o of r)i.rows.push(ee(o,i.header.length).map((p,a)=>({text:p,tokens:this.lexer.inline(p),header:!1,align:i.align[a]})));return i}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t){let n=t[1].trim();return{type:\"heading\",raw:$(t[0],`\n`),depth:t[2].charAt(0)===\"=\"?1:2,text:n,tokens:this.lexer.inline(n)}}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=t[1].charAt(t[1].length-1)===`\n`?t[1].slice(0,-1):t[1];return{type:\"paragraph\",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return{type:\"text\",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return{type:\"escape\",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:\"html\",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let i=$(n.slice(0,-1),\"\\\\\");if((n.length-i.length)%2===0)return}else{let i=fe(t[2],\"()\");if(i===-2)return;if(i>-1){let p=(t[0].indexOf(\"!\")===0?5:4)+t[1].length+i;t[2]=t[2].substring(0,i),t[0]=t[0].substring(0,p).trim(),t[3]=\"\"}}let s=t[2],r=\"\";if(this.options.pedantic){let i=this.rules.other.pedanticHrefTitle.exec(s);i&&(s=i[1],r=i[3])}else r=t[3]?t[3].slice(1,-1):\"\";return s=s.trim(),this.rules.other.startAngleBracket.test(s)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?s=s.slice(1):s=s.slice(1,-1)),xe(t,{href:s&&s.replace(this.rules.inline.anyPunctuation,\"$1\"),title:r&&r.replace(this.rules.inline.anyPunctuation,\"$1\")},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let s=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal,\" \"),r=t[s.toLowerCase()];if(!r){let i=n[0].charAt(0);return{type:\"text\",raw:i,text:i}}return xe(n,r,n[0],this.lexer,this.rules)}}emStrong(e,t,n=\"\"){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s||!s[1]&&!s[2]&&!s[3]&&!s[4]||s[4]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[3]||\"\")||!n||this.rules.inline.punctuation.exec(n)){let i=[...s[0]].length-1,o,p,a=i,u=0,c=s[0][0],h=n===c,k=c===\"*\"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(k.lastIndex=0,t=t.slice(-1*e.length+i);(s=k.exec(t))!==null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o)continue;if(p=[...o].length,s[3]||s[4]){a+=p;continue}else if(s[5]||s[6]){if(i%3&&!((i+p)%3)){u+=p;continue}if(h)break}if(a-=p,a>0)continue;p=Math.min(p,p+a+u);let T=[...s[0]][0].length,g=e.slice(0,i+s.index+T+p);if(Math.min(i,p)%2){let M=g.slice(1,-1);return{type:\"em\",raw:g,text:M,tokens:this.lexer.inlineTokens(M)}}let w=g.slice(2,-2);return{type:\"strong\",raw:g,text:w,tokens:this.lexer.inlineTokens(w)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){let n=t[2].replace(this.rules.other.newLineCharGlobal,\" \"),s=this.rules.other.nonSpaceChar.test(n),r=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return s&&r&&(n=n.substring(1,n.length-1)),{type:\"codespan\",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return{type:\"br\",raw:t[0]}}del(e,t,n=\"\"){let s=this.rules.inline.delLDelim.exec(e);if(!s)return;if(!(s[1]||\"\")||!n||this.rules.inline.punctuation.exec(n)){let i=[...s[0]].length-1,o,p,a=i,u=this.rules.inline.delRDelim;for(u.lastIndex=0,t=t.slice(-1*e.length+i);(s=u.exec(t))!==null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o||(p=[...o].length,p!==i))continue;if(s[3]||s[4]){a+=p;continue}if(a-=p,a>0)continue;p=Math.min(p,p+a);let c=[...s[0]][0].length,h=e.slice(0,i+s.index+c+p),k=h.slice(i,-i);return{type:\"del\",raw:h,text:k,tokens:this.lexer.inlineTokens(k)}}}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,s;return t[2]===\"@\"?(n=t[1],s=\"mailto:\"+n):(n=t[1],s=n),{type:\"link\",raw:t[0],text:n,href:s,tokens:[{type:\"text\",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,s;if(t[2]===\"@\")n=t[0],s=\"mailto:\"+n;else{let r;do r=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??\"\";while(r!==t[0]);n=t[0],t[1]===\"www.\"?s=\"http://\"+t[0]:s=t[0]}return{type:\"link\",raw:t[0],text:n,href:s,tokens:[{type:\"text\",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return{type:\"text\",raw:t[0],text:t[0],escaped:n}}}};var x=class l{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||R,this.options.tokenizer=this.options.tokenizer||new y,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let t={other:m,block:H.normal,inline:B.normal};this.options.pedantic?(t.block=H.pedantic,t.inline=B.pedantic):this.options.gfm&&(t.block=H.gfm,this.options.breaks?t.inline=B.breaks:t.inline=B.gfm),this.tokenizer.rules=t}static get rules(){return{block:H,inline:B}}static lex(e,t){return new l(t).lex(e)}static lexInline(e,t){return new l(t).inlineTokens(e)}lex(e){e=e.replace(m.carriageReturn,`\n`),this.blockTokens(e,this.tokens);for(let t=0;t<this.inlineQueue.length;t++){let n=this.inlineQueue[t];this.inlineTokens(n.src,n.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,t=[],n=!1){this.tokenizer.lexer=this,this.options.pedantic&&(e=e.replace(m.tabCharGlobal,\" \").replace(m.spaceLine,\"\"));let s=1/0;for(;e;){if(e.length<s)s=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}let r;if(this.options.extensions?.block?.some(o=>(r=o.call({lexer:this},e,t))?(e=e.substring(r.raw.length),t.push(r),!0):!1))continue;if(r=this.tokenizer.space(e)){e=e.substring(r.raw.length);let o=t.at(-1);r.raw.length===1&&o!==void 0?o.raw+=`\n`:t.push(r);continue}if(r=this.tokenizer.code(e)){e=e.substring(r.raw.length);let o=t.at(-1);o?.type===\"paragraph\"||o?.type===\"text\"?(o.raw+=(o.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,o.text+=`\n`+r.text,this.inlineQueue.at(-1).src=o.text):t.push(r);continue}if(r=this.tokenizer.fences(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.heading(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.hr(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.blockquote(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.list(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.html(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.def(e)){e=e.substring(r.raw.length);let o=t.at(-1);o?.type===\"paragraph\"||o?.type===\"text\"?(o.raw+=(o.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,o.text+=`\n`+r.raw,this.inlineQueue.at(-1).src=o.text):this.tokens.links[r.tag]||(this.tokens.links[r.tag]={href:r.href,title:r.title},t.push(r));continue}if(r=this.tokenizer.table(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.lheading(e)){e=e.substring(r.raw.length),t.push(r);continue}let i=e;if(this.options.extensions?.startBlock){let o=1/0,p=e.slice(1),a;this.options.extensions.startBlock.forEach(u=>{a=u.call({lexer:this},p),typeof a==\"number\"&&a>=0&&(o=Math.min(o,a))}),o<1/0&&o>=0&&(i=e.substring(0,o+1))}if(this.state.top&&(r=this.tokenizer.paragraph(i))){let o=t.at(-1);n&&o?.type===\"paragraph\"?(o.raw+=(o.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,o.text+=`\n`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=o.text):t.push(r),n=i.length!==e.length,e=e.substring(r.raw.length);continue}if(r=this.tokenizer.text(e)){e=e.substring(r.raw.length);let o=t.at(-1);o?.type===\"text\"?(o.raw+=(o.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,o.text+=`\n`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=o.text):t.push(r);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){this.tokenizer.lexer=this;let n=e;if(this.tokens.links){let o=Object.keys(this.tokens.links);o.length>0&&(n=n.replace(this.tokenizer.rules.inline.reflinkSearch,p=>o.includes(p.slice(p.lastIndexOf(\"[\")+1,-1))?\"[\"+\"a\".repeat(p.length-2)+\"]\":p))}n=n.replace(this.tokenizer.rules.inline.anyPunctuation,o=>\"+\".repeat(o.length)),n=n.replace(this.tokenizer.rules.inline.blockSkip,(o,p,a)=>{let u=a?a.length:0;return o.slice(0,u)+\"[\"+\"a\".repeat(o.length-u-2)+\"]\"}),n=this.options.hooks?.emStrongMask?.call({lexer:this},n)??n;let s=!1,r=\"\",i=1/0;for(;e;){if(e.length<i)i=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}s||(r=\"\"),s=!1;let o;if(this.options.extensions?.inline?.some(a=>(o=a.call({lexer:this},e,t))?(e=e.substring(o.raw.length),t.push(o),!0):!1))continue;if(o=this.tokenizer.escape(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.tag(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.link(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(o.raw.length);let a=t.at(-1);o.type===\"text\"&&a?.type===\"text\"?(a.raw+=o.raw,a.text+=o.text):t.push(o);continue}if(o=this.tokenizer.emStrong(e,n,r)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.codespan(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.br(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.del(e,n,r)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.autolink(e)){e=e.substring(o.raw.length),t.push(o);continue}if(!this.state.inLink&&(o=this.tokenizer.url(e))){e=e.substring(o.raw.length),t.push(o);continue}let p=e;if(this.options.extensions?.startInline){let a=1/0,u=e.slice(1),c;this.options.extensions.startInline.forEach(h=>{c=h.call({lexer:this},u),typeof c==\"number\"&&c>=0&&(a=Math.min(a,c))}),a<1/0&&a>=0&&(p=e.substring(0,a+1))}if(o=this.tokenizer.inlineText(p)){e=e.substring(o.raw.length),o.raw.slice(-1)!==\"_\"&&(r=o.raw.slice(-1)),s=!0;let a=t.at(-1);a?.type===\"text\"?(a.raw+=o.raw,a.text+=o.text):t.push(o);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return t}infiniteLoopError(e){let t=\"Infinite loop on byte: \"+e;if(this.options.silent)console.error(t);else throw new Error(t)}};var P=class{options;parser;constructor(e){this.options=e||R}space(e){return\"\"}code({text:e,lang:t,escaped:n}){let s=(t||\"\").match(m.notSpaceStart)?.[0],r=e.replace(m.endingNewline,\"\")+`\n`;return s?'<pre><code class=\"language-'+O(s)+'\">'+(n?r:O(r,!0))+`</code></pre>\n`:\"<pre><code>\"+(n?r:O(r,!0))+`</code></pre>\n`}blockquote({tokens:e}){return`<blockquote>\n${this.parser.parse(e)}</blockquote>\n`}html({text:e}){return e}def(e){return\"\"}heading({tokens:e,depth:t}){return`<h${t}>${this.parser.parseInline(e)}</h${t}>\n`}hr(e){return`<hr>\n`}list(e){let t=e.ordered,n=e.start,s=\"\";for(let o=0;o<e.items.length;o++){let p=e.items[o];s+=this.listitem(p)}let r=t?\"ol\":\"ul\",i=t&&n!==1?' start=\"'+n+'\"':\"\";return\"<\"+r+i+`>\n`+s+\"</\"+r+`>\n`}listitem(e){return`<li>${this.parser.parse(e.tokens)}</li>\n`}checkbox({checked:e}){return\"<input \"+(e?'checked=\"\" ':\"\")+'disabled=\"\" type=\"checkbox\"> '}paragraph({tokens:e}){return`<p>${this.parser.parseInline(e)}</p>\n`}table(e){let t=\"\",n=\"\";for(let r=0;r<e.header.length;r++)n+=this.tablecell(e.header[r]);t+=this.tablerow({text:n});let s=\"\";for(let r=0;r<e.rows.length;r++){let i=e.rows[r];n=\"\";for(let o=0;o<i.length;o++)n+=this.tablecell(i[o]);s+=this.tablerow({text:n})}return s&&(s=`<tbody>${s}</tbody>`),`<table>\n<thead>\n`+t+`</thead>\n`+s+`</table>\n`}tablerow({text:e}){return`<tr>\n${e}</tr>\n`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?\"th\":\"td\";return(e.align?`<${n} align=\"${e.align}\">`:`<${n}>`)+t+`</${n}>\n`}strong({tokens:e}){return`<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return`<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return`<code>${O(e,!0)}</code>`}br(e){return\"<br>\"}del({tokens:e}){return`<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let s=this.parser.parseInline(n),r=Y(e);if(r===null)return s;e=r;let i='<a href=\"'+e+'\"';return t&&(i+=' title=\"'+O(t)+'\"'),i+=\">\"+s+\"</a>\",i}image({href:e,title:t,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));let r=Y(e);if(r===null)return O(n);e=r;let i=`<img src=\"${e}\" alt=\"${O(n)}\"`;return t&&(i+=` title=\"${O(t)}\"`),i+=\">\",i}text(e){return\"tokens\"in e&&e.tokens?this.parser.parseInline(e.tokens):\"escaped\"in e&&e.escaped?e.text:O(e.text)}};var L=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return\"\"+e}image({text:e}){return\"\"+e}br(){return\"\"}checkbox({raw:e}){return e}};var b=class l{options;renderer;textRenderer;constructor(e){this.options=e||R,this.options.renderer=this.options.renderer||new P,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new L}static parse(e,t){return new l(t).parse(e)}static parseInline(e,t){return new l(t).parseInline(e)}parse(e){this.renderer.parser=this;let t=\"\";for(let n=0;n<e.length;n++){let s=e[n];if(this.options.extensions?.renderers?.[s.type]){let i=s,o=this.options.extensions.renderers[i.type].call({parser:this},i);if(o!==!1||![\"space\",\"hr\",\"heading\",\"code\",\"table\",\"blockquote\",\"list\",\"checkbox\",\"html\",\"def\",\"paragraph\",\"text\"].includes(i.type)){t+=o||\"\";continue}}let r=s;switch(r.type){case\"space\":{t+=this.renderer.space(r);break}case\"hr\":{t+=this.renderer.hr(r);break}case\"heading\":{t+=this.renderer.heading(r);break}case\"code\":{t+=this.renderer.code(r);break}case\"table\":{t+=this.renderer.table(r);break}case\"blockquote\":{t+=this.renderer.blockquote(r);break}case\"list\":{t+=this.renderer.list(r);break}case\"checkbox\":{t+=this.renderer.checkbox(r);break}case\"html\":{t+=this.renderer.html(r);break}case\"def\":{t+=this.renderer.def(r);break}case\"paragraph\":{t+=this.renderer.paragraph(r);break}case\"text\":{t+=this.renderer.text(r);break}default:{let i='Token with \"'+r.type+'\" type was not found.';if(this.options.silent)return console.error(i),\"\";throw new Error(i)}}}return t}parseInline(e,t=this.renderer){this.renderer.parser=this;let n=\"\";for(let s=0;s<e.length;s++){let r=e[s];if(this.options.extensions?.renderers?.[r.type]){let o=this.options.extensions.renderers[r.type].call({parser:this},r);if(o!==!1||![\"escape\",\"html\",\"link\",\"image\",\"checkbox\",\"strong\",\"em\",\"codespan\",\"br\",\"del\",\"text\"].includes(r.type)){n+=o||\"\";continue}}let i=r;switch(i.type){case\"escape\":{n+=t.text(i);break}case\"html\":{n+=t.html(i);break}case\"link\":{n+=t.link(i);break}case\"image\":{n+=t.image(i);break}case\"checkbox\":{n+=t.checkbox(i);break}case\"strong\":{n+=t.strong(i);break}case\"em\":{n+=t.em(i);break}case\"codespan\":{n+=t.codespan(i);break}case\"br\":{n+=t.br(i);break}case\"del\":{n+=t.del(i);break}case\"text\":{n+=t.text(i);break}default:{let o='Token with \"'+i.type+'\" type was not found.';if(this.options.silent)return console.error(o),\"\";throw new Error(o)}}}return n}};var S=class{options;block;constructor(e){this.options=e||R}static passThroughHooks=new Set([\"preprocess\",\"postprocess\",\"processAllTokens\",\"emStrongMask\"]);static passThroughHooksRespectAsync=new Set([\"preprocess\",\"postprocess\",\"processAllTokens\"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(e=this.block){return e?x.lex:x.lexInline}provideParser(e=this.block){return e?b.parse:b.parseInline}};var Z=class{defaults=C();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=b;Renderer=P;TextRenderer=L;Lexer=x;Tokenizer=y;Hooks=S;constructor(...e){this.use(...e)}walkTokens(e,t){let n=[];for(let s of e)switch(n=n.concat(t.call(this,s)),s.type){case\"table\":{let r=s;for(let i of r.header)n=n.concat(this.walkTokens(i.tokens,t));for(let i of r.rows)for(let o of i)n=n.concat(this.walkTokens(o.tokens,t));break}case\"list\":{let r=s;n=n.concat(this.walkTokens(r.items,t));break}default:{let r=s;this.defaults.extensions?.childTokens?.[r.type]?this.defaults.extensions.childTokens[r.type].forEach(i=>{let o=r[i].flat(1/0);n=n.concat(this.walkTokens(o,t))}):r.tokens&&(n=n.concat(this.walkTokens(r.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let s={...n};if(s.async=this.defaults.async||s.async||!1,n.extensions&&(n.extensions.forEach(r=>{if(!r.name)throw new Error(\"extension name required\");if(\"renderer\"in r){let i=t.renderers[r.name];i?t.renderers[r.name]=function(...o){let p=r.renderer.apply(this,o);return p===!1&&(p=i.apply(this,o)),p}:t.renderers[r.name]=r.renderer}if(\"tokenizer\"in r){if(!r.level||r.level!==\"block\"&&r.level!==\"inline\")throw new Error(\"extension level must be 'block' or 'inline'\");let i=t[r.level];i?i.unshift(r.tokenizer):t[r.level]=[r.tokenizer],r.start&&(r.level===\"block\"?t.startBlock?t.startBlock.push(r.start):t.startBlock=[r.start]:r.level===\"inline\"&&(t.startInline?t.startInline.push(r.start):t.startInline=[r.start]))}\"childTokens\"in r&&r.childTokens&&(t.childTokens[r.name]=r.childTokens)}),s.extensions=t),n.renderer){let r=this.defaults.renderer||new P(this.defaults);for(let i in n.renderer){if(!(i in r))throw new Error(`renderer '${i}' does not exist`);if([\"options\",\"parser\"].includes(i))continue;let o=i,p=n.renderer[o],a=r[o];r[o]=(...u)=>{let c=p.apply(r,u);return c===!1&&(c=a.apply(r,u)),c||\"\"}}s.renderer=r}if(n.tokenizer){let r=this.defaults.tokenizer||new y(this.defaults);for(let i in n.tokenizer){if(!(i in r))throw new Error(`tokenizer '${i}' does not exist`);if([\"options\",\"rules\",\"lexer\"].includes(i))continue;let o=i,p=n.tokenizer[o],a=r[o];r[o]=(...u)=>{let c=p.apply(r,u);return c===!1&&(c=a.apply(r,u)),c}}s.tokenizer=r}if(n.hooks){let r=this.defaults.hooks||new S;for(let i in n.hooks){if(!(i in r))throw new Error(`hook '${i}' does not exist`);if([\"options\",\"block\"].includes(i))continue;let o=i,p=n.hooks[o],a=r[o];S.passThroughHooks.has(i)?r[o]=u=>{if(this.defaults.async&&S.passThroughHooksRespectAsync.has(i))return(async()=>{let h=await p.call(r,u);return a.call(r,h)})();let c=p.call(r,u);return a.call(r,c)}:r[o]=(...u)=>{if(this.defaults.async)return(async()=>{let h=await p.apply(r,u);return h===!1&&(h=await a.apply(r,u)),h})();let c=p.apply(r,u);return c===!1&&(c=a.apply(r,u)),c}}s.hooks=r}if(n.walkTokens){let r=this.defaults.walkTokens,i=n.walkTokens;s.walkTokens=function(o){let p=[];return p.push(i.call(this,o)),r&&(p=p.concat(r.call(this,o))),p}}this.defaults={...this.defaults,...s}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return(n,s)=>{let r={...s},i={...this.defaults,...r},o=this.onError(!!i.silent,!!i.async);if(this.defaults.async===!0&&r.async===!1)return o(new Error(\"marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.\"));if(typeof n>\"u\"||n===null)return o(new Error(\"marked(): input parameter is undefined or null\"));if(typeof n!=\"string\")return o(new Error(\"marked(): input parameter is of type \"+Object.prototype.toString.call(n)+\", string expected\"));if(i.hooks&&(i.hooks.options=i,i.hooks.block=e),i.async)return(async()=>{let p=i.hooks?await i.hooks.preprocess(n):n,u=await(i.hooks?await i.hooks.provideLexer(e):e?x.lex:x.lexInline)(p,i),c=i.hooks?await i.hooks.processAllTokens(u):u;i.walkTokens&&await Promise.all(this.walkTokens(c,i.walkTokens));let k=await(i.hooks?await i.hooks.provideParser(e):e?b.parse:b.parseInline)(c,i);return i.hooks?await i.hooks.postprocess(k):k})().catch(o);try{i.hooks&&(n=i.hooks.preprocess(n));let a=(i.hooks?i.hooks.provideLexer(e):e?x.lex:x.lexInline)(n,i);i.hooks&&(a=i.hooks.processAllTokens(a)),i.walkTokens&&this.walkTokens(a,i.walkTokens);let c=(i.hooks?i.hooks.provideParser(e):e?b.parse:b.parseInline)(a,i);return i.hooks&&(c=i.hooks.postprocess(c)),c}catch(p){return o(p)}}}onError(e,t){return n=>{if(n.message+=`\nPlease report this to https://github.com/markedjs/marked.`,e){let s=\"<p>An error occurred:</p><pre>\"+O(n.message+\"\",!0)+\"</pre>\";return t?Promise.resolve(s):s}if(t)return Promise.reject(n);throw n}}};var E=new Z;function f(l,e){return E.parse(l,e)}f.options=f.setOptions=function(l){return E.setOptions(l),f.defaults=E.defaults,j(f.defaults),f};f.getDefaults=C;f.defaults=R;function kt(...l){return E.use(...l),f.defaults=E.defaults,j(f.defaults),f}f.use=kt;f.walkTokens=function(l,e){return E.walkTokens(l,e)};f.parseInline=E.parseInline;f.Parser=b;f.parser=b.parse;f.Renderer=P;f.TextRenderer=L;f.Lexer=x;f.lexer=x.lex;f.Tokenizer=y;f.Hooks=S;f.parse=f;var nn=f.options,rn=f.setOptions,sn=f.walkTokens,on=f.parseInline,an=f,ln=b.parse,pn=x.lex;export{S as Hooks,x as Lexer,Z as Marked,b as Parser,P as Renderer,L as TextRenderer,y as Tokenizer,R as defaults,C as getDefaults,pn as lexer,f as marked,nn as options,an as parse,on as parseInline,ln as parser,rn as setOptions,kt as use,sn as walkTokens};\n//# sourceMappingURL=marked.esm.js.map\n","/**\n * One reading column (DESIGN §1.3): 720px, centred, never full-bleed.\n * No bubbles, no cards — a 2px rule and whitespace carry the structure.\n */\n.transcriptWrap { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }\n.transcript {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: var(--space-8) var(--space-6) var(--space-6);\n scrollbar-gutter: stable;\n scroll-behavior: smooth;\n}\n.list {\n display: flex;\n flex-direction: column;\n gap: var(--space-6);\n width: 100%;\n max-width: var(--measure-read);\n margin: 0 auto;\n list-style: none;\n padding: 0;\n}\n.item { min-width: 0; }\n\n.skeleton {\n max-width: var(--measure-read);\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n /* The leading of .markdown body copy less the bar SkeletonLine draws, so\n the placeholder keeps the vertical rhythm of the text that replaces it.\n Derived from the SAME ramp pair as .markdown — it used to restate that\n leading as the literal 1.7, which meant retuning prose silently knocked\n the skeleton out of rhythm with it. */\n gap: calc(var(--text-base-line-relaxed) - var(--text-base-line));\n}\n.skeletonUser { margin-block: var(--space-2); padding-left: var(--space-4); }\n.loadError {\n display: grid;\n gap: var(--space-3);\n justify-items: start;\n max-width: var(--measure-read);\n margin: var(--space-8) auto 0;\n padding-left: var(--space-4);\n border-left: 2px solid var(--status-danger-solid);\n color: var(--text-secondary);\n font-size: var(--text-sm-size);\n}\n.loadError button {\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n color: var(--text-primary);\n font-size: var(--text-xs-size);\n transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);\n}\n.loadError button:hover { background: var(--bg-hover); border-color: var(--border-strong); }\n.loadError button:active { background: var(--bg-active); }\n\n.empty { max-width: var(--measure-read); margin: clamp(24px, 12vh, 120px) auto 0; color: var(--text-secondary); }\n.emptyTitle {\n font-family: var(--font-display);\n font-size: var(--text-xl-size);\n line-height: var(--text-xl-line);\n font-weight: var(--font-weight-medium);\n letter-spacing: var(--tracking-display, -0.02em);\n color: var(--text-primary);\n margin-bottom: var(--space-2);\n}\n.emptyBody { font-size: var(--text-sm-size); line-height: var(--text-sm-line); max-width: 52ch; }\n\n/* ---- user turn: indented behind a 2px rule, secondary text -------------- */\n.user { display: block; }\n.userText {\n padding-left: var(--space-4);\n border-left: 2px solid var(--border-strong);\n color: var(--text-secondary);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n font-size: var(--text-base-size);\n line-height: var(--text-base-line-relaxed);\n}\n\n/* ---- assistant turn: plain primary text at full measure ----------------- */\n.assistant { display: block; }\n.markdown {\n color: var(--text-primary);\n font-size: var(--text-base-size);\n line-height: var(--text-base-line-relaxed);\n overflow-wrap: anywhere;\n}\n.markdown > * + * { margin-top: var(--space-4); }\n.markdown p { margin: 0; }\n.markdown h1,\n.markdown h2,\n.markdown h3,\n.markdown h4 {\n font-family: var(--font-display);\n letter-spacing: var(--tracking-display, -0.02em);\n font-weight: var(--font-weight-semibold);\n margin-top: var(--space-6);\n margin-bottom: calc(-1 * var(--space-1));\n}\n.markdown h1 { font-size: var(--text-xl-size); line-height: var(--text-xl-line); }\n.markdown h2 { font-size: var(--text-lg-size); line-height: var(--text-lg-line); }\n.markdown h3 { font-size: var(--text-md-size); line-height: var(--text-md-line); }\n.markdown h4 { font-size: var(--text-base-size); font-weight: var(--font-weight-medium); }\n\n/* Hanging indents: the marker sits in the gutter, the text keeps one edge. */\n.markdown ul,\n.markdown ol { padding-left: 1.5em; margin-block: 0; }\n.markdown ul { list-style: disc; }\n.markdown ol { list-style: decimal; }\n.markdown ul ul { list-style: circle; }\n.markdown li { padding-left: 0.15em; }\n.markdown li::marker { color: var(--text-tertiary); }\n.markdown li + li { margin-top: var(--space-2); }\n.markdown li > ul,\n.markdown li > ol { margin-top: var(--space-2); }\n\n.markdown a { color: var(--text-link); text-decoration: underline; text-underline-offset: 2px; }\n.markdown blockquote {\n margin: 0;\n padding-left: var(--space-4);\n border-left: 2px solid var(--border-strong);\n color: var(--text-secondary);\n}\n.markdown hr { border: 0; border-top: 1px solid var(--border-subtle); margin-block: var(--space-6); }\n\n/* Hairline tables: rules, not boxes. */\n.markdown table {\n border-collapse: collapse;\n font-size: var(--text-sm-size);\n display: block;\n max-width: 100%;\n overflow-x: auto;\n}\n.markdown th,\n.markdown td {\n padding: var(--space-2) var(--space-3);\n border-bottom: 1px solid var(--border-subtle);\n text-align: left;\n vertical-align: top;\n}\n.markdown th {\n border-bottom-color: var(--border-default);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n}\n.markdown tr:last-child td { border-bottom: 0; }\n.markdown img { border-radius: var(--radius-xs); }\n\n.markdown code {\n font-family: var(--font-mono);\n font-size: 0.92em;\n background: var(--bg-code);\n border-radius: var(--radius-xs);\n padding: 0.1em 0.3em;\n}\n\n/* Code block: a language label and a copy button on hover, nothing else. */\n.markdown pre {\n position: relative;\n margin: 0;\n padding: var(--space-4);\n padding-top: var(--control-h-xs);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-sm);\n background: var(--bg-code);\n overflow-x: auto;\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line-relaxed);\n tab-size: 2;\n}\n.markdown pre code { background: none; padding: 0; font-size: inherit; white-space: pre; }\n.codeHead {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-2);\n height: var(--control-h-xs);\n padding: 0 var(--space-2) 0 var(--space-4);\n pointer-events: none;\n}\n/* --text-secondary, not tertiary: these sit on --bg-code, which resolves to\n --gray-100 in light, where --text-tertiary measures 4.40:1 — under the\n 4.5:1 floor, at 11px, on the only thing identifying the block's language.\n --text-secondary is 7.03:1 there. .copy:hover already goes to primary. */\n.codeLang {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-secondary);\n}\n.copy {\n pointer-events: auto;\n min-height: calc(var(--control-h-xs) - var(--space-1));\n padding: 0 var(--space-2);\n border-radius: var(--radius-xs);\n color: var(--text-secondary);\n font-family: var(--font-ui);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-medium);\n opacity: 0;\n transition: opacity var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);\n}\n.markdown pre:hover .copy,\n.copy:focus-visible { opacity: 1; }\n.copy:hover { color: var(--text-primary); background: var(--bg-hover); }\n.copy:active { background: var(--bg-active); }\n\n/* Streaming: a 2px × 1em accent caret trailing the text. */\n.caret,\n.streaming > :last-child::after {\n content: '';\n display: inline-block;\n width: 2px;\n height: 1em;\n margin-left: 2px;\n vertical-align: -0.15em;\n background: var(--accent-500);\n animation: verse-caret 1.2s var(--ease-standard) infinite;\n}\n.caret { vertical-align: middle; }\n\n/* ---- thinking ---------------------------------------------------------- */\n.thinking { color: var(--text-tertiary); font-size: var(--text-sm-size); }\n.thinkingSummary {\n cursor: pointer;\n list-style: none;\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--density-row, 32px);\n font-style: italic;\n}\n.thinkingSummary::-webkit-details-marker { display: none; }\n.thinkingSummary::before { content: '›'; font-style: normal; transition: transform var(--duration-fast) var(--ease-standard); }\n.thinking[open] .thinkingSummary::before { transform: rotate(90deg); }\n.thinkingBody {\n margin-top: var(--space-2);\n padding-left: var(--space-4);\n border-left: 2px solid var(--border-subtle);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n line-height: var(--text-sm-line-relaxed);\n color: var(--text-secondary);\n}\n\n/* ---- tool calls: one dense line, no card ------------------------------- */\n.tool,\n.toolRun { font-size: var(--text-sm-size); }\n\n.toolLine {\n display: grid;\n grid-template-columns: 12px auto minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--density-row-sm);\n padding-left: var(--space-3);\n border-left: 2px solid var(--border-subtle);\n cursor: pointer;\n list-style: none;\n color: var(--text-tertiary);\n}\n.toolLine::-webkit-details-marker { display: none; }\n.toolLine {\n transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.toolLine:hover { color: var(--text-secondary); background: var(--bg-hover); }\n.toolLine:active { background: var(--bg-active); }\n/* .toolArg and .toolState declare --text-tertiary themselves, so the row's\n :hover colour change does not reach them — only the ground under them moves.\n Measured, --text-tertiary is 4.40:1 on light --bg-hover and 3.95:1 on light\n --bg-active, both under the 4.5:1 floor in DESIGN-V2 §6. --text-secondary is\n 7.03:1 and 6.32:1 on the same two grounds. Same correction Sidebar.time\n already carries; design/tokens-contrast.test.ts pins both token pairs. */\n.toolLine:hover .toolArg,\n.toolLine:hover .toolState,\n.toolLine:active .toolArg,\n.toolLine:active .toolState { color: var(--text-secondary); }\n\n.toolGlyph {\n width: 12px;\n height: 12px;\n border: 1px solid currentColor;\n border-radius: 2px;\n transition: transform var(--duration-fast) var(--ease-standard);\n}\n.tool[open] > .toolLine > .toolGlyph,\n.toolRun[open] > .toolLine > .toolGlyph { background: currentColor; }\n\n.toolName {\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n color: var(--text-secondary);\n white-space: nowrap;\n}\n.toolArg {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n color: var(--text-tertiary);\n}\n.toolState {\n justify-self: end;\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n white-space: nowrap;\n}\n\n/* A failure tints the left rule and nothing else. */\n.toolFailed > .toolLine { border-left-color: var(--status-danger-solid); }\n.toolFailed > .toolLine > .toolState { color: var(--status-danger-fg); }\n\n.toolBody,\n.toolRunBody {\n display: grid;\n gap: var(--space-3);\n margin-top: var(--space-2);\n padding-left: var(--space-3);\n border-left: 2px solid var(--border-subtle);\n}\n.toolRunList { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }\n.toolRunList > li { min-width: 0; }\n.toolLabel {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-weight: var(--font-weight-semibold);\n letter-spacing: var(--tracking-label, 0.06em);\n text-transform: uppercase;\n color: var(--text-tertiary);\n margin-bottom: var(--space-1);\n}\n.toolPre {\n margin: 0;\n max-height: 360px;\n overflow: auto;\n padding: var(--space-3);\n border: 1px solid var(--border-subtle);\n border-radius: var(--radius-xs);\n background: var(--bg-code);\n font-family: var(--font-mono);\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: var(--text-primary);\n}\n.toolPending { color: var(--text-tertiary); font-size: var(--text-xs-size); }\n\n/* ---- notes / meta ------------------------------------------------------ */\n.note {\n padding-left: var(--space-4);\n border-left: 2px solid var(--border-subtle);\n color: var(--text-tertiary);\n font-size: var(--text-sm-size);\n}\n.noteError { border-left-color: var(--status-danger-solid); color: var(--status-danger-fg); }\n.meta { padding-left: var(--space-4); }\n.noteDuration {\n font-family: var(--font-display);\n font-variant-numeric: tabular-nums;\n}\n.metaText {\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n color: var(--text-tertiary);\n}\n\n.jump {\n position: absolute;\n left: 50%;\n bottom: var(--space-4);\n transform: translateX(-50%);\n display: inline-flex;\n align-items: center;\n gap: var(--space-2);\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-full);\n background: var(--bg-surface-raised);\n color: var(--text-secondary);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n box-shadow: var(--shadow-menu, var(--shadow-md));\n}\n.jump {\n transition: color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);\n}\n.jump:hover { color: var(--text-primary); border-color: var(--border-strong); }\n.jump:active { background: var(--bg-active); }\n.jumpUnseen { border-color: var(--accent-500); color: var(--text-primary); }\n\n@keyframes verse-caret { 50% { opacity: 0.15; } }\n\n/* Two triggers, the same pattern as the duration tokens in tokens.css and the\n shimmer in global.css: the OS preference applies unless Settings explicitly\n asked for full motion, and data-motion=\"reduce\" forces it on for an operator\n whose OS says nothing. A persistent `animation` has a hardcoded duration, so\n collapsing --duration-* does NOT reach it — it needs both rules by name. */\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .transcript { scroll-behavior: auto; }\n :root:not([data-motion=\"full\"]) .caret,\n :root:not([data-motion=\"full\"]) .streaming > :last-child::after { animation: none; }\n}\n:root[data-motion=\"reduce\"] .caret,\n:root[data-motion=\"reduce\"] .streaming > :last-child::after { animation: none; }\n:root[data-motion=\"reduce\"] .transcript { scroll-behavior: auto; }\n@media (max-width: 900px) {\n .transcript { padding: var(--space-5) var(--space-4); }\n}\n\n/* ---- turns ------------------------------------------------------------- */\n/* One exchange: the items, then the summary of what it touched. A turn is a\n region, not a card — no border, no background, no radius. Its only visible\n chrome appears when it is the target of a jump or a search hit. */\n.turn {\n display: block;\n min-width: 0;\n scroll-margin-block: var(--space-6);\n border-radius: var(--radius-xs);\n}\n/* `box-shadow: none` resets the GLOBAL focus ring. global.css gives every\n :focus-visible element `--shadow-focus-ring` (a 2px surface gap plus a 2px\n accent ring drawn with box-shadow); adding an accent outline on top of it\n without that reset is what drew two concentric accent rings around a\n focused turn, 8px apart. The outline is the right shape here — the turn is\n a region, and an 8px offset keeps the ring off the text — so the outline\n stays and the shadow goes.\n\n The reset is safe for a SEARCH HIT: `.turn[data-match]` below paints its\n gutter rule with box-shadow too, and at equal specificity the later rule\n wins, so a focused hit keeps its marker and an unfocused one is unchanged. */\n.turn:focus-visible {\n outline: 2px solid var(--accent-500);\n outline-offset: var(--space-2);\n box-shadow: none;\n}\n.turnItems {\n display: flex;\n flex-direction: column;\n gap: var(--space-6);\n list-style: none;\n margin: 0;\n padding: 0;\n min-width: 0;\n}\n\n/* Search hit / jump target: a 2px rule in the gutter, not a highlight wash.\n The gutter is outside the measure, so the reading column does not move.\n\n `--text-tertiary`, not `--border-strong`: this rule is the ONLY indication\n that a turn matched the query, so it carries meaning and DESIGN-V2 §6's 3:1\n floor applies. `--border-strong` is a hairline token, pinned only to a 1.1\n \"not invisible\" floor and explicitly exempt from 3:1 — it measures 1.45:1\n light / 1.66:1 dark against the transcript's `--bg-surface`. `--text-tertiary`\n is 4.83:1 / 5.47:1 and leaves `--accent-500` free to distinguish the ACTIVE\n hit from the rest. */\n.turn[data-match] {\n box-shadow: -2px 0 0 0 var(--text-tertiary);\n}\n.turn[data-match='active'] {\n box-shadow: -2px 0 0 0 var(--accent-500);\n}\n.turn[data-flash],\n[data-flash] {\n animation: verse-flash 1.4s var(--ease-standard) 1;\n}\n\n@keyframes verse-flash {\n 0%, 60% { background: var(--bg-selected); }\n 100% { background: transparent; }\n}\n\n.turnErrorJump {\n display: inline-flex;\n align-items: center;\n margin-top: var(--space-3);\n min-height: var(--control-h-xs);\n padding: 0 var(--space-2);\n border: 0;\n border-left: 2px solid var(--status-danger-solid);\n background: transparent;\n color: var(--status-danger-fg);\n font-size: var(--text-xs-size);\n cursor: pointer;\n transition: background var(--duration-fast) var(--ease-standard);\n}\n.turnErrorJump:hover { background: var(--status-danger-bg); }\n\n/* ---- tool line: the change size, right of the argument ------------------ */\n.toolLine { grid-template-columns: 12px auto minmax(0, 1fr) auto auto; }\n.toolDelta {\n display: inline-flex;\n gap: var(--space-2);\n font-family: var(--font-display);\n font-size: var(--text-2xs-size, 11px);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.toolAdd { color: var(--status-success-fg); }\n.toolDel { color: var(--status-danger-fg); }\n\n.toolNote {\n margin-top: var(--space-2);\n color: var(--text-tertiary);\n /* Prose, not a micro-label: tokens.css sets the body floor at 12px and\n reserves --text-2xs for uppercase labels and keyboard hints. */\n font-size: var(--text-xs-size);\n line-height: var(--text-xs-line-relaxed);\n}\n\n@media (prefers-reduced-motion: reduce) {\n :root:not([data-motion=\"full\"]) .turn[data-flash],\n :root:not([data-motion=\"full\"]) [data-flash] { animation: none; }\n}\n:root[data-motion=\"reduce\"] .turn[data-flash],\n:root[data-motion=\"reduce\"] [data-flash] { animation: none; }\n","/**\n * routes/verse/MessageMarkdown.tsx — assistant text rendered as Markdown.\n * `marked` produces HTML, DOMPurify strips anything that isn't safe inline\n * content, then each fenced block gets a language label and a copy button\n * revealed on hover (DESIGN §5). Model output is untrusted: raw HTML in the\n * Markdown never reaches the DOM unsanitized, links open in a new tab with\n * rel=noopener, and no script/style/handler attributes survive.\n */\nimport DOMPurify from 'dompurify';\nimport { marked } from 'marked';\nimport { useEffect, useMemo, useRef, type MouseEvent } from 'react';\nimport styles from './Transcript.module.css';\n\nlet hooked = false;\nfunction ensureHooks(): void {\n if (hooked) return;\n hooked = true;\n DOMPurify.addHook('afterSanitizeAttributes', (node) => {\n if (node.tagName === 'A') {\n node.setAttribute('target', '_blank');\n node.setAttribute('rel', 'noopener noreferrer');\n }\n });\n}\n\nconst SANITIZE: Parameters<typeof DOMPurify.sanitize>[1] = {\n USE_PROFILES: { html: true },\n ADD_ATTR: ['target'],\n FORBID_TAGS: ['style', 'form', 'input', 'button', 'iframe', 'object', 'embed'],\n};\n\nexport function renderMarkdown(text: string): string {\n ensureHooks();\n const html = marked.parse(text, { async: false, gfm: true, breaks: false });\n return DOMPurify.sanitize(html, SANITIZE);\n}\n\nconst COPY_LABEL = 'Copy';\nconst COPIED_LABEL = 'Copied';\n\n/** `language-ts` / `lang-ts` → `ts`; anything else is an unlabelled block. */\nexport function codeLanguage(code: Element | null): string {\n const match = /(?:^|\\s)(?:language|lang)-([\\w+#.-]+)/.exec(code?.className ?? '');\n return match?.[1] ?? '';\n}\n\nexport function MessageMarkdown({ text, streaming = false }: { text: string; streaming?: boolean }) {\n const html = useMemo(() => renderMarkdown(text), [text]);\n const root = useRef<HTMLDivElement>(null);\n\n // Decorate every <pre> with a language label + copy control after the\n // sanitized HTML lands. Buttons are stripped by the sanitizer, so the only\n // <button> inside a code block is one we put there ourselves.\n useEffect(() => {\n const node = root.current;\n if (!node) return;\n for (const pre of node.querySelectorAll('pre')) {\n if (pre.querySelector('[data-code-head]')) continue;\n const head = document.createElement('div');\n head.className = styles.codeHead ?? '';\n head.setAttribute('data-code-head', '');\n\n const language = codeLanguage(pre.querySelector('code'));\n const tag = document.createElement('span');\n tag.className = styles.codeLang ?? '';\n tag.textContent = language;\n head.append(tag);\n\n const button = document.createElement('button');\n button.type = 'button';\n button.className = styles.copy ?? '';\n button.setAttribute('data-copy', '');\n button.setAttribute('aria-label', 'Copy code');\n button.textContent = COPY_LABEL;\n head.append(button);\n\n pre.prepend(head);\n }\n }, [html]);\n\n function onClick(event: MouseEvent<HTMLDivElement>) {\n const target = event.target as HTMLElement | null;\n const button = target?.closest<HTMLButtonElement>('[data-copy]');\n if (!button) return;\n event.preventDefault();\n const pre = button.closest('pre');\n const codeNode = pre?.querySelector('code');\n const head = pre?.querySelector('[data-code-head]');\n const code = codeNode\n ? codeNode.textContent ?? ''\n : Array.from(pre?.childNodes ?? []).filter((n) => n !== head).map((n) => n.textContent ?? '').join('');\n void copyText(code).then((ok) => {\n button.textContent = ok ? COPIED_LABEL : 'Copy failed';\n setTimeout(() => {\n button.textContent = COPY_LABEL;\n }, 1500);\n });\n }\n\n return (\n <div\n ref={root}\n className={`${styles.markdown} ${streaming ? styles.streaming : ''}`}\n onClick={onClick}\n // Sanitized above — DOMPurify with the html profile, no raw model HTML.\n dangerouslySetInnerHTML={{ __html: html }}\n />\n );\n}\n\nasync function copyText(text: string): Promise<boolean> {\n try {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(text);\n return true;\n }\n } catch {\n /* fall through to the legacy path */\n }\n try {\n const area = document.createElement('textarea');\n area.value = text;\n area.setAttribute('readonly', '');\n area.style.position = 'fixed';\n area.style.opacity = '0';\n document.body.append(area);\n area.select();\n const ok = document.execCommand('copy');\n area.remove();\n return ok;\n } catch {\n return false;\n }\n}\n","/**\n * routes/verse/chat/ansi.ts — turning raw process output into something a\n * human can read.\n *\n * An agentic turn's Bash results arrive exactly as the child process wrote\n * them: SGR colour runs, cursor moves, OSC title sets, and carriage returns\n * from progress bars that expected a terminal to overwrite the line. Dumped\n * into a <pre> those print as `[0;32m` litter and a hundred duplicate\n * progress lines, which is why command output in the transcript is currently\n * the hardest thing in it to read.\n *\n * Pure string functions, no DOM: the colour information is DROPPED rather\n * than translated into spans. DESIGN §1 is monochrome-first — a tool's own\n * palette is not one of the meanings this interface spends colour on.\n */\n\n/* eslint-disable no-control-regex --\n Matching control bytes IS this module's entire purpose: the four patterns\n below are the escape grammar a terminal emits, and there is no way to\n express them without naming the control characters they match. They are\n written as \\uXXXX escapes, never as literal bytes in the source. */\n\n/** CSI … final byte @-~ — SGR colour, cursor moves, erase, everything. */\nconst CSI = /\\u001B\\[[0-9;:?]*[ -/]*[@-~]/g;\n/** OSC … terminated by BEL or ST — window titles, hyperlinks, clipboard. */\nconst OSC = /\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\\\)/g;\n/** Two-byte escapes (ESC 7 / ESC M / charset selects). */\nconst SHORT = /\\u001B[@-Z\\\\-_]/g;\n/** Control bytes that carry no meaning inside a <pre>: tab/newline/CR stay. */\nconst CONTROL = /[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F]/g;\n\n/* eslint-enable no-control-regex */\n\n/** True when the text contains at least one escape sequence. */\nexport function hasAnsi(text: string): boolean {\n return text.includes('\\u001B');\n}\n\n/** Remove every escape sequence and stray control byte; keep tabs/newlines. */\nexport function stripAnsi(text: string): string {\n return text.replace(OSC, '').replace(CSI, '').replace(SHORT, '').replace(CONTROL, '');\n}\n\n/**\n * Collapse carriage-return rewrites the way a terminal would: within one\n * line each CR returns the cursor to column 0 and what follows overwrites\n * what was there. A shorter overwrite leaves the tail of the longer line\n * visible, which is why this overlays rather than simply taking the last\n * segment — `100%\\rdone` is `done%` on a real terminal, not `done`.\n */\nexport function applyCarriageReturns(text: string): string {\n if (!text.includes('\\r')) return text;\n return text\n .split('\\n')\n .map((line) => {\n if (!line.includes('\\r')) return line;\n let out = '';\n for (const segment of line.split('\\r')) {\n out = segment.length >= out.length ? segment : segment + out.slice(segment.length);\n }\n return out;\n })\n .join('\\n');\n}\n\n/**\n * The whole treatment: escapes out, carriage returns applied, trailing blank\n * lines trimmed. Leading whitespace is preserved — indentation is content in\n * compiler output, stack traces and test reports.\n */\nexport function cleanTerminalOutput(text: string): string {\n return applyCarriageReturns(stripAnsi(text))\n .replace(/[ \\t]+$/gm, '')\n .replace(/\\n+$/, '');\n}\n\n/** Line count without allocating a split array. */\nexport function countLines(text: string): number {\n if (text.length === 0) return 0;\n let n = 1;\n for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) === 10) n++;\n return n;\n}\n\n/**\n * First `limit` lines plus how many were withheld. Backs the collapsed view\n * of a long result — the full text stays one click away, never discarded.\n */\nexport function headLines(text: string, limit: number): { head: string; hidden: number } {\n const lines = text.split('\\n');\n if (lines.length <= limit) return { head: text, hidden: 0 };\n return { head: lines.slice(0, limit).join('\\n'), hidden: lines.length - limit };\n}\n","/**\n * routes/verse/chat/CommandOutput.tsx — a shell run, readable.\n *\n * Three things were wrong with dumping `tool-result.output` into a <pre>:\n * escape sequences printed as `[0;32m` litter, progress bars repeated every\n * carriage-return frame, and a thousand-line build log pushed the rest of\n * the turn off the screen. All three are fixed here without losing anything:\n * `ansi.ts` cleans the text, long output collapses to a head with an exact\n * count of what is hidden, and \"Show all\" restores it.\n *\n * The status line is honest (DESIGN §6). A stated exit code is printed as a\n * number; when the tool never stated one, the line says whether the call\n * failed and does not invent a code.\n */\nimport { useMemo, useState, type ReactNode } from 'react';\nimport { cleanTerminalOutput, countLines, hasAnsi, headLines } from './ansi.js';\nimport type { CommandFacts } from './tool-semantics.js';\nimport styles from './chat.module.css';\n\nconst PREVIEW_LINES = 20;\n/** Hard ceiling: past this, the DOM cost stops being worth it. */\nconst MAX_RENDER_CHARS = 200_000;\n\nexport interface CommandOutputProps {\n command: CommandFacts | null;\n output: string;\n /** The tool reported failure for this call. */\n isError: boolean;\n pending: boolean;\n /**\n * Replaces the raw output block. A command whose output IS a diff\n * (`git diff`, `git show`) keeps its command line and exit status here and\n * renders the diff properly instead of as terminal text.\n */\n body?: ReactNode;\n}\n\nexport function CommandOutput({ command, output, isError, pending, body }: CommandOutputProps) {\n const [expanded, setExpanded] = useState(false);\n const cleaned = useMemo(() => {\n const text = cleanTerminalOutput(output);\n return text.length > MAX_RENDER_CHARS\n ? `${text.slice(0, MAX_RENDER_CHARS)}\\n… (${text.length - MAX_RENDER_CHARS} more characters not shown)`\n : text;\n }, [output]);\n const { head, hidden } = useMemo(() => headLines(cleaned, PREVIEW_LINES), [cleaned]);\n const shown = expanded ? cleaned : head;\n const exit = command?.exitCode ?? null;\n\n return (\n <div className={styles.command} data-failed={isError ? 'true' : undefined}>\n {command ? (\n <div className={styles.commandLine}>\n <span className={styles.commandPrompt} aria-hidden=\"true\">$</span>\n <code className={styles.commandText}>{command.command}</code>\n </div>\n ) : null}\n <div className={styles.commandStatus}>\n <span className={styles.commandStatusText} data-tone={pending ? 'pending' : isError ? 'bad' : 'ok'}>\n {pending\n ? 'running…'\n : exit !== null\n ? `exit ${exit}`\n : isError\n ? 'failed — no exit code reported'\n : 'completed — no exit code reported'}\n </span>\n {!pending && !body && cleaned.length === 0 ? <span className={styles.commandMeta}>no output</span> : null}\n {!pending && !body && cleaned.length > 0 ? (\n <span className={styles.commandMeta}>\n {countLines(cleaned)} line{countLines(cleaned) === 1 ? '' : 's'}\n {hasAnsi(output) ? ' · colour codes stripped' : ''}\n </span>\n ) : null}\n </div>\n {pending ? (\n <p className={styles.commandPending}>Waiting for the command to finish…</p>\n ) : body ? (\n body\n ) : cleaned.length > 0 ? (\n <>\n <pre className={styles.commandPre}>{shown}</pre>\n {hidden > 0 ? (\n <button type=\"button\" className={styles.commandMore} aria-expanded={expanded}\n onClick={() => setExpanded((v) => !v)}>\n {expanded ? 'Collapse output' : `Show ${hidden} more line${hidden === 1 ? '' : 's'}`}\n </button>\n ) : null}\n </>\n ) : null}\n </div>\n );\n}\n","/**\n * routes/verse/chat/DiffBlock.tsx — a file change rendered as a change.\n *\n * The transcript's job here is narrow: ONE file, inside a 720px reading\n * column, inline in a tool card. The inbox `DiffViewer` is the right tool\n * for the other shape — a multi-file patch that wants a file tree and a\n * split toggle — so that component is imported and used verbatim for\n * multi-file diffs rather than reimplemented. The parser\n * (`routes/inbox/diff-parser.ts`) and the highlighter\n * (`routes/inbox/highlight.ts`) are shared by both paths; nothing about\n * either is rewritten here.\n *\n * Honesty (DESIGN §6): an `Edit` payload knows what was replaced but not\n * where it sat, so when `diff.anchored` is false the line-number gutter is\n * hidden and the header says the offsets are not the file's.\n */\nimport { useMemo, useState } from 'react';\nimport { DiffViewer } from '../../inbox/DiffViewer.js';\nimport { parseUnifiedDiff, type DiffFile, type DiffHunk } from '../../inbox/diff-parser.js';\nimport { languageForPath, tokenizeLine, type LangFamily } from '../../inbox/highlight.js';\nimport type { ToolDiff } from './tool-semantics.js';\nimport styles from './chat.module.css';\n\n/** Beyond this many rendered lines the block collapses to a preview. */\nconst COLLAPSE_AFTER_LINES = 28;\nconst PREVIEW_LINES = 18;\n/**\n * Hard ceiling on rows materialised from one file's hunks. The text itself is\n * already capped in `readToolFacts`, but a capped diff can still be tens of\n * thousands of lines, and every row here becomes DOM. Past this the block says\n * how many it dropped rather than locking the tab building rows nobody asked to\n * see.\n */\nconst MAX_ROWS = 4000;\n\nexport interface DiffBlockProps {\n diff: ToolDiff;\n /** Falls back to the diff's own path when the payload named none. */\n path?: string | null;\n}\n\nexport function DiffBlock({ diff, path = null }: DiffBlockProps) {\n const parsed = useMemo(() => parseUnifiedDiff(diff.text), [diff.text]);\n\n if (parsed.files.length === 0) return null;\n if (diff.multiFile || parsed.files.length > 1) {\n return (\n <div className={styles.diffMulti}>\n <DiffViewer diff={diff.text} proposalKind=\"tool call\" />\n </div>\n );\n }\n\n const file = parsed.files[0]!;\n return <SingleFileDiff file={file} anchored={diff.anchored} path={path ?? file.displayPath} />;\n}\n\n/**\n * What happened to the file, when that is not simply \"it was edited\".\n *\n * A rename with no hunks is the case that made this necessary: it reached the\n * empty branch below and printed \"No line-level changes in this call.\" under\n * the NEW path alone, telling the operator nothing happened while silently\n * dropping the old location — the one fact that makes a rename legible.\n */\nfunction statusNote(file: DiffFile): string | null {\n switch (file.status) {\n case 'renamed':\n return 'Renamed. The contents did not change, so there are no lines to show.';\n case 'added':\n return 'New file. It was added with no contents to diff against.';\n case 'deleted':\n return 'Deleted. The file is gone, so there are no lines to show.';\n default:\n return null;\n }\n}\n\nfunction SingleFileDiff({ file, anchored, path }: { file: DiffFile; anchored: boolean; path: string }) {\n const [expanded, setExpanded] = useState(false);\n const lang = languageForPath(path);\n const rows = useMemo(() => flatten(file.hunks), [file.hunks]);\n const long = rows.length > COLLAPSE_AFTER_LINES;\n const visible = long && !expanded ? rows.slice(0, PREVIEW_LINES) : rows;\n const hidden = rows.length - visible.length;\n const renamedFrom = file.status === 'renamed' ? file.oldPath : null;\n const note = statusNote(file);\n\n return (\n <div className={styles.diff} data-anchored={anchored ? 'true' : 'false'} data-status={file.status}>\n <div className={styles.diffHead}>\n {renamedFrom ? (\n <span className={styles.diffOldPath} title={renamedFrom}>\n {renamedFrom}\n <span className={styles.visuallyHidden}> renamed to</span>\n </span>\n ) : null}\n <span className={styles.diffPath} title={path}>{path}</span>\n {file.status !== 'modified' ? (\n <span className={styles.diffStatus}>{file.status}</span>\n ) : null}\n <span className={styles.diffStats}>\n {file.additions > 0 ? <span className={styles.diffAdd}>+{file.additions}</span> : null}\n {file.deletions > 0 ? <span className={styles.diffDel}>−{file.deletions}</span> : null}\n </span>\n </div>\n {file.unparsedNotice ? <pre className={styles.diffNotice}>{file.unparsedNotice}</pre> : null}\n {rows.length === 0 ? (\n <p className={styles.diffEmpty}>\n {note ?? 'No line-level changes in this call.'}\n </p>\n ) : (\n <>\n <table className={styles.diffTable}>\n <tbody>\n {visible.map((row) =>\n row.kind === 'hunk' ? (\n <tr key={row.key} className={styles.diffHunkRow}>\n {anchored ? <td className={styles.diffNo} aria-hidden=\"true\" /> : null}\n <td className={styles.diffMarker} aria-hidden=\"true\" />\n <td className={styles.diffHunkHead}>{row.label}</td>\n </tr>\n ) : (\n <tr key={row.key} className={styles[`diffRow_${row.line.kind}`]}>\n {anchored ? (\n <td className={styles.diffNo}>{row.line.newLineNo ?? row.line.oldLineNo ?? ''}</td>\n ) : null}\n <td className={styles.diffMarker} aria-hidden=\"true\">\n {row.line.kind === 'add' ? '+' : row.line.kind === 'del' ? '−' : ''}\n </td>\n <td className={styles.diffText}>\n <CodeLine text={row.line.text} lang={lang} />\n </td>\n </tr>\n ),\n )}\n </tbody>\n </table>\n {long ? (\n <button type=\"button\" className={styles.diffMore} onClick={() => setExpanded((v) => !v)}\n aria-expanded={expanded}>\n {expanded ? 'Collapse diff' : `Show ${hidden} more line${hidden === 1 ? '' : 's'}`}\n </button>\n ) : null}\n </>\n )}\n {!anchored ? (\n <p className={styles.diffUnanchored}>\n Line numbers are not shown — this tool call reported what it replaced, not where in the file.\n </p>\n ) : null}\n </div>\n );\n}\n\ntype Row =\n | { kind: 'hunk'; key: string; label: string }\n | { kind: 'line'; key: string; line: DiffHunk['lines'][number] };\n\n/** Hunks into one flat row list, with a separator row between hunks. */\nfunction flatten(hunks: readonly DiffHunk[]): Row[] {\n const rows: Row[] = [];\n let truncated = false;\n hunks.forEach((hunk, h) => {\n if (truncated) return;\n // The `@@ -a,b +c,d @@` arithmetic is noise in a chat column; the free\n // text after it (`edit 2 of 3`, a function name) is the only part worth\n // a row, and a multi-hunk diff needs SOME separator regardless.\n const section = hunk.header.replace(/^@@[^@]*@@/, '').trim();\n if (section || hunks.length > 1) {\n rows.push({ kind: 'hunk', key: `h${h}`, label: section || `hunk ${h + 1}` });\n }\n for (let i = 0; i < hunk.lines.length; i++) {\n if (rows.length >= MAX_ROWS) {\n truncated = true;\n rows.push({ kind: 'hunk', key: 'truncated', label: `diff truncated at ${MAX_ROWS} lines` });\n return;\n }\n rows.push({ kind: 'line', key: `h${h}l${i}`, line: hunk.lines[i]! });\n }\n });\n return rows;\n}\n\nfunction CodeLine({ text, lang }: { text: string; lang: LangFamily }) {\n const tokens = tokenizeLine(text, lang);\n return (\n <code className={styles.diffCode}>\n {tokens.map((token, i) => (\n <span key={i} className={styles[`tok_${token.kind}`]}>{token.text}</span>\n ))}\n </code>\n );\n}\n","/**\n * routes/verse/ToolUseCard.tsx — one tool call.\n *\n * Collapsed it is a single dense line (DESIGN §5): a 12px glyph, the tool\n * name in mono, a truncated argument, and a right-aligned duration. A call\n * that changed a file also carries its `+12 −3` there, in the display font,\n * because the size of a change is the thing most worth knowing before\n * deciding to open it.\n *\n * Expanded, the body is chosen by what the call actually DID\n * (`chat/tool-semantics.ts`) rather than by dumping JSON:\n *\n * - an edit / create / patch → a real unified diff (`chat/DiffBlock`,\n * which reuses the inbox parser, highlighter and multi-file viewer)\n * - a shell run → the command, an honest exit status, and\n * output with ANSI stripped and long logs collapsed (`chat/CommandOutput`)\n * - anything else → the input and result as mono blocks, as before\n *\n * A failure tints the left rule and nothing else — the word \"error\" carries\n * the state (DESIGN §6).\n */\nimport { useMemo } from 'react';\nimport { CommandOutput } from './chat/CommandOutput.js';\nimport { DiffBlock } from './chat/DiffBlock.js';\nimport { countDiffLines } from './chat/turn-model.js';\nimport { readToolFacts, toolAnchorId, type ToolFacts } from './chat/tool-semantics.js';\nimport { formatDuration, prettyJson, summarizeToolInput } from './verse-model.js';\nimport styles from './Transcript.module.css';\n\nexport interface ToolUseCardProps {\n name: string;\n input: unknown;\n result: { output: string; isError: boolean } | null;\n /** Stable id so open/closed state can survive re-renders (data-state-key). */\n toolUseId: string;\n /** tool-use → tool-result wall time, when both frames were stamped. */\n durationMs?: number | null;\n /**\n * Derived once per transcript by `chat/turn-model.buildTurns` and handed\n * down, so a card never re-parses a diff the file-activity summary already\n * parsed. Omitted (tests, one-off renders) it is derived here.\n */\n facts?: ToolFacts;\n}\n\nconst MAX_OUTPUT_CHARS = 20_000;\n\nexport function ToolUseCard({ name, input, result, toolUseId, durationMs = null, facts }: ToolUseCardProps) {\n const derived = useMemo(\n () => facts ?? readToolFacts({ name, input, result }),\n [facts, name, input, result],\n );\n const summary = summarizeToolInput(input);\n const isError = derived.failed || result?.isError === true;\n const pending = result === null;\n const state = pending\n ? 'running'\n : isError\n ? 'error'\n : durationMs !== null && durationMs > 0\n ? formatDuration(durationMs)\n : 'done';\n // Re-splitting the whole diff on every render of every card is pure waste:\n // the text is immutable once the result has landed.\n const delta = useMemo(\n () => (derived.diff ? countDiffLines(derived.diff.text) : null),\n [derived.diff],\n );\n const output = result\n ? result.output.length > MAX_OUTPUT_CHARS\n ? `${result.output.slice(0, MAX_OUTPUT_CHARS)}\\n… (${result.output.length - MAX_OUTPUT_CHARS} more characters)`\n : result.output\n : '';\n\n return (\n <details id={toolAnchorId(toolUseId)} className={`${styles.tool} ${isError ? styles.toolFailed : ''}`}\n data-state-key={`tool:${toolUseId}`} data-action={derived.action}>\n <summary className={styles.toolLine} aria-label={`${name}${summary ? `: ${summary}` : ''} (${state})`}>\n <span className={styles.toolGlyph} aria-hidden=\"true\" />\n <span className={styles.toolName}>{name}</span>\n {summary ? <span className={styles.toolArg} title={summary}>{summary}</span> : null}\n {delta && (delta.additions > 0 || delta.deletions > 0) ? (\n <span className={styles.toolDelta} aria-hidden=\"true\">\n {delta.additions > 0 ? <span className={styles.toolAdd}>+{delta.additions}</span> : null}\n {delta.deletions > 0 ? <span className={styles.toolDel}>−{delta.deletions}</span> : null}\n </span>\n ) : null}\n <span className={styles.toolState}>{state}</span>\n </summary>\n <div className={styles.toolBody}>\n <ToolBody input={input} output={output} facts={derived} pending={pending} isError={isError} />\n </div>\n </details>\n );\n}\n\ninterface ToolBodyProps {\n input: unknown;\n output: string;\n facts: ToolFacts;\n pending: boolean;\n isError: boolean;\n}\n\nfunction ToolBody({ input, output, facts, pending, isError }: ToolBodyProps) {\n // A shell run: the command line and exit status always, with the diff in\n // place of the log when the command's own output is one.\n if (facts.command) {\n return (\n <CommandOutput command={facts.command} output={output} isError={isError} pending={pending}\n body={facts.diff ? <DiffBlock diff={facts.diff} path={facts.paths[0] ?? null} /> : undefined} />\n );\n }\n\n if (facts.diff) {\n return (\n <>\n <DiffBlock diff={facts.diff} path={facts.paths[0] ?? null} />\n {pending ? <p className={styles.toolPending}>Waiting for the tool to finish…</p> : null}\n {isError && output ? (\n <section>\n <h4 className={styles.toolLabel}>Error</h4>\n <pre className={styles.toolPre}>{output}</pre>\n </section>\n ) : null}\n </>\n );\n }\n\n if (facts.written) {\n return (\n <>\n <section>\n <h4 className={styles.toolLabel}>Contents written to {facts.written.path}</h4>\n <pre className={styles.toolPre}>{facts.written.text}</pre>\n <p className={styles.toolNote}>\n The previous contents were not in this tool call, so there is nothing to diff against.\n </p>\n </section>\n <section>\n <h4 className={styles.toolLabel}>{isError ? 'Error' : 'Result'}</h4>\n {pending ? <p className={styles.toolPending}>Waiting for the tool to finish…</p>\n : <pre className={styles.toolPre}>{output || '(empty)'}</pre>}\n </section>\n </>\n );\n }\n\n return (\n <>\n {input !== null && input !== undefined ? (\n <section>\n <h4 className={styles.toolLabel}>Input</h4>\n <pre className={styles.toolPre}>{prettyJson(input)}</pre>\n </section>\n ) : null}\n <section>\n <h4 className={styles.toolLabel}>{isError ? 'Error' : 'Result'}</h4>\n {pending ? <p className={styles.toolPending}>Waiting for the tool to finish…</p>\n : <pre className={styles.toolPre}>{output || '(empty)'}</pre>}\n </section>\n </>\n );\n}\n","/**\n * routes/verse/Transcript.tsx — the conversation, in one 720px measure.\n *\n * No bubbles (DESIGN §5): the user turn is indented behind a 2px left rule\n * in secondary text, the assistant turn is plain primary text at full\n * measure. Role is weight and rule, never a coloured box.\n *\n * Runs of tool calls fold (verse-store groupTranscriptItems) into one\n * `6 tools · Read ×4, Edit ×2 · 12s` row, so an agentic turn reads as a\n * summary line between two pieces of prose instead of a wall of cards.\n *\n * On top of that the items are grouped into TURNS (`chat/turn-model.ts`),\n * which is what makes a long agentic session usable:\n *\n * - each turn ends with a file-activity summary — the blast radius of one\n * ask, with a click-through to the call that changed each file;\n * - the nav strip gives the session an outline, a search over prose AND\n * tool payloads, and a jump to the first failure;\n * - Alt+↑/↓ (and plain ↑/↓ once a turn has focus) step between turns.\n *\n * Follows the newest message unless the operator scrolled up, in which case\n * a \"Jump to latest\" control appears.\n */\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react';\nimport { SkeletonLine } from '../../components/primitives/Skeleton.js';\nimport { FileActivity } from './chat/FileActivity.js';\nimport { TranscriptNav } from './chat/TranscriptNav.js';\nimport { toolAnchorId, type ToolFacts } from './chat/tool-semantics.js';\nimport { buildTurns, createTurnCache, noteAnchorId, searchTurns, turnAnchorId } from './chat/turn-model.js';\nimport { MessageMarkdown } from './MessageMarkdown.js';\nimport { ToolUseCard } from './ToolUseCard.js';\nimport { ArrowDownIcon } from './verse-icons.js';\nimport { formatDuration } from './verse-model.js';\nimport { groupTranscriptItems, type ToolGroupItem, type ToolGroupMember, type Transcript as TranscriptModel, type TranscriptRenderItem } from './verse-store.js';\nimport styles from './Transcript.module.css';\n\nexport interface TranscriptProps {\n transcript: TranscriptModel;\n loaded: boolean;\n loadError: string | null;\n onRetry?: () => void;\n emptyHint?: string;\n}\n\nconst FOLLOW_THRESHOLD_PX = 48;\n/** Below this the session is short enough to scroll; chrome would be noise. */\nconst NAV_MIN_TURNS = 3;\n/** How long a jumped-to element keeps its locator tint. */\nconst FLASH_MS = 1400;\n\nexport function Transcript({ transcript, loaded, loadError, onRetry, emptyHint }: TranscriptProps) {\n const scroller = useRef<HTMLDivElement>(null);\n const turnNodes = useRef(new Map<string, HTMLElement>());\n const flashTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [following, setFollowing] = useState(true);\n const [unseen, setUnseen] = useState(false);\n const [query, setQuery] = useState('');\n const [matchIndex, setMatchIndex] = useState(-1);\n const [focusToken, setFocusToken] = useState(0);\n const lastCount = useRef(0);\n\n // `transcript.items` is a fresh array on every streamed token, so both memos\n // below miss on every frame. The cache is what keeps that from meaning \"and\n // therefore re-derive every tool call in the session, LCS diffs included\".\n // It is keyed by `toolUseId`, which outlives the rebuilt item objects.\n const turnCache = useRef(createTurnCache());\n const rendered = useMemo(() => groupTranscriptItems(transcript.items), [transcript.items]);\n const model = useMemo(() => buildTurns(rendered, turnCache.current), [rendered]);\n const matches = useMemo(\n () => searchTurns(model.turns, query, turnCache.current),\n [model.turns, query],\n );\n const matchKeys = useMemo(() => new Set(matches.map((m) => m.turnKey)), [matches]);\n\n // A `turn-done ok:false` that follows the same turn's `cancelled`/`error`\n // note is already explained; a second red \"ended without a result\" line\n // would make every Stop look like a failure.\n const explained = useMemo(() => {\n const out = new Set<string>();\n let last: { turnId: string | null; kind: string } | null = null;\n for (const item of transcript.items) {\n if (item.kind === 'turn-done' && !item.ok && last && last.turnId === item.turnId && (last.kind === 'cancelled' || last.kind === 'error')) {\n out.add(item.key);\n }\n last = { turnId: item.turnId, kind: item.kind };\n }\n return out;\n }, [transcript.items]);\n\n const scrollToBottom = useCallback((behavior: ScrollBehavior = 'auto') => {\n const node = scroller.current;\n if (!node) return;\n // jsdom has no Element.scrollTo; fall back to the property for tests.\n if (typeof node.scrollTo === 'function') node.scrollTo({ top: node.scrollHeight, behavior });\n else node.scrollTop = node.scrollHeight;\n }, []);\n\n function onScroll() {\n const node = scroller.current;\n if (!node) return;\n const distance = node.scrollHeight - node.scrollTop - node.clientHeight;\n const atBottom = distance <= FOLLOW_THRESHOLD_PX;\n setFollowing(atBottom);\n if (atBottom) setUnseen(false);\n }\n\n // ---- jumping -------------------------------------------------------------\n /** Scroll an element into view and tint it briefly so the eye can find it. */\n const reveal = useCallback((node: HTMLElement | null) => {\n if (!node) return;\n setFollowing(false);\n if (typeof node.scrollIntoView === 'function') node.scrollIntoView({ block: 'center', behavior: 'smooth' });\n if (typeof node.focus === 'function') node.focus({ preventScroll: true });\n node.setAttribute('data-flash', 'true');\n if (flashTimer.current) clearTimeout(flashTimer.current);\n flashTimer.current = setTimeout(() => node.removeAttribute('data-flash'), FLASH_MS);\n }, []);\n\n useEffect(() => () => {\n if (flashTimer.current) clearTimeout(flashTimer.current);\n }, []);\n\n const jumpToTurn = useCallback((turnKey: string) => {\n reveal(turnNodes.current.get(turnKey) ?? null);\n }, [reveal]);\n\n /** Open the disclosure chain around a tool call before revealing it. */\n const jumpToAnchor = useCallback((id: string) => {\n const node = scroller.current?.ownerDocument?.getElementById(id) ?? null;\n if (!node) return;\n for (let el: Element | null = node; el; el = el.parentElement) {\n if (el instanceof HTMLDetailsElement) el.open = true;\n if (el === scroller.current) break;\n }\n reveal(node);\n }, [reveal]);\n\n const jumpToTool = useCallback((toolUseId: string) => jumpToAnchor(toolAnchorId(toolUseId)), [jumpToAnchor]);\n\n const jumpToFirstError = useCallback(() => {\n const anchor = model.errorAnchors[0];\n if (anchor) jumpToAnchor(anchor);\n }, [model.errorAnchors, jumpToAnchor]);\n\n const stepMatch = useCallback((delta: number) => {\n if (matches.length === 0) return;\n const next = matchIndex < 0\n ? (delta > 0 ? 0 : matches.length - 1)\n : (matchIndex + delta + matches.length) % matches.length;\n setMatchIndex(next);\n jumpToTurn(matches[next]!.turnKey);\n }, [matches, matchIndex, jumpToTurn]);\n\n useEffect(() => { setMatchIndex(-1); }, [query]);\n\n /** Move focus n turns from whichever turn currently holds it. */\n const stepTurn = useCallback((delta: number) => {\n const turns = model.turns;\n if (turns.length === 0) return;\n const active = scroller.current?.ownerDocument?.activeElement;\n const currentKey = active instanceof HTMLElement ? active.getAttribute('data-turn-key') : null;\n const index = currentKey ? turns.findIndex((t) => t.key === currentKey) : -1;\n const next = index < 0\n ? (delta > 0 ? 0 : turns.length - 1)\n : Math.max(0, Math.min(turns.length - 1, index + delta));\n jumpToTurn(turns[next]!.key);\n }, [model.turns, jumpToTurn]);\n\n // ⌘F focuses the in-chat search; Alt+↑/↓ steps turns from anywhere EXCEPT a\n // text field, where the OS already owns those chords for word/paragraph\n // movement and the composer must keep them.\n useEffect(() => {\n if (model.turns.length === 0) return;\n const onKey = (event: globalThis.KeyboardEvent) => {\n const target = event.target as HTMLElement | null;\n const typing = target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement\n || target?.isContentEditable === true;\n if ((event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey && event.key.toLowerCase() === 'f') {\n if (model.turns.length < NAV_MIN_TURNS) return;\n event.preventDefault();\n setFocusToken((n) => n + 1);\n return;\n }\n if (event.altKey && !event.metaKey && !event.ctrlKey && !typing) {\n if (event.key === 'ArrowDown') { event.preventDefault(); stepTurn(1); }\n else if (event.key === 'ArrowUp') { event.preventDefault(); stepTurn(-1); }\n }\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [model.turns.length, stepTurn]);\n\n /** Plain ↑/↓ once a turn container itself has focus. */\n function onListKeyDown(event: KeyboardEvent<HTMLOListElement>) {\n const target = event.target as HTMLElement | null;\n if (!target?.hasAttribute('data-turn-key')) return;\n if (event.key === 'ArrowDown') { event.preventDefault(); stepTurn(1); }\n else if (event.key === 'ArrowUp') { event.preventDefault(); stepTurn(-1); }\n else if (event.key === 'Home') { event.preventDefault(); jumpToTurn(model.turns[0]!.key); }\n else if (event.key === 'End') { event.preventDefault(); jumpToTurn(model.turns[model.turns.length - 1]!.key); }\n }\n\n // Auto-follow new content only while pinned to the bottom.\n useLayoutEffect(() => {\n const count = transcript.items.length;\n const lastItem = transcript.items[count - 1];\n const grew = count !== lastCount.current || lastItem?.kind === 'assistant' && lastItem.streaming;\n lastCount.current = count;\n if (!grew) return;\n if (following) scrollToBottom();\n else setUnseen(true);\n }, [transcript, following, scrollToBottom]);\n\n useEffect(() => {\n if (loaded) scrollToBottom();\n }, [loaded, scrollToBottom]);\n\n if (!loaded && !loadError) {\n return (\n <div className={styles.transcript} aria-busy=\"true\">\n <div className={styles.skeleton}>\n <div className={styles.skeletonUser}><SkeletonLine width=\"42%\" /></div>\n <SkeletonLine width=\"88%\" /><SkeletonLine width=\"72%\" /><SkeletonLine width=\"80%\" />\n <div className={styles.skeletonUser}><SkeletonLine width=\"30%\" /></div>\n <SkeletonLine width=\"64%\" />\n </div>\n </div>\n );\n }\n\n if (loadError) {\n return (\n <div className={styles.transcript}>\n <div role=\"alert\" className={styles.loadError}>\n <p>{loadError}</p>\n {onRetry ? <button type=\"button\" onClick={onRetry}>Retry</button> : null}\n </div>\n </div>\n );\n }\n\n const activeMatchKey = matchIndex >= 0 ? matches[matchIndex]?.turnKey ?? null : null;\n\n return (\n <div className={styles.transcriptWrap}>\n {model.turns.length >= NAV_MIN_TURNS ? (\n <TranscriptNav turns={model.turns} query={query} onQuery={setQuery} matches={matches} matchIndex={matchIndex}\n onStepMatch={stepMatch} errorCount={model.errorAnchors.length} onJumpError={jumpToFirstError}\n onJumpTurn={jumpToTurn} focusToken={focusToken} />\n ) : null}\n <div ref={scroller} className={styles.transcript} onScroll={onScroll} role=\"log\" aria-live=\"polite\" aria-relevant=\"additions text\">\n {transcript.items.length === 0 ? (\n <div className={styles.empty}>\n <p className={styles.emptyTitle}>Say something to begin.</p>\n <p className={styles.emptyBody}>{emptyHint ?? 'The agent can read and edit this project. Ask for a change, a review, or an explanation.'}</p>\n </div>\n ) : null}\n <ol className={styles.list} onKeyDown={onListKeyDown}>\n {model.turns.map((turn, index) => (\n <li\n key={turn.key}\n id={turnAnchorId(turn.key)}\n ref={(node) => {\n if (node) turnNodes.current.set(turn.key, node);\n else turnNodes.current.delete(turn.key);\n }}\n className={styles.turn}\n data-turn-key={turn.key}\n data-status={turn.status}\n data-match={matchKeys.has(turn.key) ? (turn.key === activeMatchKey ? 'active' : 'true') : undefined}\n tabIndex={-1}\n aria-label={`Turn ${index + 1} of ${model.turns.length}`}\n >\n <ol className={styles.turnItems}>\n {turn.items.map((item) => renderItem(item, model.facts, explained))}\n </ol>\n {turn.files.length > 0 ? <FileActivity files={turn.files} onJump={jumpToTool} /> : null}\n {turn.errorCount > 0 && turn.firstErrorAnchor ? (\n <button type=\"button\" className={styles.turnErrorJump}\n onClick={() => jumpToAnchor(turn.firstErrorAnchor!)}>\n {turn.errorCount} failure{turn.errorCount === 1 ? '' : 's'} in this turn — jump to the first\n </button>\n ) : null}\n </li>\n ))}\n {/* Waiting for the first token: the caret alone. No skeletons mid-stream (DESIGN §5). */}\n {transcript.live && !transcript.items.some((i) => i.kind === 'assistant' && i.streaming) ? (\n <li className={`${styles.item} ${styles.assistant}`} data-kind=\"pending\" aria-label=\"Waiting for the agent\">\n <span className={styles.caret} aria-hidden=\"true\" />\n </li>\n ) : null}\n </ol>\n </div>\n {!following ? (\n <button type=\"button\" className={`${styles.jump} ${unseen ? styles.jumpUnseen : ''}`}\n onClick={() => { setFollowing(true); setUnseen(false); scrollToBottom('smooth'); }}>\n <ArrowDownIcon size={12} /> Jump to latest\n </button>\n ) : null}\n </div>\n );\n}\n\nfunction renderItem(item: TranscriptRenderItem, facts: Map<string, ToolFacts>, explained: Set<string>) {\n switch (item.kind) {\n case 'user':\n return (\n <li key={item.key} className={`${styles.item} ${styles.user}`} data-kind=\"user\">\n <div className={styles.userText}>{item.text}</div>\n </li>\n );\n case 'assistant':\n return (\n <li key={item.key} className={`${styles.item} ${styles.assistant}`} data-kind=\"assistant\" data-streaming={item.streaming || undefined}>\n <MessageMarkdown text={item.text} streaming={item.streaming} />\n </li>\n );\n case 'thinking':\n return (\n <li key={item.key} className={styles.item} data-kind=\"thinking\">\n <ThinkingBlock item={item} />\n </li>\n );\n case 'tool':\n return (\n <li key={item.key} className={styles.item} data-kind=\"tool\">\n <ToolUseCard name={item.name} input={item.input} result={item.result} toolUseId={item.toolUseId}\n durationMs={item.durationMs} facts={facts.get(item.toolUseId)} />\n </li>\n );\n case 'toolGroup':\n return (\n <li key={item.key} className={styles.item} data-kind=\"tool-group\">\n <ToolGroup item={item} facts={facts} />\n </li>\n );\n case 'error':\n return (\n <li key={item.key} className={styles.item} data-kind=\"error\">\n <div id={noteAnchorId(item.key)} role=\"alert\" className={`${styles.note} ${styles.noteError}`}>{item.message}</div>\n </li>\n );\n case 'cancelled':\n return (\n <li key={item.key} className={styles.item} data-kind=\"cancelled\">\n <div className={styles.note}>Stopped.</div>\n </li>\n );\n case 'turn-done':\n if (item.ok || explained.has(item.key)) {\n return item.durationMs > 0 ? (\n <li key={item.key} className={`${styles.item} ${styles.meta}`} data-kind=\"turn-done\">\n <span className={styles.metaText}>{formatDuration(item.durationMs)}</span>\n </li>\n ) : null;\n }\n return (\n <li key={item.key} className={styles.item} data-kind=\"turn-done\">\n <div id={noteAnchorId(item.key)} className={`${styles.note} ${styles.noteError}`}>Turn ended without a result (<span className={styles.noteDuration}>{formatDuration(item.durationMs)}</span>).</div>\n </li>\n );\n default:\n return null;\n }\n}\n\nfunction ThinkingBlock({ item }: { item: Extract<ToolGroupMember, { kind: 'thinking' }> }) {\n return (\n <details className={styles.thinking} data-state-key={`thinking:${item.key}`}>\n <summary className={styles.thinkingSummary}>Thinking</summary>\n <div className={styles.thinkingBody}>{item.text}</div>\n </details>\n );\n}\n\n/**\n * The folded run: `6 tools · Read ×4, Edit ×2 · 12s`. Failures tint the left\n * rule and say so in words — never the colour on its own (DESIGN §6).\n */\nfunction ToolGroup({ item, facts }: { item: ToolGroupItem; facts: Map<string, ToolFacts> }) {\n const state = item.pending\n ? 'running'\n : item.errorCount > 0\n ? `${item.errorCount} failed`\n : item.spanMs !== null && item.spanMs > 0\n ? formatDuration(item.spanMs)\n : 'done';\n const label = `${item.toolCount} tool${item.toolCount === 1 ? '' : 's'}`;\n return (\n <details className={`${styles.toolRun} ${item.errorCount > 0 ? styles.toolFailed : ''}`} data-state-key={`toolgroup:${item.key}`}>\n <summary className={styles.toolLine} aria-label={`${label}: ${item.summary} (${state})`}>\n <span className={styles.toolGlyph} aria-hidden=\"true\" />\n <span className={styles.toolName}>{label}</span>\n {item.summary ? <span className={styles.toolArg} title={item.summary}>{item.summary}</span> : null}\n <span className={styles.toolState}>{state}</span>\n </summary>\n <div className={styles.toolRunBody}>\n <ol className={styles.toolRunList}>\n {item.items.map((member) => (\n <li key={member.key} data-member={member.kind}>\n {member.kind === 'tool'\n ? <ToolUseCard name={member.name} input={member.input} result={member.result}\n toolUseId={member.toolUseId} durationMs={member.durationMs} facts={facts.get(member.toolUseId)} />\n : <ThinkingBlock item={member} />}\n </li>\n ))}\n </ol>\n </div>\n </details>\n );\n}\n","/**\n * routes/verse/useSeatsRefresh.ts — keep the seat roster live.\n *\n * THE BUG THIS CLOSES. `GET /api/verse/bootstrap` carries the seats, and it\n * has NO entry in sse.ts's `EVENT_TO_CACHE_KEYS`: nothing on the server can\n * push a new reading into it. It is re-read only on mount and after a write\n * (`invalidateVerseLists`). The account collector, meanwhile, needs roughly a\n * cycle and a half — about 75 seconds measured — before its first readings\n * exist. Open the app cold, as Mason does, and the one read that ever happens\n * lands BEFORE any reading exists. Every seat then shows \"unknown\" for the\n * rest of the session, on the surface he looks at all day, and no amount of\n * correct rendering downstream can fix that.\n *\n * So the chat surfaces poll. The cost is a cached JSON read, not a probe: the\n * collector spawns its processes on its own 30s cycle regardless of whether\n * anyone asks, and this only picks up what it already published. Owner S's\n * V2.1 bootstrap handler recomputes seat telemetry on every read\n * (`liveSeats` in core/verse/verse-api.ts), so a poll of this key genuinely\n * returns the collector's CURRENT state rather than a warm cache.\n *\n * WHY BOOTSTRAP AND NOT `GET /api/verse/seats`. S added that route precisely\n * to be polled, and it is the cheaper read. But `verse-bootstrap` is the cache\n * key ChatSection already subscribes to and hands down as the `seats` prop to\n * the sidebar, the workspace, the seat selector and the new-chat dialog.\n * Polling it updates all five surfaces with no change to the component that\n * owns them. Moving to `/api/verse/seats` means lifting seats out of the\n * bootstrap prop first; that is a worthwhile follow-up, not a prerequisite.\n *\n * Two deliberate choices:\n *\n * - `useRefetch`, not `useRefresh`. Refetch collapses a burst of ticks (and a\n * tick landing on a read that just started) into ONE request, which is what\n * a poll wants. `useRefresh` never joins, which is what a person pressing a\n * button wants; the panel's own Refresh control uses that.\n * - Nothing is requested while the document is hidden, and a read is issued\n * the moment it becomes visible again. A backgrounded app polls zero times\n * and is nonetheless correct the instant it is looked at.\n */\nimport { useEffect } from 'react';\nimport { useRefetch } from '../../data/hooks.js';\nimport { verseBootstrapQuery } from './verse-queries.js';\n\n/** Matches the collector's own publish cadence; there is nothing to gain from faster. */\nexport const SEATS_POLL_MS = 30_000;\n\nexport function useSeatsRefresh(active = true): void {\n const refetch = useRefetch(verseBootstrapQuery);\n useEffect(() => {\n if (!active) return;\n const tick = (): void => {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return;\n refetch();\n };\n const timer = window.setInterval(tick, SEATS_POLL_MS);\n document.addEventListener('visibilitychange', tick);\n return () => {\n window.clearInterval(timer);\n document.removeEventListener('visibilitychange', tick);\n };\n }, [active, refetch]);\n}\n","/**\n * routes/verse/Workspace.tsx — the chat pane: a --strip-height header with a\n * hairline bottom border and ghost controls only, the 2px context line\n * directly beneath it, the 720px transcript column, and the composer docked\n * at the bottom on the same measure.\n *\n * THE HEADER READS LEFT TO RIGHT, in the order a person asks the questions:\n *\n * [ project ] [ seat · model ] …… [ meter ] [ delete ] │ [ ⬓ ⬔ ]\n * [ Chat title ]\n *\n * 1. WHERE AM I — a two-line lockup: the project above, the chat title\n * below. It is the only thing in the strip allowed to shrink, and both\n * of its lines ellipsise, so neither a 200-character title nor a deep\n * project path can shove the actions off the end.\n * 2. WHAT IS IT RUNNING ON — the seat pill, which is now seat · model ONLY.\n * The project moved up into the lockup rather than being said twice.\n * 3. WHAT CAN I DO — stream state, context numbers and the destructive\n * action, then a hairline, then the two pane toggles as a matched pair.\n *\n * With nothing selected the strip is NOT empty: the lockup says \"Chat / No\n * chat selected\", so the header still answers \"where am I\" — which the old\n * strip left as a bare band with one icon floating at the right edge.\n *\n * Two capacity responsibilities live here because this component is mounted\n * for the whole life of the Chat section, selected chat or not:\n *\n * - IT OWNS THE SEAT POLL. `/api/verse/bootstrap` carries the seats and has\n * no SSE invalidation, while the account collector needs ~75s to warm; a\n * mount-time snapshot is therefore guaranteed to be the COLD one. See\n * useSeatsRefresh for the full reasoning.\n * - The header's seat pill carries the seat's capacity when it is tight or\n * spent. Quietly: a healthy seat adds nothing to the strip, because a\n * badge that is always there is a badge nobody reads.\n */\nimport { useEffect, useId, useRef, useState, type KeyboardEvent, type ReactNode } from 'react';\nimport type { VerseProject, VerseSeat } from '../../data/api-types.js';\nimport { Composer } from './Composer.js';\nimport { ContextMeter } from './ContextMeter.js';\nimport type { SeatChoice } from './SeatSelector.js';\nimport { Transcript } from './Transcript.js';\nimport { PanelIcon, SidebarIcon, TrashIcon, VerseMark } from './verse-icons.js';\nimport { CapacityChip } from './SeatCapacity.js';\nimport { seatSubscription, seatSubscriptionSentence, worthFlagging } from './seat-subscription.js';\nimport { contextWindowFor, projectName, seatById, seatPillLabel } from './verse-model.js';\nimport { useSeatsRefresh } from './useSeatsRefresh.js';\nimport type { VerseSessionView } from './useVerseSession.js';\nimport styles from './Workspace.module.css';\n\nexport interface WorkspaceProps {\n view: VerseSessionView;\n seats: readonly VerseSeat[];\n projects: readonly VerseProject[];\n dispatchEnabled: boolean;\n locked: boolean;\n hasAnySessions: boolean;\n onSend: (text: string) => Promise<boolean>;\n onStop: () => void;\n onRename: (title: string) => Promise<boolean>;\n onDelete: () => Promise<boolean>;\n onSeatChange: (choice: SeatChoice) => void;\n onNew: () => void;\n onRetry: () => void;\n sidebarCollapsed: boolean;\n onToggleSidebar: () => void;\n resourcesOpen: boolean;\n onToggleResources: () => void;\n}\n\nexport function Workspace(props: WorkspaceProps) {\n const { view, seats, projects, dispatchEnabled, locked, hasAnySessions, onSend, onStop, onRename, onDelete,\n onSeatChange, onNew, onRetry, sidebarCollapsed, onToggleSidebar, resourcesOpen, onToggleResources } = props;\n const session = view.session;\n const [editing, setEditing] = useState(false);\n const [draftTitle, setDraftTitle] = useState('');\n const [confirmDelete, setConfirmDelete] = useState(false);\n const [busy, setBusy] = useState(false);\n const titleInput = useRef<HTMLInputElement>(null);\n const headingId = useId();\n\n // Mounted for the whole life of the section, so the roster stays live even\n // with the resources panel hidden.\n useSeatsRefresh();\n\n useEffect(() => {\n setEditing(false);\n setConfirmDelete(false);\n }, [view.sessionId]);\n\n useEffect(() => {\n if (editing) titleInput.current?.select();\n }, [editing]);\n\n /**\n * The two pane toggles — always both rendered, always adjacent, so they\n * read as one control for \"which panes are open\" rather than as whichever\n * of them happens to apply right now.\n */\n const toggles = (\n <div className={styles.toggles} role=\"group\" aria-label=\"Panels\">\n <SidebarToggle collapsed={sidebarCollapsed} onToggle={onToggleSidebar} />\n <ResourcesToggle open={resourcesOpen} onToggle={onToggleResources} />\n </div>\n );\n\n if (!view.sessionId) {\n return (\n <section className={styles.workspace} aria-label=\"Chat\">\n <header className={styles.header} data-app-region=\"drag\">\n <Lockup\n eyebrow={<span className={styles.eyebrow}>Chat</span>}\n title={\n <span className={styles.titleStatic} data-state=\"empty\">\n {hasAnySessions ? 'No chat selected' : 'No chats yet'}\n </span>\n }\n />\n <div className={styles.headerSpacer} />\n <div className={styles.actions}>{toggles}</div>\n </header>\n <div className={styles.emptyState}>\n <span className={styles.emptyMark} aria-hidden=\"true\"><VerseMark size={36} /></span>\n <h1 className={styles.emptyTitle}>{hasAnySessions ? 'Pick a chat, or start a new one' : 'No chats yet — ⌘N'}</h1>\n <p className={styles.emptyBody}>\n Open a project, choose a seat — a Claude or Codex account, Grok, or a local Ollama model — and talk to an agent that can edit that project.\n </p>\n <button type=\"button\" className={styles.emptyButton} onClick={onNew}>New chat <kbd>⌘N</kbd></button>\n {!dispatchEnabled ? (\n <p className={styles.emptyWarn} role=\"status\">\n This server was started without dispatch, so chats are read-only here. Run <code>ashlr verse</code> to enable sending.\n </p>\n ) : null}\n </div>\n </section>\n );\n }\n\n async function commitTitle() {\n const next = draftTitle.trim();\n setEditing(false);\n if (!session || !next || next === session.title) return;\n setBusy(true);\n try {\n await onRename(next);\n } finally {\n setBusy(false);\n }\n }\n\n function onTitleKey(event: KeyboardEvent<HTMLInputElement>) {\n if (event.key === 'Enter') {\n event.preventDefault();\n void commitTitle();\n } else if (event.key === 'Escape') {\n event.preventDefault();\n setEditing(false);\n }\n }\n\n const running = session?.status === 'running';\n const contextWindow = session ? contextWindowFor(seats, session) : null;\n const activeSeat = session ? seatById(seats, session.seatId) ?? null : null;\n const capacity = activeSeat === null ? null : seatSubscription(activeSeat);\n // The pill's tooltip is the whole story — seat, plan, verdict, evidence,\n // reset, credits — so the strip itself can stay to one short chip.\n const seatTitle = session === null\n ? ''\n : `${activeSeat === null || capacity === null\n ? seatPillLabel(seats, session)\n : seatSubscriptionSentence(activeSeat, capacity)} · ${session.projectPath}`;\n const disabledReason = !dispatchEnabled ? 'Sending is disabled: this server was started without dispatch.' : null;\n\n return (\n <section className={styles.workspace} aria-labelledby={headingId}>\n <header className={styles.header} data-app-region=\"drag\">\n <Lockup\n eyebrow={session ? (\n // The full path is the tooltip; the strip shows the short name,\n // because a deep path is exactly what used to eat the title.\n <span className={styles.eyebrow} title={session.projectPath}>{projectName(session.projectPath, projects)}</span>\n ) : (\n <span className={`${styles.eyebrow} skeleton ${styles.eyebrowSkeleton}`} aria-hidden=\"true\" />\n )}\n title={session ? (\n editing ? (\n <input ref={titleInput} className={styles.titleInput} value={draftTitle} aria-label=\"Chat title\"\n onChange={(event) => setDraftTitle(event.target.value)} onBlur={() => { void commitTitle(); }}\n onKeyDown={onTitleKey} maxLength={120} />\n ) : (\n <h1 id={headingId} className={styles.title}>\n <button type=\"button\" className={styles.titleButton} title=\"Rename chat\" disabled={busy || !dispatchEnabled}\n onClick={() => { setDraftTitle(session.title); setEditing(true); }}>\n {session.title || 'Untitled chat'}\n </button>\n </h1>\n )\n ) : (\n // The skeleton takes .titleStatic, not .title: .title carries the\n // optical pull-back that only the INSET BUTTON needs, and a grey\n // bar hanging --space-2 into the gutter is just a misalignment.\n <h1 id={headingId} className={`${styles.titleStatic} skeleton ${styles.titleSkeleton}`} aria-label=\"Loading chat\" />\n )}\n />\n\n {session ? (\n <span className={`${styles.seatPill} ${styles[`engine-${session.engine}`] ?? ''}`} data-engine={session.engine}\n data-seat-capacity={capacity !== null && worthFlagging(capacity.cls) ? capacity.cls : undefined}\n title={seatTitle}>\n <span className={styles.engineDot} aria-hidden=\"true\" />\n <span className={styles.seatText}>{seatPillLabel(seats, session)}</span>\n {/* Only when it changes the decision. A chip on every chat is noise. */}\n {capacity !== null && worthFlagging(capacity.cls)\n ? <CapacityChip view={capacity} />\n : null}\n </span>\n ) : null}\n\n <div className={styles.headerSpacer} />\n\n {/* One cluster, and it never shrinks: the lockup truncates instead, so\n the actions can never be pushed past the strip's right edge. */}\n <div className={styles.actions}>\n {view.stream === 'reconnecting' ? <span className={styles.streamState} role=\"status\">reconnecting…</span> : null}\n {session ? <ContextMeter contextTokens={session.usage.contextTokens} contextWindow={contextWindow} /> : null}\n\n {session ? (\n confirmDelete ? (\n <span className={styles.confirm} role=\"group\" aria-label=\"Confirm delete\">\n <span className={styles.confirmText}>Delete this chat?</span>\n <button type=\"button\" className={styles.danger} disabled={busy} onClick={async () => {\n setBusy(true);\n try {\n const ok = await onDelete();\n if (!ok) setConfirmDelete(false);\n } finally {\n setBusy(false);\n }\n }}>Delete</button>\n <button type=\"button\" className={styles.ghost} onClick={() => setConfirmDelete(false)}>Keep</button>\n </span>\n ) : (\n <button type=\"button\" className={styles.ghostIcon} onClick={() => setConfirmDelete(true)}\n disabled={!dispatchEnabled || running} aria-label=\"Delete chat\"\n title={running ? 'Stop the turn before deleting' : 'Delete chat'}>\n <TrashIcon />\n </button>\n )\n ) : null}\n\n <span className={styles.actionDivider} aria-hidden=\"true\" />\n {toggles}\n </div>\n </header>\n\n <Transcript transcript={view.transcript} loaded={view.loaded} loadError={view.loadError} onRetry={onRetry} />\n\n {session ? (\n <Composer key={session.id} sessionId={session.id} seats={seats} seat={{ seatId: session.seatId, model: session.model }}\n engine={session.engine} running={running} disabled={!dispatchEnabled} disabledReason={disabledReason} locked={locked}\n hintSeen={session.turnCount > 0} contextTokens={session.usage.contextTokens} contextWindow={contextWindow}\n onSend={onSend} onStop={onStop} onSeatChange={onSeatChange} autoFocus />\n ) : null}\n </section>\n );\n}\n\n/**\n * The identity lockup — context over name, one column, and the only flex item\n * in the strip that is allowed to give up width.\n */\nfunction Lockup({ eyebrow, title }: { eyebrow: ReactNode; title: ReactNode }) {\n return (\n <div className={styles.identity}>\n {eyebrow}\n {title}\n </div>\n );\n}\n\n/**\n * Pane toggles. Both are `aria-pressed` buttons, so the open/closed state is\n * spoken rather than implied by a name that changes under you.\n *\n * The collapsed name stays \"Show chat list\" — that is the contract the Chat\n * section's own tests drive — while the expanded one is \"Chat list\" and NOT\n * \"Hide chat list\", because the sidebar already owns a button by that exact\n * name and two controls sharing one accessible name is an ambiguity, not a\n * pair. The action itself is in the tooltip in both states.\n */\nfunction SidebarToggle({ collapsed, onToggle }: { collapsed: boolean; onToggle: () => void }) {\n return (\n <button type=\"button\" className={styles.ghostIcon} onClick={onToggle} aria-pressed={!collapsed}\n title={collapsed ? 'Show chat list' : 'Hide chat list'} aria-label={collapsed ? 'Show chat list' : 'Chat list'}>\n <SidebarIcon />\n </button>\n );\n}\n\nfunction ResourcesToggle({ open, onToggle }: { open: boolean; onToggle: () => void }) {\n return (\n <button type=\"button\" className={styles.ghostIcon} onClick={onToggle} aria-pressed={open}\n title={open ? 'Hide resources' : 'Show resources'} aria-label=\"Resources\">\n <PanelIcon />\n </button>\n );\n}\n","/**\n * Chat section layout: sidebar · handle · workspace · (handle · resources).\n * Both side panels drag-resize and persist (chat-panel-sizing.ts); at 900px\n * the resources panel collapses first, at 760px the sidebar becomes an\n * overlay.\n *\n * THE GRID TRACKS MATCH THE ITEMS THAT ACTUALLY EXIST. A hidden panel renders\n * no handle at all rather than a stranded one, and `display:none` takes an\n * element out of grid placement entirely — so every template below is\n * written for the exact item list that state produces. Getting this wrong is\n * silent: items shift one track left and the transcript lands in a 1px\n * column. `.scrim` never counts (display:none, then absolutely positioned).\n */\n.chat {\n position: relative;\n display: grid;\n /* nav · handle · main · handle · aside */\n grid-template-columns:\n var(--verse-sidebar-width, 264px)\n 1px\n minmax(0, 1fr)\n 1px\n var(--verse-resources-width, 320px);\n flex: 1;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n background: var(--bg-canvas);\n color: var(--text-primary);\n}\n/* nav · handle · main */\n.chat[data-resources='closed'] {\n grid-template-columns: var(--verse-sidebar-width, 264px) 1px minmax(0, 1fr);\n}\n/* main · handle · aside — the collapsed nav and its handle are both gone. */\n.chat[data-sidebar='collapsed'] {\n grid-template-columns: minmax(0, 1fr) 1px var(--verse-resources-width, 320px);\n}\n/* main */\n.chat[data-sidebar='collapsed'][data-resources='closed'] { grid-template-columns: minmax(0, 1fr); }\n.chat[data-sidebar='collapsed'] > nav { display: none; }\n.chat > * { min-width: 0; min-height: 0; }\n\n.main {\n display: flex;\n flex-direction: column;\n min-height: 0;\n min-width: 0;\n background: var(--bg-surface);\n}\n.main:focus { outline: none; }\n\n/* ---- banners ----------------------------------------------------------- */\n.banner,\n.bannerWarn {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--space-3);\n padding: var(--space-2) var(--space-5);\n font-size: var(--text-sm-size);\n line-height: var(--text-sm-line);\n border-bottom: 1px solid var(--border-subtle);\n}\n.banner { background: var(--status-danger-bg); color: var(--status-danger-fg); }\n.bannerWarn { background: var(--status-warning-bg); color: var(--status-warning-fg); }\n.bannerWarn code { font-size: var(--text-xs-size); }\n.banner button {\n flex-shrink: 0;\n min-height: var(--control-h-sm);\n padding: 0 var(--space-3);\n border: 1px solid var(--border-default);\n border-radius: var(--radius-sm);\n background: var(--bg-surface);\n color: var(--text-primary);\n font-size: var(--text-xs-size);\n font-weight: var(--font-weight-medium);\n}\n.banner button {\n transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);\n}\n.banner button:hover { background: var(--bg-hover); border-color: var(--border-strong); }\n.banner button:active { background: var(--bg-active); }\n\n/* ---- resize handles ---------------------------------------------------- */\n/* A 1px column that behaves like a 9px target: the hairline is the design,\n the hit area is the ergonomics.\n\n THE HAIRLINE ITSELF TAKES NO POINTER EVENTS — only the ::before grab area\n does. That is what lets the grab area start BELOW the macOS title bar:\n the top 48px of the panels either side is the window's drag strip\n (Sidebar `.headDragStrip`, Workspace `.header[data-app-region=\"drag\"]`),\n this handle paints after them, and a ±4px overhang there would both steal\n 4px of draggable window edge and turn macOS's double-click-to-zoom into a\n width reset. `--app-titlebar-height` is absent in a browser, so the grab\n area is full height there and nothing changes. */\n.resize {\n position: relative;\n pointer-events: none;\n cursor: col-resize;\n background: var(--border-subtle);\n touch-action: none;\n transition: background var(--duration-fast) var(--ease-standard);\n}\n.resize::before {\n content: '';\n position: absolute;\n top: var(--app-titlebar-height, 0px);\n bottom: 0;\n left: -4px;\n right: -4px;\n pointer-events: auto;\n}\n.resize:hover,\n.resize:focus-visible,\n.resize[data-dragging] { background: var(--accent-500); }\n/* Focus is a wider bar rather than a ring: a 1px element cannot carry one. */\n.resize:focus-visible { outline: none; box-shadow: 0 0 0 1px var(--accent-500); }\n\n/* The drag must not select the transcript it is dragging past. Scoped to the\n flag ChatResizer sets for the duration of the gesture, and released on\n pointerup, pointercancel, blur, Escape and unmount alike. */\n:global(body[data-verse-resizing='true']) {\n user-select: none;\n -webkit-user-select: none;\n cursor: col-resize;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .resize { transition: none; }\n}\n\n/* ---- narrow-width sidebar overlay -------------------------------------- */\n.scrim { display: none; }\n\n/* The resources panel goes first: the transcript keeps the sidebar longer\n than it keeps reference material. Its handle goes with it — see the grid\n comment at the top; these templates are the item lists these rules leave. */\n@media (max-width: 900px) {\n .chat,\n .chat[data-resources='open'] { grid-template-columns: var(--verse-sidebar-width, 264px) 1px minmax(0, 1fr); }\n .chat[data-sidebar='collapsed'],\n .chat[data-sidebar='collapsed'][data-resources='open'] { grid-template-columns: minmax(0, 1fr); }\n .chat > aside,\n .chat > [data-verse-resizer='resources'] { display: none; }\n}\n\n/* Phone width: the sidebar floats over the transcript, so there is no edge\n left to drag and every handle goes. */\n@media (max-width: 760px) {\n .chat,\n .chat[data-sidebar='collapsed'] { grid-template-columns: minmax(0, 1fr); }\n .chat > nav {\n position: absolute;\n z-index: var(--z-overlay);\n inset-block: 0;\n left: 0;\n width: min(var(--verse-sidebar-width, 264px), 86vw);\n box-shadow: var(--shadow-menu, var(--shadow-lg));\n }\n .chat > [data-verse-resizer] { display: none; }\n .scrim {\n display: block;\n position: absolute;\n inset: 0;\n z-index: calc(var(--z-overlay) - 1);\n background: var(--bg-overlay);\n cursor: default;\n }\n .chat[data-sidebar='collapsed'] .scrim { display: none; }\n}\n","/**\n * routes/verse/sections/ChatSection.tsx — the Chat section of the Verse\n * shell: sidebar · workspace (720px transcript + docked composer) ·\n * resources panel, plus the new-chat dialog, the ⌘K switcher, and every\n * mutation the chat surface makes.\n *\n * Takes NO props (VERSE-CONTRACT-V2 shell contract): the shell lazily\n * mounts it and hands over ⌘N / ⌘K as one-shot commands through\n * verse-ui-store, because only this section knows which chat is open and\n * therefore what those shortcuts should pre-fill.\n *\n * Mutations go through one guard: if no mutation token is held,\n * MutationTokenDialog opens and the action re-runs once unlocked (the same\n * hand-off the command palette uses).\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, type CSSProperties } from 'react';\nimport type { VerseCreateSessionRequest, VerseSession } from '../../../data/api-types.js';\nimport { MutationTokenDialog } from '../../../components/auth/MutationTokenDialog.js';\nimport { useToast } from '../../../components/primitives/Toast.js';\nimport { clearReadSession } from '../../../data/auth-store.js';\nimport { ApiError, DispatchDisabledError } from '../../../data/client.js';\nimport { useMutationHold, useQuery, useRefresh } from '../../../data/hooks.js';\nimport { NewChatDialog } from '../NewChatDialog.js';\nimport { QuickSwitcher } from '../QuickSwitcher.js';\nimport { ResourcesPanel } from '../ResourcesPanel.js';\nimport type { SeatChoice } from '../SeatSelector.js';\nimport { Sidebar } from '../Sidebar.js';\nimport { useVerseSession } from '../useVerseSession.js';\nimport { useVerseUi } from '../useVerseUi.js';\nimport { openVerseListChannel } from '../verse-events.js';\nimport {\n cancelVerseTurn,\n createVerseSession,\n deleteVerseSession,\n renameVerseSession,\n sendVerseTurn,\n verseBootstrapQuery,\n verseSessionsQuery,\n verseWorkspacesQuery,\n VerseMutationLockedError,\n} from '../verse-queries.js';\nimport {\n clearVerseCommand,\n lastVerseSeat,\n rememberVerseSeat,\n setVerseResourcesOpen,\n setVerseSidebarCollapsed,\n} from '../verse-ui-store.js';\n// Panel widths are NOT in verse-ui-store: `ashlr.verse.ui.v2` is the shell\n// contract, and a resizable width is a pair (chosen / afforded) that key\n// cannot hold. Same precedent as resources-collapse.ts — its own module,\n// its own key. See chat-panel-sizing.ts.\nimport { ChatResizer, useChatPanelSizing } from '../ChatResizer.js';\nimport { setChatPanelFit } from '../chat-panel-sizing.js';\nimport { forgetComposerMemory } from '../chat/composer-state.js';\nimport { forgetVerseSession, setVerseSession, setVerseSessionStatus } from '../verse-store.js';\nimport { Workspace } from '../Workspace.js';\nimport styles from './ChatSection.module.css';\n\nconst SELECTED_KEY = 'ashlr.verse.selected.v1';\n\nfunction loadSelected(): string | null {\n try {\n return localStorage.getItem(SELECTED_KEY);\n } catch {\n return null;\n }\n}\n\nfunction describeError(err: unknown): string {\n if (err instanceof DispatchDisabledError) return 'This server was started without dispatch — run `ashlr verse` to chat.';\n if (err instanceof ApiError) {\n if (err.status === 409) return 'A turn is already running in this chat. Stop it first.';\n if (err.status === 413) return 'That message is too large (64 KB max).';\n if (err.status === 401) return 'Mutation token was rejected. Unlock again with the token ashlr verse printed.';\n return err.message;\n }\n return err instanceof Error ? err.message : 'Something went wrong.';\n}\n\nexport function ChatSection() {\n const bootstrap = useQuery(verseBootstrapQuery);\n const sessionsQuery = useQuery(verseSessionsQuery);\n const refetchSessions = useRefresh(verseSessionsQuery);\n const refetchBootstrap = useRefresh(verseBootstrapQuery);\n const hold = useMutationHold();\n const toast = useToast();\n const ui = useVerseUi();\n\n const [selectedId, setSelectedIdState] = useState<string | null>(loadSelected);\n const [query, setQuery] = useState('');\n const [newChat, setNewChat] = useState<{ open: boolean; projectPath?: string | null; seat?: SeatChoice | null }>({ open: false });\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n const [switcherOpen, setSwitcherOpen] = useState(false);\n const [reload, setReload] = useState(0);\n const [tokenPrompt, setTokenPrompt] = useState<{ open: boolean; reason: string }>({ open: false, reason: '' });\n const pendingAction = useRef<{ run: () => void; cancel: () => void } | null>(null);\n const chatRef = useRef<HTMLDivElement>(null);\n const panels = useChatPanelSizing();\n\n const seats = useMemo(() => bootstrap.data?.seats ?? [], [bootstrap.data]);\n const projects = useMemo(() => bootstrap.data?.projects ?? [], [bootstrap.data]);\n // Workspaces come from their own route, not bootstrap: the dialog wants the\n // live per-root status alongside the list, and bootstrap's key set is a\n // frozen contract asserted by test/verse-api.test.ts.\n const workspacesQuery = useQuery(verseWorkspacesQuery);\n const workspaces = useMemo(() => workspacesQuery.data?.workspaces ?? [], [workspacesQuery.data]);\n const dispatchEnabled = bootstrap.data?.dispatchEnabled ?? true;\n\n const view = useVerseSession(selectedId, reload);\n\n // Sidebar list: the sessions query, else bootstrap's copy, with the live\n // store record overlaid for the open chat so its running dot is immediate.\n const sessions = useMemo<VerseSession[]>(() => {\n const base = sessionsQuery.data ?? bootstrap.data?.sessions ?? [];\n if (!view.session) return base;\n const live = view.session;\n return base.some((s) => s.id === live.id) ? base.map((s) => (s.id === live.id ? live : s)) : [live, ...base];\n }, [sessionsQuery.data, bootstrap.data, view.session]);\n\n const setSelectedId = useCallback((id: string | null) => {\n setSelectedIdState(id);\n try {\n if (id) localStorage.setItem(SELECTED_KEY, id);\n else localStorage.removeItem(SELECTED_KEY);\n } catch {\n /* best-effort */\n }\n }, []);\n\n // A remembered selection that no longer exists (deleted elsewhere) is dropped once the list is known.\n useEffect(() => {\n if (!selectedId || !sessionsQuery.data) return;\n if (!sessionsQuery.data.some((s) => s.id === selectedId) && !view.session) setSelectedId(null);\n }, [selectedId, sessionsQuery.data, view.session, setSelectedId]);\n\n // Sidebar digest channel (verse-sessions on /api/events).\n useEffect(() => openVerseListChannel(), []);\n\n // ---- mutation guard -----------------------------------------------------\n // Runs `action` now when a token is held; otherwise opens the token dialog\n // and runs it once unlocked. Resolves null when the dialog is dismissed.\n const withToken = useCallback(<T,>(reason: string, action: () => Promise<T>): Promise<T | null> => {\n if (hold.hasHold) return action();\n return new Promise<T | null>((resolve) => {\n pendingAction.current = {\n run: () => { void action().then(resolve); },\n cancel: () => resolve(null),\n };\n setTokenPrompt({ open: true, reason });\n });\n }, [hold.hasHold]);\n\n const fail = useCallback((err: unknown) => {\n if (err instanceof VerseMutationLockedError) return;\n toast.show(describeError(err), 'danger');\n }, [toast]);\n\n // ---- actions ------------------------------------------------------------\n /**\n * ONE resolution of what \"new chat\" pre-fills, for every entry point.\n *\n * The sidebar \"+\", ⌘N, the empty-state button and the quick switcher all\n * land here, so they cannot drift apart again: an explicit prefill wins, the\n * open session is next, and the per-project seat memory is the floor. Only\n * when nothing has ever been started does it fall through to the dialog's\n * `defaultSeatChoice()` — which walks ENGINE_ORDER and lands on Claude, the\n * scarcest account, picked by alphabet rather than intent.\n */\n const openNewChat = useCallback((prefill: { projectPath?: string | null; seat?: SeatChoice | null } = {}) => {\n setCreateError(null);\n const current = view.session;\n const projectPath = prefill.projectPath !== undefined\n ? prefill.projectPath\n : current?.projectPath ?? null;\n // The open session's seat only carries forward onto its OWN project;\n // switching projects asks that project's memory instead.\n const fromCurrent = current && projectPath === current.projectPath\n ? { seatId: current.seatId, model: current.model }\n : null;\n const seat = prefill.seat ?? fromCurrent ?? lastVerseSeat(projectPath);\n setNewChat({ open: true, projectPath, seat });\n }, [view.session]);\n\n const create = useCallback(async (req: VerseCreateSessionRequest) => {\n await withToken('Starting a chat spawns an agent process for this project.', async () => {\n setCreating(true);\n setCreateError(null);\n try {\n const session = await createVerseSession(req);\n // Remember what this project was actually started on, so the NEXT new\n // chat here opens on it instead of resetting to the default engine.\n rememberVerseSeat(session.projectPath, { seatId: session.seatId, model: session.model });\n setVerseSession(session.id, session);\n setNewChat({ open: false });\n setSelectedId(session.id);\n toast.show(`Started “${session.title}”`, 'success');\n } catch (err) {\n setCreateError(describeError(err));\n } finally {\n setCreating(false);\n }\n });\n }, [withToken, setSelectedId, toast]);\n\n const send = useCallback(async (text: string) => {\n const id = selectedId;\n if (!id) return false;\n const result = await withToken('Sending a message runs the agent against this project.', async () => {\n setVerseSessionStatus(id, 'running');\n try {\n const response = await sendVerseTurn(id, text);\n // The turn may already have settled (spawn failure, fast vendor error)\n // by the time the 202 is applied; the store checks the log for this\n // turnId before trusting the `running` snapshot.\n setVerseSession(id, response.session, response.turnId);\n return true;\n } catch (err) {\n setVerseSessionStatus(id, 'idle');\n fail(err);\n return false;\n }\n });\n return result === true;\n }, [selectedId, withToken, fail]);\n\n const stop = useCallback((id: string | null = selectedId) => {\n if (!id) return;\n void withToken('Stopping the running turn.', async () => {\n try {\n await cancelVerseTurn(id);\n } catch (err) {\n fail(err);\n }\n });\n }, [selectedId, withToken, fail]);\n\n const rename = useCallback(async (title: string) => {\n const id = selectedId;\n if (!id) return false;\n const result = await withToken('Renaming a chat.', async () => {\n try {\n const session = await renameVerseSession(id, title);\n setVerseSession(id, session);\n return true;\n } catch (err) {\n fail(err);\n return false;\n }\n });\n return result === true;\n }, [selectedId, withToken, fail]);\n\n const remove = useCallback(async () => {\n const id = selectedId;\n if (!id) return false;\n const result = await withToken('Deleting a chat removes its transcript from disk.', async () => {\n try {\n await deleteVerseSession(id);\n forgetVerseSession(id);\n // The transcript is gone from disk; the verbatim prompts must not\n // survive it in browser storage under a dead session id.\n forgetComposerMemory(id);\n setSelectedId(null);\n toast.show('Chat deleted.', 'neutral');\n return true;\n } catch (err) {\n fail(err);\n return false;\n }\n });\n return result === true;\n }, [selectedId, withToken, fail, setSelectedId, toast]);\n\n /** Sessions are seat-bound: a different seat means a new chat on the same project. */\n const changeSeat = useCallback((choice: SeatChoice) => {\n const current = view.session;\n if (!current) return;\n openNewChat({ projectPath: current.projectPath, seat: choice });\n toast.show('Chats are bound to one seat — starting a new chat on the same project.', 'neutral');\n }, [view.session, openNewChat, toast]);\n\n // ---- shell commands (⌘N / ⌘K) -------------------------------------------\n // The rail owns the shortcuts; this section owns what they mean. Each\n // command is consumed once, by nonce, then cleared.\n const handledCommand = useRef(0);\n useEffect(() => {\n const command = ui.command;\n if (!command || command.nonce === handledCommand.current) return;\n handledCommand.current = command.nonce;\n if (command.name === 'quick-switcher') setSwitcherOpen(true);\n // ⌘N and the sidebar \"+\" both call this with no prefill: openNewChat owns\n // the resolution, so the two affordances cannot mean different things.\n else openNewChat();\n clearVerseCommand();\n }, [ui.command, view.session, openNewChat]);\n\n const dispatchOff = bootstrap.data ? !bootstrap.data.dispatchEnabled : false;\n const resourcesOpen = ui.resourcesOpen;\n const sidebarCollapsed = ui.sidebarCollapsed;\n\n // ---- fit ----------------------------------------------------------------\n // Tell the sizing store how much room the grid actually has, so a width\n // chosen on a 1900px display cannot strand the transcript at 1100px. This\n // never persists: the chosen width is remembered, the afforded width is\n // recomputed, so widening the window gives the panel its size back.\n useEffect(() => {\n const node = chatRef.current;\n if (!node) return undefined;\n const measure = () => setChatPanelFit({\n containerWidth: node.clientWidth,\n sidebarVisible: !sidebarCollapsed,\n resourcesVisible: resourcesOpen,\n });\n measure();\n // ResizeObserver also catches the rail expanding, which moves this grid's\n // width without a window resize. The listener is the fallback where it is\n // missing (jsdom), where clientWidth is 0 and fitting is skipped anyway.\n const observer = typeof ResizeObserver === 'function' ? new ResizeObserver(measure) : null;\n observer?.observe(node);\n window.addEventListener('resize', measure);\n return () => {\n observer?.disconnect();\n window.removeEventListener('resize', measure);\n };\n }, [sidebarCollapsed, resourcesOpen]);\n\n const style = {\n '--verse-sidebar-width': `${panels.effective.sidebar}px`,\n '--verse-resources-width': `${panels.effective.resources}px`,\n } as CSSProperties;\n\n return (\n <div ref={chatRef} className={styles.chat} style={style}\n data-sidebar={sidebarCollapsed ? 'collapsed' : 'open'} data-resources={resourcesOpen ? 'open' : 'closed'}>\n <Sidebar sessions={sessions} sessionsStatus={sessionsQuery.status} sessionsError={sessionsQuery.error?.message ?? null}\n projects={projects} seats={seats} selectedId={selectedId} query={query} onQuery={setQuery}\n onSelect={(id) => { setSelectedId(id); if (window.matchMedia?.('(max-width: 760px)')?.matches === true) setVerseSidebarCollapsed(true); }}\n // Identical to ⌘N by construction: both hand the decision to\n // openNewChat, which carries the open session's seat forward and, when\n // there is no open session, falls back to this project's remembered\n // seat rather than to defaultSeatChoice's alphabetical Claude.\n onNew={() => openNewChat()}\n onRetry={() => { refetchSessions(); refetchBootstrap(); }}\n onCollapse={() => setVerseSidebarCollapsed(true)} onDisconnect={() => { void clearReadSession(); }} />\n {/* A hidden panel leaves no handle behind — and the grid templates in\n ChatSection.module.css are written for exactly these item lists. */}\n {sidebarCollapsed ? null : <ChatResizer side=\"sidebar\" label=\"Resize chat list\" className={styles.resize} />}\n {/* At phone width the sidebar floats over the transcript; the scrim dismisses it. */}\n <button type=\"button\" className={styles.scrim} aria-label=\"Close chat list\" tabIndex={-1}\n onClick={() => setVerseSidebarCollapsed(true)} />\n <div className={styles.main}>\n {bootstrap.status === 'error' && !bootstrap.data ? (\n <div role=\"alert\" className={styles.banner}>\n <span>{bootstrap.error?.message ?? 'Could not load Verse.'}</span>\n <button type=\"button\" onClick={refetchBootstrap}>Retry</button>\n </div>\n ) : dispatchOff ? (\n <div role=\"status\" className={styles.bannerWarn}>\n Read-only: this server was started without dispatch. Run <code>ashlr verse</code> to send messages.\n </div>\n ) : null}\n <Workspace view={view} seats={seats} projects={projects} dispatchEnabled={dispatchEnabled} locked={!hold.hasHold}\n hasAnySessions={sessions.length > 0} onSend={send} onStop={() => stop()} onRename={rename} onDelete={remove}\n onSeatChange={changeSeat} onNew={() => openNewChat()} onRetry={() => setReload((n) => n + 1)}\n sidebarCollapsed={sidebarCollapsed} onToggleSidebar={() => setVerseSidebarCollapsed(!sidebarCollapsed)}\n resourcesOpen={resourcesOpen} onToggleResources={() => setVerseResourcesOpen(!resourcesOpen)} />\n </div>\n {resourcesOpen ? (\n <>\n <ChatResizer side=\"resources\" label=\"Resize resources panel\" className={styles.resize} />\n <ResourcesPanel bootstrap={bootstrap.data} sessions={sessions} current={view.session} onStop={(id) => stop(id)}\n onOpen={setSelectedId} onClose={() => setVerseResourcesOpen(false)} />\n </>\n ) : null}\n\n <NewChatDialog open={newChat.open} onClose={() => setNewChat({ open: false })} projects={projects} seats={seats} workspaces={workspaces}\n initialProjectPath={newChat.projectPath ?? null} initialSeat={newChat.seat ?? null} busy={creating} error={createError} onCreate={create} />\n <QuickSwitcher open={switcherOpen} onClose={() => setSwitcherOpen(false)} sessions={sessions} seats={seats} projects={projects}\n onSelectSession={setSelectedId} onNewChat={(seat) => openNewChat({ projectPath: view.session?.projectPath ?? null, seat })} />\n <MutationTokenDialog open={tokenPrompt.open} reason={tokenPrompt.reason} tokenLabel=\"Mutation token\"\n tokenHelp=\"the mutation token ashlr verse printed\"\n onClose={() => {\n setTokenPrompt({ open: false, reason: '' });\n // The dialog calls onClose before onUnlocked on submit, so only treat\n // this as a dismissal if nothing has claimed the pending action by\n // the next tick.\n const pending = pendingAction.current;\n if (!pending) return;\n setTimeout(() => {\n if (pendingAction.current === pending) {\n pendingAction.current = null;\n pending.cancel();\n }\n }, 0);\n }}\n onUnlocked={() => {\n const pending = pendingAction.current;\n pendingAction.current = null;\n pending?.run();\n }} />\n </div>\n );\n}\n"],"x_google_ignoreList":[36,37],"mappings":"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"}