openplanr 3.4.0 → 3.5.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 (336) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/cli/commands/design.d.ts +3 -0
  3. package/dist/cli/commands/design.d.ts.map +1 -0
  4. package/dist/cli/commands/design.js +137 -0
  5. package/dist/cli/commands/design.js.map +1 -0
  6. package/dist/cli/commands/groups/operations.d.ts.map +1 -1
  7. package/dist/cli/commands/groups/operations.js +2 -0
  8. package/dist/cli/commands/groups/operations.js.map +1 -1
  9. package/dist/dashboard/.vite/manifest.json +1 -1
  10. package/dist/dashboard/assets/{index-CvQAlBy3.js → index-B-l_941W.js} +2 -2
  11. package/dist/dashboard/assets/{index-CvQAlBy3.js.map → index-B-l_941W.js.map} +1 -1
  12. package/dist/dashboard/dashboard-manifest.json +13 -13
  13. package/dist/dashboard/index.html +1 -1
  14. package/dist/services/design-artifact-service.d.ts +22 -0
  15. package/dist/services/design-artifact-service.d.ts.map +1 -1
  16. package/dist/services/design-artifact-service.js +76 -16
  17. package/dist/services/design-artifact-service.js.map +1 -1
  18. package/dist/services/runtime-manager/runtime-package.js +1 -1
  19. package/dist/services/runtime-manager/runtime-package.js.map +1 -1
  20. package/docs/CLI.md +29 -0
  21. package/lib/host-packages/adapter-registry.json +5 -5
  22. package/lib/host-packages/capability-map.json +1 -1
  23. package/lib/host-packages/claude/.claude-plugin/marketplace.json +2 -2
  24. package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +1 -1
  25. package/lib/host-packages/claude/openplanr/.openplanr-content.json +24 -340
  26. package/lib/host-packages/claude/openplanr/README.md +8 -8
  27. package/lib/host-packages/claude/openplanr/skills/artifact/references/design-sharing.md +2 -2
  28. package/lib/host-packages/claude/openplanr/skills/design/SKILL.md +23 -12
  29. package/lib/host-packages/claude/openplanr/skills/design/references/design-system.md +2 -2
  30. package/lib/host-packages/claude/openplanr/skills/design/references/generation.md +3 -3
  31. package/lib/host-packages/claude/openplanr/skills/design/references/hosted-canvas.md +6 -3
  32. package/lib/host-packages/claude/openplanr/skills/design/references/review.md +6 -6
  33. package/lib/host-packages/claude/openplanr/skills/design/references/team-review.md +3 -4
  34. package/lib/host-packages/claude/openplanr/skills/design/references/utilities.md +78 -38
  35. package/lib/host-packages/claude/openplanr/skills/design-loop/SKILL.md +15 -7
  36. package/lib/host-packages/claude/openplanr/skills/design-loop/references/design-system.md +2 -2
  37. package/lib/host-packages/claude/openplanr/skills/design-loop/references/generation.md +3 -3
  38. package/lib/host-packages/claude/openplanr/skills/design-loop/references/review.md +6 -6
  39. package/lib/host-packages/claude/openplanr/skills/design-loop/references/team-review.md +3 -4
  40. package/lib/host-packages/claude/openplanr/skills/design-loop/references/utilities.md +78 -38
  41. package/lib/host-packages/claude/openplanr/skills/design-review/SKILL.md +25 -5
  42. package/lib/host-packages/claude/openplanr/skills/design-review/references/design-system.md +2 -2
  43. package/lib/host-packages/claude/openplanr/skills/design-review/references/generation.md +3 -3
  44. package/lib/host-packages/claude/openplanr/skills/design-review/references/review.md +6 -6
  45. package/lib/host-packages/claude/openplanr/skills/design-review/references/team-review.md +3 -4
  46. package/lib/host-packages/claude/openplanr/skills/design-review/references/utilities.md +78 -38
  47. package/lib/host-packages/claude/openplanr/skills/plan/SKILL.md +7 -3
  48. package/lib/host-packages/cursor/openplanr/.openplanr-content.json +23 -339
  49. package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
  50. package/lib/host-packages/cursor/openplanr/rules/planr-artifact/references/design-sharing.md +2 -2
  51. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/design-system.md +2 -2
  52. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/generation.md +3 -3
  53. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/hosted-canvas.md +6 -3
  54. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/review.md +6 -6
  55. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/team-review.md +3 -4
  56. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/utilities.md +78 -38
  57. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/design-system.md +2 -2
  58. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/generation.md +3 -3
  59. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/review.md +6 -6
  60. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/team-review.md +3 -4
  61. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/utilities.md +78 -38
  62. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop.mdc +15 -7
  63. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/design-system.md +2 -2
  64. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/generation.md +3 -3
  65. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/review.md +6 -6
  66. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/team-review.md +3 -4
  67. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/utilities.md +78 -38
  68. package/lib/host-packages/cursor/openplanr/rules/planr-design-review.mdc +25 -5
  69. package/lib/host-packages/cursor/openplanr/rules/planr-design.mdc +23 -12
  70. package/lib/host-packages/cursor/openplanr/rules/planr-plan.mdc +7 -3
  71. package/lib/host-packages/openai/.claude-plugin/marketplace.json +2 -2
  72. package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +1 -1
  73. package/lib/host-packages/openai/openplanr/.openplanr-content.json +27 -343
  74. package/lib/host-packages/openai/openplanr/skills/artifact/references/design-sharing.md +2 -2
  75. package/lib/host-packages/openai/openplanr/skills/design/SKILL.md +23 -12
  76. package/lib/host-packages/openai/openplanr/skills/design/openplanr.skill.json +0 -11
  77. package/lib/host-packages/openai/openplanr/skills/design/references/design-system.md +2 -2
  78. package/lib/host-packages/openai/openplanr/skills/design/references/generation.md +3 -3
  79. package/lib/host-packages/openai/openplanr/skills/design/references/hosted-canvas.md +6 -3
  80. package/lib/host-packages/openai/openplanr/skills/design/references/review.md +6 -6
  81. package/lib/host-packages/openai/openplanr/skills/design/references/team-review.md +3 -4
  82. package/lib/host-packages/openai/openplanr/skills/design/references/utilities.md +78 -38
  83. package/lib/host-packages/openai/openplanr/skills/design-loop/SKILL.md +15 -7
  84. package/lib/host-packages/openai/openplanr/skills/design-loop/openplanr.skill.json +0 -11
  85. package/lib/host-packages/openai/openplanr/skills/design-loop/references/design-system.md +2 -2
  86. package/lib/host-packages/openai/openplanr/skills/design-loop/references/generation.md +3 -3
  87. package/lib/host-packages/openai/openplanr/skills/design-loop/references/review.md +6 -6
  88. package/lib/host-packages/openai/openplanr/skills/design-loop/references/team-review.md +3 -4
  89. package/lib/host-packages/openai/openplanr/skills/design-loop/references/utilities.md +78 -38
  90. package/lib/host-packages/openai/openplanr/skills/design-review/SKILL.md +25 -5
  91. package/lib/host-packages/openai/openplanr/skills/design-review/openplanr.skill.json +0 -11
  92. package/lib/host-packages/openai/openplanr/skills/design-review/references/design-system.md +2 -2
  93. package/lib/host-packages/openai/openplanr/skills/design-review/references/generation.md +3 -3
  94. package/lib/host-packages/openai/openplanr/skills/design-review/references/review.md +6 -6
  95. package/lib/host-packages/openai/openplanr/skills/design-review/references/team-review.md +3 -4
  96. package/lib/host-packages/openai/openplanr/skills/design-review/references/utilities.md +78 -38
  97. package/lib/host-packages/openai/openplanr/skills/plan/SKILL.md +7 -3
  98. package/lib/host-packages/openai/openplanr/skills/plan/openplanr.skill.json +0 -11
  99. package/package.json +2 -2
  100. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1772
  101. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  102. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  103. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-handoff.mjs +0 -2370
  104. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  105. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  106. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  107. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-review-state-store.mjs +0 -45
  108. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-review.mjs +0 -3376
  109. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -38
  110. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  111. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +0 -321
  112. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +0 -1652
  113. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-9f6918b0.mjs +0 -1037
  114. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +0 -137
  115. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design.mjs +0 -1500
  116. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2023
  117. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  118. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  119. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -814
  120. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -10
  121. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +0 -2568
  122. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -60
  123. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  124. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  125. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  126. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  127. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -139
  128. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  129. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  130. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  131. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  132. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  133. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  134. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  135. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  136. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  137. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  138. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  139. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  140. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  141. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  142. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  143. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  144. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  145. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  146. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  147. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  148. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  149. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  150. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  151. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -163
  152. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  153. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  154. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  155. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  156. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  157. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  158. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  159. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  160. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  161. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  162. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  163. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  164. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  165. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  166. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  167. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  168. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  169. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  170. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -1232
  171. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design.mjs +0 -2611
  172. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  173. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -163
  174. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  175. package/lib/host-packages/claude/openplanr/skills/design/scripts/design.mjs +0 -12
  176. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design.mjs +0 -12
  177. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design.mjs +0 -12
  178. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design.mjs +0 -12
  179. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design.mjs +0 -12
  180. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design.mjs +0 -12
  181. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design.mjs +0 -12
  182. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design.mjs +0 -12
  183. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1772
  184. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  185. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  186. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-handoff.mjs +0 -2370
  187. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  188. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  189. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  190. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-review-state-store.mjs +0 -45
  191. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-review.mjs +0 -3376
  192. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -38
  193. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  194. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +0 -321
  195. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +0 -1652
  196. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-9f6918b0.mjs +0 -1037
  197. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +0 -137
  198. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design.mjs +0 -1500
  199. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2023
  200. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  201. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  202. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -814
  203. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -10
  204. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +0 -2568
  205. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -60
  206. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  207. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  208. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  209. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  210. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -139
  211. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  212. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  213. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  214. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  215. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  216. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  217. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  218. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  219. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  220. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  221. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  222. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  223. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  224. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  225. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  226. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  227. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  228. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  229. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  230. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  231. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  232. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  233. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  234. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -163
  235. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  236. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  237. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  238. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  239. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  240. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  241. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  242. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  243. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  244. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  245. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  246. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  247. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  248. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  249. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  250. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  251. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  252. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  253. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -1232
  254. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design.mjs +0 -2611
  255. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  256. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -163
  257. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  258. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1772
  259. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  260. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  261. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-handoff.mjs +0 -2370
  262. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  263. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  264. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  265. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-review-state-store.mjs +0 -45
  266. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-review.mjs +0 -3376
  267. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -38
  268. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  269. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +0 -321
  270. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +0 -1652
  271. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-9f6918b0.mjs +0 -1037
  272. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +0 -137
  273. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design.mjs +0 -1500
  274. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2023
  275. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  276. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  277. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -814
  278. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -10
  279. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +0 -2568
  280. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -60
  281. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  282. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  283. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  284. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  285. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -139
  286. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  287. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  288. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  289. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  290. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  291. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  292. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  293. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  294. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  295. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  296. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  297. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  298. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  299. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  300. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  301. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  302. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  303. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  304. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  305. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  306. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  307. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  308. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  309. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -163
  310. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  311. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  312. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  313. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  314. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  315. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  316. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  317. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  318. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  319. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  320. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  321. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  322. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  323. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  324. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  325. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  326. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  327. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  328. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -1232
  329. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design.mjs +0 -2611
  330. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  331. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -163
  332. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  333. package/lib/host-packages/openai/openplanr/skills/design/scripts/design.mjs +0 -12
  334. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design.mjs +0 -12
  335. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design.mjs +0 -12
  336. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design.mjs +0 -12
@@ -1,1772 +0,0 @@
1
- import {
2
- digestArtifactEnvelope,
3
- validateJson
4
- } from "./design-shared-artifact-support-protocol-contracts-9f6918b0.mjs";
5
-
6
- // packages/artifact/lib/artifact/ui/shell.mjs
7
- import { readFileSync as readFileSync2 } from "node:fs";
8
-
9
- // packages/artifact/lib/artifact/internal/escape.mjs
10
- var HTML_ENTITIES = Object.freeze({
11
- "&": "&",
12
- "<": "&lt;",
13
- ">": "&gt;",
14
- '"': "&quot;",
15
- "'": "&#39;"
16
- });
17
- var LINE_SEP = String.fromCharCode(8232);
18
- var PARA_SEP = String.fromCharCode(8233);
19
- var JSON_HTML_ESCAPES = Object.freeze({
20
- "<": "\\u003c",
21
- ">": "\\u003e",
22
- "&": "\\u0026",
23
- [LINE_SEP]: "\\u2028",
24
- [PARA_SEP]: "\\u2029"
25
- });
26
- var JSON_HTML_RE = new RegExp(`[<>&${LINE_SEP}${PARA_SEP}]`, "g");
27
- function escapeHtml(value) {
28
- return String(value ?? "").replace(/[&<>"']/g, (ch) => HTML_ENTITIES[ch]);
29
- }
30
- function embedJson(value) {
31
- return JSON.stringify(value ?? null).replace(JSON_HTML_RE, (ch) => JSON_HTML_ESCAPES[ch]);
32
- }
33
-
34
- // packages/artifact/lib/artifact/ui/annotation-styles.mjs
35
- var ARTIFACT_ANNOTATION_CSS = `.planr-annotation-layer { position: absolute; z-index: 6; inset: 0; }
36
- .planr-shell[data-planr-review-mode="interact"] .planr-annotation-layer { pointer-events: none; }
37
- .planr-shell[data-planr-review-mode="comment"] .planr-annotation-layer { cursor: crosshair; touch-action: none; }
38
- .planr-shell[data-planr-review-mode="comment"] .planr-frame iframe { pointer-events: none; }
39
- .planr-region-selection {
40
- position: absolute;
41
- min-width: 2px;
42
- min-height: 2px;
43
- border: 2px solid var(--planr-color-primary);
44
- border-radius: var(--planr-radius-small);
45
- background: color-mix(in srgb, var(--planr-color-primary) 14%, transparent);
46
- pointer-events: none;
47
- }
48
- .planr-pin {
49
- position: absolute;
50
- z-index: 8;
51
- width: 44px;
52
- height: 44px;
53
- min-width: 44px;
54
- min-height: 44px;
55
- translate: -50% -50%;
56
- display: grid;
57
- place-items: center;
58
- padding: 0;
59
- border: 8px solid transparent;
60
- border-radius: 50%;
61
- background-clip: padding-box;
62
- color: var(--planr-color-on-danger);
63
- cursor: pointer;
64
- pointer-events: auto;
65
- font: 700 10px/1 var(--planr-font-mono);
66
- box-shadow: 0 4px 14px color-mix(in srgb, var(--planr-color-background) 38%, transparent);
67
- }
68
- .planr-pin-fix { background-color: var(--planr-color-danger); }
69
- .planr-pin-improve { background-color: var(--planr-color-primary-strong); color: var(--planr-color-on-improve); }
70
- .planr-pin-question { background-color: var(--planr-color-question); color: var(--planr-color-on-question); }
71
- .planr-pin-resolved, .planr-pin-addressed { background-color: var(--planr-color-resolved); color: var(--planr-color-on-resolved); }
72
- .planr-pin-highlight { animation: planr-pin-highlight 1.2s ease-out; }
73
- @keyframes planr-pin-highlight {
74
- 0%, 35% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--planr-color-primary) 52%, transparent), 0 4px 14px color-mix(in srgb, var(--planr-color-background) 38%, transparent); }
75
- 100% { box-shadow: 0 4px 14px color-mix(in srgb, var(--planr-color-background) 38%, transparent); }
76
- }
77
- .planr-pin-region {
78
- position: absolute;
79
- z-index: 7;
80
- min-width: 2px;
81
- min-height: 2px;
82
- border: 2px solid var(--planr-color-danger);
83
- border-radius: var(--planr-radius-small);
84
- background: color-mix(in srgb, var(--planr-color-danger) 12%, transparent);
85
- pointer-events: none;
86
- }
87
- .planr-pin-region-improve { border-color: var(--planr-color-primary-strong); background: color-mix(in srgb, var(--planr-color-primary-strong) 12%, transparent); }
88
- .planr-pin-region-question { border-color: var(--planr-color-question); background: color-mix(in srgb, var(--planr-color-question) 12%, transparent); }
89
- .planr-pin-region-resolved, .planr-pin-region-addressed { border-color: var(--planr-color-resolved); background: color-mix(in srgb, var(--planr-color-resolved) 10%, transparent); }
90
- .planr-annotation-composer {
91
- position: fixed;
92
- inset: auto;
93
- z-index: 100;
94
- box-sizing: border-box;
95
- width: min(360px, calc(100vw - 24px));
96
- max-height: min(620px, calc(100dvh - 24px));
97
- margin: 0;
98
- overflow: auto;
99
- overscroll-behavior: contain;
100
- translate: none;
101
- transform: none;
102
- padding: 14px;
103
- border: 1px solid var(--planr-color-rule);
104
- border-radius: var(--planr-radius-large);
105
- background: var(--planr-color-panel);
106
- color: var(--planr-color-text);
107
- box-shadow: 0 18px 60px color-mix(in srgb, var(--planr-color-background) 58%, transparent);
108
- cursor: default;
109
- pointer-events: auto;
110
- }
111
- .planr-annotation-composer strong { display: block; margin: 0; font: 650 14px/1.2 var(--planr-font-display); }
112
- .planr-composer-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
113
- .planr-composer-header button { display: grid; place-items: center; flex: 0 0 28px; width: 28px; height: 28px; padding: 0; border: 1px solid transparent; border-radius: var(--planr-radius-small); background: transparent; color: var(--planr-color-text-muted); font: 22px/1 var(--planr-font-body); cursor: pointer; }
114
- .planr-composer-header button:hover { background: var(--planr-color-raised); color: var(--planr-color-text); }
115
- .planr-annotation-composer :focus-visible { outline: 2px solid var(--planr-color-primary); outline-offset: 2px; }
116
- .planr-annotation-composer::backdrop { background: transparent; pointer-events: none; }
117
- .planr-annotation-composer label, .planr-identity label {
118
- display: grid;
119
- gap: 5px;
120
- margin-bottom: 9px;
121
- color: var(--planr-color-text-muted);
122
- font-size: 11px;
123
- }
124
- .planr-annotation-composer input, .planr-annotation-composer textarea, .planr-identity input,
125
- .planr-reply-form textarea {
126
- width: 100%;
127
- padding: 8px 9px;
128
- border: 1px solid var(--planr-color-rule);
129
- border-radius: var(--planr-radius-small);
130
- background: var(--planr-color-chrome);
131
- color: var(--planr-color-text);
132
- }
133
- .planr-annotation-composer textarea { min-height: 84px; resize: vertical; }
134
- .planr-intent-picker { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; margin-bottom: 9px; }
135
- .planr-intent-picker button {
136
- min-height: 30px;
137
- border: 1px solid var(--planr-color-rule);
138
- border-radius: var(--planr-radius-small);
139
- background: transparent;
140
- cursor: pointer;
141
- font-size: 10px;
142
- }
143
- .planr-intent-picker [aria-checked="true"] { border-color: var(--planr-color-primary); background: var(--planr-color-raised); }
144
- .planr-field-error { min-height: 16px; margin: 0; color: var(--planr-color-danger); font-size: 10px; }
145
- .planr-composer-actions { display: flex; justify-content: flex-end; gap: 7px; margin-top: 8px; }
146
- .planr-composer-actions button, .planr-thread button, .planr-reply-form button {
147
- min-height: 30px;
148
- padding: 0 10px;
149
- border: 1px solid var(--planr-color-rule);
150
- border-radius: var(--planr-radius-small);
151
- background: transparent;
152
- cursor: pointer;
153
- font-weight: 700;
154
- }
155
- .planr-composer-actions [type="submit"], .planr-reply-form [type="submit"] { border-color: var(--planr-color-primary); background: var(--planr-color-primary); color: var(--planr-color-background); }
156
- `;
157
- var ARTIFACT_ANNOTATION_MOBILE_CSS = `@media (max-width: 600px) { .planr-annotation-composer input, .planr-annotation-composer textarea, .planr-annotation-composer select { font-size: 16px; } }`;
158
-
159
- // packages/artifact/lib/artifact/ui/presentation.mjs
160
- function resolveArtifactPresentation(value, {
161
- mode,
162
- viewMode = mode ?? "single",
163
- artifactCount = 1
164
- } = {}) {
165
- if (value === "document" || value === "canvas") return value;
166
- return artifactCount > 1 || viewMode === "variants" || viewMode === "split" ? "canvas" : "document";
167
- }
168
-
169
- // packages/artifact/lib/artifact/ui/renderers.mjs
170
- var ARTIFACT_SHELL_STATES = Object.freeze([
171
- "ready",
172
- "empty",
173
- "bundling",
174
- "loading",
175
- "invalid",
176
- "expired",
177
- "decryption-failed",
178
- "unsupported-browser"
179
- ]);
180
- var ARTIFACT_VIEW_MODES = Object.freeze(["single", "variants", "split"]);
181
- var ARTIFACT_REVIEW_MODES = Object.freeze(["interact", "comment"]);
182
- var ARTIFACT_SHELL_THEMES = Object.freeze(["auto", "light", "dark"]);
183
- var ARTIFACT_PRESENTATIONS = Object.freeze(["document", "canvas"]);
184
- var STATUS_COPY = Object.freeze({
185
- empty: Object.freeze({
186
- title: "No artifact content",
187
- detail: "Choose a bundled HTML artifact to begin this review."
188
- }),
189
- bundling: Object.freeze({
190
- title: "Bundling artifact",
191
- detail: "Packaging local scripts, styles, fonts, and images without network access."
192
- }),
193
- loading: Object.freeze({
194
- title: "Loading private review",
195
- detail: "Validating the envelope and frozen artifact viewport."
196
- }),
197
- invalid: Object.freeze({
198
- title: "This review is invalid",
199
- detail: "The artifact envelope could not be decoded or validated."
200
- }),
201
- expired: Object.freeze({
202
- title: "This encrypted review expired",
203
- detail: "Ask the sender for a new immutable review link."
204
- }),
205
- "decryption-failed": Object.freeze({
206
- title: "This key cannot decrypt the review",
207
- detail: "Use the complete link, including its private fragment key."
208
- }),
209
- "unsupported-browser": Object.freeze({
210
- title: "Browser support is required",
211
- detail: "Use a current browser with raw DEFLATE and Web Crypto support."
212
- })
213
- });
214
- var PRIVACY_LABELS = Object.freeze({
215
- local: "Local review",
216
- fragment: "Private fragment",
217
- "encrypted-short": "Encrypted short link"
218
- });
219
- function plainText(value, fallback = "") {
220
- if (typeof value === "string") return value;
221
- if (typeof value === "number" && Number.isFinite(value)) return String(value);
222
- return fallback;
223
- }
224
- function member(value, allowed, fallback) {
225
- return allowed.includes(value) ? value : fallback;
226
- }
227
- function nonNegativeInteger(value, fallback = 0) {
228
- return Number.isInteger(value) && value >= 0 ? value : fallback;
229
- }
230
- function viewportDimension(value, fallback) {
231
- return Number.isInteger(value) && value > 0 && value <= 16384 ? value : fallback;
232
- }
233
- function normalizeArtifact(value, index) {
234
- const artifact = value && typeof value === "object" ? value : {};
235
- const id = plainText(artifact.id, `artifact-${index + 1}`) || `artifact-${index + 1}`;
236
- return Object.freeze({
237
- id,
238
- domId: `planr-artifact-${index + 1}`,
239
- title: plainText(artifact.title, `Artifact ${index + 1}`) || `Artifact ${index + 1}`,
240
- kind: plainText(artifact.kind, "html") || "html",
241
- viewport: Object.freeze({
242
- width: viewportDimension(artifact.viewport?.width, 1440),
243
- height: viewportDimension(artifact.viewport?.height, 900)
244
- }),
245
- colorScheme: member(artifact.colorScheme, ["light", "dark"], "light")
246
- });
247
- }
248
- function normalizeArtifactShellModel(input = {}) {
249
- const source = input && typeof input === "object" ? input : {};
250
- const envelope = source.envelope && typeof source.envelope === "object" ? source.envelope : {};
251
- const viewer = source.viewer && typeof source.viewer === "object" ? source.viewer : envelope.viewer && typeof envelope.viewer === "object" ? envelope.viewer : {};
252
- const shell = source.shell && typeof source.shell === "object" ? source.shell : {};
253
- const artifacts = Object.freeze(
254
- (Array.isArray(envelope.artifacts) ? envelope.artifacts : []).map(normalizeArtifact)
255
- );
256
- const requestedActiveId = plainText(viewer.activeArtifactId);
257
- const activeIndex = Math.max(
258
- 0,
259
- artifacts.findIndex((artifact) => artifact.id === requestedActiveId)
260
- );
261
- const activeArtifact = artifacts[activeIndex] ?? null;
262
- const requestedComparisonId = plainText(viewer.comparisonArtifactId);
263
- let comparisonIndex = artifacts.findIndex(
264
- (artifact, index) => index !== activeIndex && artifact.id === requestedComparisonId
265
- );
266
- if (comparisonIndex < 0 && artifacts.length > 1) comparisonIndex = activeIndex === 0 ? 1 : 0;
267
- const comparisonArtifact = comparisonIndex >= 0 ? artifacts[comparisonIndex] : null;
268
- let viewMode = member(
269
- viewer.mode,
270
- ARTIFACT_VIEW_MODES,
271
- artifacts.length > 1 ? "variants" : "single"
272
- );
273
- if (artifacts.length < 2 && viewMode !== "single") viewMode = "single";
274
- const reviewMode = member(
275
- viewer.reviewMode ?? shell.reviewMode,
276
- ARTIFACT_REVIEW_MODES,
277
- "interact"
278
- );
279
- let status = member(viewer.status ?? shell.status, ARTIFACT_SHELL_STATES, "ready");
280
- if (artifacts.length === 0 && status === "ready") status = "empty";
281
- const privacy = member(shell.privacy, Object.keys(PRIVACY_LABELS), "local");
282
- const theme = member(shell.theme, ARTIFACT_SHELL_THEMES, "auto");
283
- const zoom = Math.min(200, Math.max(25, nonNegativeInteger(shell.zoom, 72)));
284
- const feedbackCount = nonNegativeInteger(shell.feedbackCount, 0);
285
- const presentation = resolveArtifactPresentation(viewer.presentation ?? shell.presentation, {
286
- mode: viewMode,
287
- artifactCount: artifacts.length
288
- });
289
- return Object.freeze({
290
- schemaVersion: "1.0.0",
291
- title: plainText(shell.title, activeArtifact?.title ?? "Artifact review") || "Artifact review",
292
- artifacts,
293
- activeArtifact,
294
- activeIndex,
295
- comparisonArtifact,
296
- comparisonIndex,
297
- viewMode,
298
- reviewMode,
299
- status,
300
- statusCopy: STATUS_COPY[status] ?? null,
301
- privacy,
302
- privacyLabel: PRIVACY_LABELS[privacy],
303
- theme,
304
- zoom,
305
- feedbackCount,
306
- presentation,
307
- railOpen: shell.railOpen === void 0 ? presentation === "canvas" : Boolean(shell.railOpen)
308
- });
309
- }
310
- function activeMetadata(model) {
311
- const artifact = model.activeArtifact;
312
- if (!artifact) return "HTML \xB7 1440\xD7900";
313
- return `${artifact.kind.toUpperCase()} \xB7 ${artifact.viewport.width}\xD7${artifact.viewport.height}`;
314
- }
315
- function renderPlanrMark() {
316
- return '<span class="planr-mark" aria-hidden="true"><svg viewBox="0 0 160 160" focusable="false"><g transform="rotate(-45 80 80)"><path d="M125 50A52 52 0 1 0 125 110" fill="none" stroke="currentColor" stroke-width="12" stroke-linecap="round" stroke-linejoin="round"/><rect x="127" y="71" width="18" height="18" rx="3" fill="currentColor"/></g></svg></span>';
317
- }
318
- function renderArtifactToolbar(model) {
319
- const interact = model.reviewMode === "interact";
320
- const canvas = model.presentation === "canvas";
321
- return `<header class="planr-toolbar">
322
- <div class="planr-brand" aria-label="OpenPlanr">${renderPlanrMark()}<span class="planr-title-block"><strong>${escapeHtml(model.title)}</strong>${canvas ? `<span>${escapeHtml(activeMetadata(model))}</span>` : ""}</span></div>
323
- <span class="planr-privacy" data-privacy="${escapeHtml(model.privacy)}">${escapeHtml(model.privacyLabel)}</span>
324
- ${canvas ? ' <span class="planr-domain-toolbar" data-planr-slot="domain-toolbar" aria-label="Artifact workflow controls"></span>\n' : ""} <span class="planr-toolbar-spacer" aria-hidden="true"></span>
325
- ${canvas ? ` <div class="planr-segment" role="group" aria-label="Viewport controls"><button type="button" data-planr-action="zoom-out" aria-label="Zoom out">\u2212</button><button type="button" data-planr-action="zoom-reset" aria-label="Reset zoom">${model.zoom}%</button><button type="button" data-planr-action="zoom-in" aria-label="Zoom in">+</button></div>
326
- ` : ""} <div class="planr-segment" role="group" aria-label="Review mode"><button type="button" data-planr-mode="interact" data-planr-short-label="I" aria-pressed="${interact}">Interact</button><button type="button" data-planr-mode="comment" data-planr-short-label="C" aria-pressed="${!interact}">Comment</button></div>
327
- ${canvas ? ` <button class="planr-toolbar-action" type="button" data-planr-action="theme" aria-label="Shell theme ${escapeHtml(model.theme)}">${escapeHtml(model.theme)}</button>
328
- ` : ""} <button class="planr-toolbar-action" type="button" data-planr-action="feedback" aria-controls="planr-review-rail" aria-expanded="${model.railOpen}"><span class="planr-feedback-label">Feedback</span> <span class="planr-count">${model.feedbackCount}</span></button>
329
- <button class="planr-toolbar-action planr-share" type="button" data-planr-action="share" aria-haspopup="dialog">Share</button>
330
- </header>`;
331
- }
332
- function actionIcon(name) {
333
- const paths = {
334
- comment: '<path d="M12 20a8 8 0 1 0-7.1-4.3L4 20l4.3-.9A8 8 0 0 0 12 20Z"/><path d="M12 8v8M8 12h8"/>',
335
- comments: '<path d="M20 11.5a7.5 7.5 0 0 1-8 7.5 8.8 8.8 0 0 1-3.2-.6L4 20l1.6-4.1A7.4 7.4 0 0 1 4 11.5a8 8 0 0 1 16 0Z"/><path d="M8.5 11.5h7"/>',
336
- share: '<path d="M12 3v12M7 8l5-5 5 5"/><path d="M5 13v6h14v-6"/>',
337
- more: '<circle cx="5" cy="12" r="1.25"/><circle cx="12" cy="12" r="1.25"/><circle cx="19" cy="12" r="1.25"/>'
338
- };
339
- return `<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">${paths[name]}</svg>`;
340
- }
341
- function commentsLabel(count) {
342
- return `${count} ${count === 1 ? "comment" : "comments"}`;
343
- }
344
- function renderDocumentActionRail(model) {
345
- return `<nav class="planr-floating-actions" aria-label="Review actions">
346
- <button type="button" data-planr-action="add-comment" aria-label="Add comment" aria-keyshortcuts="C" aria-pressed="${model.reviewMode === "comment"}" data-planr-tooltip="Add comment (C)">${actionIcon("comment")}</button>
347
- <button type="button" data-planr-action="feedback" aria-label="${commentsLabel(model.feedbackCount)}" aria-controls="planr-review-rail" aria-expanded="${model.railOpen}" data-planr-tooltip="Comments">${actionIcon("comments")}<span class="planr-count" aria-hidden="true">${model.feedbackCount}</span></button>
348
- <button type="button" data-planr-action="share" aria-label="Share review" aria-haspopup="dialog" data-planr-tooltip="Share">${actionIcon("share")}<span class="planr-action-label">Share</span></button>
349
- <div class="planr-more">
350
- <button type="button" data-planr-action="more" aria-label="More review options" aria-haspopup="menu" aria-expanded="false" data-planr-tooltip="More">${actionIcon("more")}</button>
351
- <div class="planr-more-menu" role="menu" hidden>
352
- <div><strong>Private review</strong><span>${escapeHtml(model.privacyLabel)} \xB7 Encrypted when shared</span></div>
353
- <button type="button" role="menuitem" data-planr-action="sharing-options">Snapshot and sharing options</button>
354
- <div data-planr-slot="room-manager" hidden></div>
355
- </div>
356
- </div>
357
- </nav>`;
358
- }
359
- function renderDocumentCommentsScrim() {
360
- return '<button class="planr-comments-scrim" type="button" data-planr-comments-scrim data-planr-close-feedback aria-label="Close comments" tabindex="-1"></button>';
361
- }
362
- function renderViewButton(mode, model, disabled = false) {
363
- const label = mode[0].toUpperCase() + mode.slice(1);
364
- return `<button type="button" data-planr-view="${mode}" aria-pressed="${model.viewMode === mode}"${disabled ? " disabled" : ""}>${label}</button>`;
365
- }
366
- function renderArtifactVariantControls(model) {
367
- const hasVariants = model.artifacts.length > 1;
368
- const tabs = model.artifacts.map((artifact, index) => {
369
- const selected = index === model.activeIndex;
370
- return `<button type="button" role="tab" id="planr-variant-tab-${index + 1}" aria-controls="${artifact.domId}-panel" aria-selected="${selected}" tabindex="${selected ? 0 : -1}" data-artifact-id="${escapeHtml(artifact.id)}"><span>${String(index + 1).padStart(2, "0")}</span> ${escapeHtml(artifact.title)}</button>`;
371
- }).join("");
372
- return `<div class="planr-stage-controls" role="group" aria-label="Artifact display controls">
373
- <div class="planr-segment planr-view-modes" role="group" aria-label="Artifact view mode">${renderViewButton("single", model)}${renderViewButton("variants", model, !hasVariants)}${renderViewButton("split", model, !hasVariants)}</div>
374
- <div class="planr-variants" role="tablist" aria-label="Artifact variants"${model.viewMode === "single" || !hasVariants ? " hidden" : ""}>${tabs}</div>
375
- </div>`;
376
- }
377
- function visibleArtifactIndexes(model) {
378
- if (model.viewMode === "split" && model.comparisonArtifact) {
379
- return /* @__PURE__ */ new Set([model.activeIndex, model.comparisonIndex]);
380
- }
381
- return new Set(model.activeArtifact ? [model.activeIndex] : []);
382
- }
383
- function renderArtifactPanels(model) {
384
- const visible = visibleArtifactIndexes(model);
385
- const unavailable = model.status !== "ready";
386
- return model.artifacts.map((artifact, index) => {
387
- const hidden = !visible.has(index);
388
- const primary = index === model.activeIndex;
389
- const annotationTabIndex = !hidden && !unavailable && model.reviewMode === "comment" ? 0 : -1;
390
- const frameTabIndex = !hidden && !unavailable && model.reviewMode === "interact" ? 0 : -1;
391
- return `<section class="planr-artifact-panel" id="${artifact.domId}-panel" role="tabpanel" aria-labelledby="planr-variant-tab-${index + 1}" data-artifact-id="${escapeHtml(artifact.id)}" data-artifact-color-scheme="${artifact.colorScheme}" style="--planr-artifact-width:${artifact.viewport.width}px;--planr-artifact-height:${artifact.viewport.height}px" aria-label="${primary ? "Primary" : "Comparison"} artifact: ${escapeHtml(artifact.title)}"${hidden ? " hidden" : ""}>
392
- <span class="planr-frame-label">${String(index + 1).padStart(2, "0")} \xB7 ${escapeHtml(artifact.title)}</span>
393
- <div class="planr-frame"><iframe id="${artifact.domId}" title="${escapeHtml(artifact.title)} artifact" sandbox="allow-scripts" referrerpolicy="no-referrer" tabindex="${frameTabIndex}" data-planr-artifact-frame="${escapeHtml(artifact.id)}"></iframe></div>
394
- <div class="planr-annotation-layer" role="region" aria-label="Annotations for ${escapeHtml(artifact.title)}" aria-disabled="${annotationTabIndex < 0}" tabindex="${annotationTabIndex}" data-coordinate-space="normalized" data-planr-annotation-layer="${escapeHtml(artifact.id)}"></div>
395
- </section>`;
396
- }).join("");
397
- }
398
- function renderArtifactStatus(model) {
399
- const ready = model.status === "ready";
400
- const copy = model.statusCopy ?? { title: "", detail: "" };
401
- return `<div class="planr-stage-status" role="status" aria-live="polite" aria-atomic="true"${ready ? " hidden" : ""}>
402
- <div><strong>${escapeHtml(copy.title)}</strong><p>${escapeHtml(copy.detail)}</p></div>
403
- </div>`;
404
- }
405
- function renderArtifactStage(model) {
406
- const unavailable = model.status !== "ready";
407
- const breadcrumb = model.activeArtifact?.title ?? "Artifact";
408
- return `<main class="planr-stage" aria-label="Artifact review stage">
409
- ${model.presentation === "canvas" ? ` <div class="planr-stage-heading"><span>ARTIFACT / ${escapeHtml(breadcrumb.toUpperCase())}</span><span role="status" aria-live="polite" data-planr-slot="status">${model.reviewMode === "comment" ? "Comment mode" : "Interactions enabled"}</span></div>
410
- ${renderArtifactVariantControls(model)}
411
- ` : ""} <div class="planr-stage-scroll"><div class="planr-stage-surface" style="--planr-shell-zoom:${model.zoom / 100}"${unavailable ? ' inert aria-hidden="true"' : ""}><div class="planr-frame-grid" data-planr-layout="${model.viewMode}">${renderArtifactPanels(model)}</div></div></div>
412
- ${renderArtifactStatus(model)}
413
- </main>`;
414
- }
415
- function renderArtifactRail(model) {
416
- const closed = !model.railOpen;
417
- return `<aside class="planr-review-rail" id="planr-review-rail" aria-label="Review comments"${closed ? ' inert aria-hidden="true"' : ""}>
418
- <header><h2>Review comments</h2><div class="planr-review-header-actions"><div class="planr-review-metrics" aria-label="Review metrics"><span data-planr-metric="open">0 open</span><span class="planr-count" data-planr-metric="total" aria-label="${commentsLabel(model.feedbackCount)}">${model.feedbackCount}</span></div><button class="planr-rail-close" type="button" data-planr-close-feedback aria-label="Close comments">\xD7</button></div></header>
419
- <section class="planr-identity" aria-label="Reviewer identity"><label for="planr-reviewer-name">Your name<input id="planr-reviewer-name" type="text" maxlength="256" autocomplete="name" aria-describedby="planr-identity-status planr-review-error" data-planr-reviewer-name></label><p class="planr-identity-status" id="planr-identity-status" aria-live="polite" data-planr-identity-status>Used to sign your comments.</p><p class="planr-field-error" id="planr-review-error" role="alert" hidden></p></section>
420
- <div class="planr-feedback-slot" data-planr-slot="feedback-rail" role="region" aria-label="Comment threads"><p data-planr-empty-feedback>No comments yet. Choose Add comment, then click or drag on the artifact.</p><div class="planr-thread-list" data-planr-thread-list></div></div>
421
- <section class="planr-domain-rail" data-planr-slot="domain-rail" aria-label="Artifact workflow details" hidden></section>
422
- <section class="planr-decision-slot" data-planr-slot="decision" aria-label="Review decision">
423
- <label for="planr-overall-note">Overall note</label><textarea id="planr-overall-note" maxlength="65536" placeholder="Overall note for the coding agent\u2026" data-planr-overall></textarea>
424
- <div><button type="button" data-planr-decision="approved" aria-pressed="false">Approve</button><button type="button" data-planr-decision="changes_requested" aria-pressed="false">Request changes</button></div>
425
- <p data-planr-slot="decision-status">Decision pending</p>
426
- </section>
427
- </aside>`;
428
- }
429
- function renderArtifactShareDialog() {
430
- return `<div class="planr-dialog-backdrop" data-planr-share-dialog hidden>
431
- <section class="planr-share-dialog" role="dialog" aria-modal="true" aria-labelledby="planr-share-title" aria-describedby="planr-share-description" data-planr-share-phase="idle" data-planr-share-selected="live">
432
- <header><div><h2 id="planr-share-title">Share this review</h2><p id="planr-share-description">Live review is encrypted and collaborative. Snapshot links are immutable alternatives.</p></div><button type="button" class="planr-dialog-close" data-planr-share-close aria-label="Close share dialog">\xD7</button></header>
433
- <div class="planr-share-receipt" role="group" aria-label="Privacy receipt">
434
- <button type="button" class="planr-share-receipt-row is-selected" data-planr-share-transport="live" aria-pressed="true">
435
- <span class="planr-share-receipt-icon" aria-hidden="true">\u25CF</span><span><strong>Live collaborative review</strong><small>Encrypted artifact and comment events are stored until expiry. Anyone with the link can comment.</small></span><span class="planr-share-receipt-size">Default</span>
436
- </button>
437
- <button type="button" class="planr-share-receipt-row" data-planr-share-transport="fragment" aria-pressed="false">
438
- <span class="planr-share-receipt-icon" aria-hidden="true">#</span><span><strong>Private fragment</strong><small>Compressed into the URL. Nothing is uploaded.</small></span><span class="planr-share-receipt-size" data-planr-share-fragment-size>Calculating\u2026</span>
439
- </button>
440
- <button type="button" class="planr-share-receipt-row" data-planr-share-transport="short" aria-pressed="false">
441
- <span class="planr-share-receipt-icon" aria-hidden="true">\u25C7</span><span><strong>Encrypted short link</strong><small>AES-256-GCM ciphertext is stored until expiry; the key stays in this link fragment.</small></span><span class="planr-share-receipt-size" data-planr-share-short-size>Calculating\u2026</span>
442
- </button>
443
- </div>
444
- <p class="planr-share-threshold" data-planr-share-threshold>Live rooms are the default. Private fragments are immutable snapshots through 8,000 characters.</p>
445
- <div class="planr-share-ttl" data-planr-share-ttl-row hidden><label for="planr-share-ttl">Encrypted storage expiry<select id="planr-share-ttl" data-planr-share-ttl><option value="1d">1 day</option><option value="7d" selected>7 days</option><option value="30d">30 days</option></select></label><p>Ciphertext and request metadata are visible to the service until <time data-planr-share-expiry></time>. The decryption key is not uploaded.</p></div>
446
- <aside class="planr-owner-custody" data-planr-share-owner-custody><strong>Owner-verdict custody</strong><p>Download the private owner key first. The key stays in your downloaded file and is never put in a URL, browser storage, log, or server request.</p><p role="status" data-planr-share-owner-custody-status>No room will be created until the private owner key is downloaded successfully.</p></aside>
447
- <section class="planr-share-result" data-planr-share-result hidden aria-label="Share receipt">
448
- <label for="planr-share-url">Reviewer URL \xB7 view and comment</label><div><input id="planr-share-url" data-planr-share-url readonly><button type="button" data-planr-share-copy-url>Copy URL</button></div>
449
- <aside class="planr-live-capability" data-planr-share-owner hidden><strong>Private owner-verdict URL</strong><p>Use this URL with the matching downloaded owner key to approve or request changes.</p><div><input id="planr-share-owner-url" aria-label="Private owner-verdict URL" data-planr-share-owner-url readonly><button type="button" data-planr-share-copy-owner>Copy owner URL</button></div></aside>
450
- <aside class="planr-live-capability" data-planr-share-manage hidden><strong>Private management URL</strong><p>Pause or reopen comments, or delete the room. Management cannot set a verdict.</p><div><input id="planr-share-manage-url" aria-label="Private management URL" data-planr-share-manage-url readonly><button type="button" data-planr-share-copy-manage>Copy manage URL</button></div></aside>
451
- <aside class="planr-deletion-receipt" data-planr-share-deletion hidden><strong>One-time deletion token</strong><p>Store this token now; it cannot be recovered. It is separate from the review URL.</p><code data-planr-share-deletion-token></code><button type="button" data-planr-share-copy-deletion>Copy deletion token</button></aside>
452
- </section>
453
- <p class="planr-share-error" role="alert" data-planr-share-error hidden></p>
454
- <p class="planr-visually-hidden" role="status" aria-live="polite" aria-atomic="true" data-planr-share-status></p>
455
- <footer><button type="button" data-planr-share-cancel>Cancel</button><button type="button" class="planr-share-confirm" data-planr-share-confirm disabled>Download owner key</button></footer>
456
- </section>
457
- </div>`;
458
- }
459
- function renderHostedArtifactViewerSlot() {
460
- return `<section class="planr-hosted-viewer" data-planr-hosted-viewer data-planr-hosted-state="idle" role="status" aria-live="polite" aria-atomic="true" hidden>
461
- <div>${renderPlanrMark()}<strong data-planr-hosted-title></strong><p data-planr-hosted-detail></p><button type="button" data-planr-hosted-retry hidden></button></div>
462
- </section>`;
463
- }
464
- function renderArtifactShellMarkup(model) {
465
- return `<div class="planr-shell" data-planr-presentation="${model.presentation}" data-planr-view="${model.viewMode}" data-planr-review-mode="${model.reviewMode}" data-planr-state="${model.status}" data-planr-rail-open="${model.railOpen}">
466
- ${model.presentation === "canvas" ? renderArtifactToolbar(model) : `${renderDocumentActionRail(model)}
467
- ${renderDocumentCommentsScrim()}`}
468
- <div class="planr-workspace">${renderArtifactStage(model)}${renderArtifactRail(model)}</div>
469
- </div>
470
- <div data-planr-slot="dialogs">${renderArtifactShareDialog()}</div>
471
- ${renderHostedArtifactViewerSlot()}
472
- <div class="planr-visually-hidden" role="status" aria-live="polite" aria-atomic="true" data-planr-slot="review-announcer"></div>`;
473
- }
474
- function renderArtifactShellModelData(model) {
475
- return embedJson(model);
476
- }
477
-
478
- // packages/artifact/lib/artifact/ui/stage-payload.mjs
479
- var PRESENTATIONS = Object.freeze(["document", "canvas"]);
480
- function positiveInteger(value, fallback) {
481
- return Number.isInteger(value) && value > 0 ? value : fallback;
482
- }
483
- function freezeArtifactMetadata(artifact, index) {
484
- if (!artifact || typeof artifact !== "object") {
485
- throw new TypeError(`Artifact ${index + 1} must be an object.`);
486
- }
487
- if (typeof artifact.id !== "string" || artifact.id.length === 0) {
488
- throw new TypeError(`Artifact ${index + 1} requires an id.`);
489
- }
490
- return Object.freeze({
491
- id: artifact.id,
492
- title: typeof artifact.title === "string" && artifact.title.length > 0 ? artifact.title : `Artifact ${index + 1}`,
493
- sha256: typeof artifact.sha256 === "string" ? artifact.sha256 : "",
494
- viewport: Object.freeze({
495
- width: positiveInteger(artifact.viewport?.width, 1440),
496
- height: positiveInteger(artifact.viewport?.height, 900)
497
- }),
498
- colorScheme: ["light", "dark"].includes(artifact.colorScheme) ? artifact.colorScheme : "light"
499
- });
500
- }
501
- function requestedArtifactId(value) {
502
- if (typeof value === "string") return value;
503
- return typeof value?.id === "string" ? value.id : "";
504
- }
505
- function availableId(artifacts, requested, fallback = "") {
506
- return artifacts.some(({ id }) => id === requested) ? requested : fallback;
507
- }
508
- function normalizeViewMode(value, artifactCount) {
509
- if (artifactCount < 2) return "single";
510
- return ["single", "variants", "split"].includes(value) ? value : "variants";
511
- }
512
- function createArtifactStagePayload(envelope = {}, { viewer } = {}) {
513
- const artifacts = Object.freeze(
514
- (Array.isArray(envelope?.artifacts) ? envelope.artifacts : []).map(freezeArtifactMetadata)
515
- );
516
- const sourceViewer = viewer && typeof viewer === "object" ? viewer : envelope?.viewer && typeof envelope.viewer === "object" ? envelope.viewer : {};
517
- const firstId = artifacts[0]?.id ?? "";
518
- const activeArtifactId = availableId(
519
- artifacts,
520
- requestedArtifactId(sourceViewer.activeArtifactId),
521
- firstId
522
- );
523
- const mode = normalizeViewMode(sourceViewer.mode, artifacts.length);
524
- return Object.freeze({
525
- schemaVersion: "1.0.0",
526
- artifacts,
527
- viewer: Object.freeze({
528
- mode,
529
- activeArtifactId,
530
- ...PRESENTATIONS.includes(sourceViewer.presentation) ? { presentation: sourceViewer.presentation } : {}
531
- })
532
- });
533
- }
534
-
535
- // packages/artifact/lib/artifact/ui/tokens.mjs
536
- import { fileURLToPath as __planrAssetFile } from "node:url";
537
- import { readFileSync } from "node:fs";
538
- import { createRequire } from "node:module";
539
-
540
- // packages/artifact/lib/artifact/internal/contrast.mjs
541
- var clamp01 = (x) => x < 0 ? 0 : x > 1 ? 1 : x;
542
- var srgbToLinear = (c) => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
543
- var linearToSrgb = (c) => {
544
- c = clamp01(c);
545
- return c <= 31308e-7 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;
546
- };
547
- function parseHex(s) {
548
- let h = s.replace("#", "").trim();
549
- if (h.length === 3 || h.length === 4)
550
- h = h.split("").map((d) => d + d).join("");
551
- if (h.length !== 6 && h.length !== 8) return null;
552
- const r = parseInt(h.slice(0, 2), 16) / 255;
553
- const g = parseInt(h.slice(2, 4), 16) / 255;
554
- const b = parseInt(h.slice(4, 6), 16) / 255;
555
- return [r, g, b].some(Number.isNaN) ? null : { r, g, b };
556
- }
557
- function parseRgb(s) {
558
- const m = /rgba?\(([^)]+)\)/i.exec(s);
559
- if (!m) return null;
560
- const parts = m[1].split(/[,\s/]+/).filter(Boolean).slice(0, 3);
561
- if (parts.length < 3) return null;
562
- const toUnit = (p) => p.endsWith("%") ? parseFloat(p) / 100 : parseFloat(p) / 255;
563
- const [r, g, b] = parts.map(toUnit);
564
- return [r, g, b].some((x) => !Number.isFinite(x)) ? null : { r: clamp01(r), g: clamp01(g), b: clamp01(b) };
565
- }
566
- function parseOklch(s) {
567
- const m = /oklch\(([^)]+)\)/i.exec(s);
568
- if (!m) return null;
569
- const parts = m[1].split(/[\s/]+/).filter(Boolean);
570
- if (parts.length < 3) return null;
571
- let [L, C, H] = parts;
572
- L = L.endsWith("%") ? parseFloat(L) / 100 : parseFloat(L);
573
- C = parseFloat(C);
574
- H = parseFloat(H);
575
- if (![L, C, H].every(Number.isFinite)) return null;
576
- const h = H * Math.PI / 180;
577
- const a = C * Math.cos(h);
578
- const b2 = C * Math.sin(h);
579
- const l_ = L + 0.3963377774 * a + 0.2158037573 * b2;
580
- const m_ = L - 0.1055613458 * a - 0.0638541728 * b2;
581
- const s_ = L - 0.0894841775 * a - 1.291485548 * b2;
582
- const l = l_ ** 3, mm = m_ ** 3, ss = s_ ** 3;
583
- return {
584
- r: linearToSrgb(4.0767416621 * l - 3.3077115913 * mm + 0.2309699292 * ss),
585
- g: linearToSrgb(-1.2684380046 * l + 2.6097574011 * mm - 0.3413193965 * ss),
586
- b: linearToSrgb(-0.0041960863 * l - 0.7034186147 * mm + 1.707614701 * ss)
587
- };
588
- }
589
- var NAMED = { white: { r: 1, g: 1, b: 1 }, black: { r: 0, g: 0, b: 0 } };
590
- function parseColor(input) {
591
- if (!input || typeof input !== "string") return null;
592
- const s = input.trim().toLowerCase();
593
- if (s.includes("var(") || s.includes("gradient") || ["currentcolor", "transparent", "inherit", "none"].includes(s))
594
- return null;
595
- if (s in NAMED) return NAMED[s];
596
- if (s.startsWith("#")) return parseHex(s);
597
- if (s.startsWith("rgb")) return parseRgb(s);
598
- if (s.startsWith("oklch")) return parseOklch(s);
599
- return null;
600
- }
601
- function relativeLuminance(color) {
602
- if (!color) return null;
603
- const { r, g, b } = color;
604
- return 0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
605
- }
606
- function contrastRatio(a, b) {
607
- const la = relativeLuminance(typeof a === "string" ? parseColor(a) : a);
608
- const lb = relativeLuminance(typeof b === "string" ? parseColor(b) : b);
609
- if (la == null || lb == null) return null;
610
- const hi = Math.max(la, lb), lo = Math.min(la, lb);
611
- return (hi + 0.05) / (lo + 0.05);
612
- }
613
- var AA_NORMAL = 4.5;
614
-
615
- // packages/artifact/lib/artifact/ui/tokens.mjs
616
- var require2 = createRequire(new URL("./runtime/packages/artifact/lib/artifact/ui/tokens.mjs", import.meta.url).href);
617
- var ARTIFACT_THEME_REGISTRY_PATH = __planrAssetFile(new URL("./runtime/packages/protocol/registries/artifact-theme.json", import.meta.url));
618
- var ARTIFACT_THEME_SCHEMA_PATH = __planrAssetFile(new URL("./runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json", import.meta.url));
619
- var ARTIFACT_THEME_ERROR_CODES = Object.freeze({
620
- PARSE: "E_ARTIFACT_THEME_PARSE",
621
- SCHEMA: "E_ARTIFACT_THEME_SCHEMA",
622
- TOKEN_MISSING: "E_ARTIFACT_THEME_TOKEN_MISSING",
623
- TOKEN_UNKNOWN: "E_ARTIFACT_THEME_TOKEN_UNKNOWN",
624
- FORMAT: "E_ARTIFACT_THEME_FORMAT",
625
- LAYOUT: "E_ARTIFACT_THEME_LAYOUT",
626
- MOTION: "E_ARTIFACT_THEME_MOTION",
627
- CONTRAST: "E_ARTIFACT_THEME_CONTRAST"
628
- });
629
- var ArtifactThemeError = class extends Error {
630
- constructor(code, message, details = {}) {
631
- super(message);
632
- this.name = "ArtifactThemeError";
633
- this.code = code;
634
- this.details = details;
635
- }
636
- };
637
- var TYPOGRAPHY_KEYS = Object.freeze(["display", "body", "mono"]);
638
- var LAYOUT_KEYS = Object.freeze([
639
- "toolbarHeight",
640
- "reviewRailWidth",
641
- "radiusSmall",
642
- "radiusMedium",
643
- "radiusLarge",
644
- "motionFastMs",
645
- "motionBaseMs"
646
- ]);
647
- var THEME_NAMES = Object.freeze(["dark", "light"]);
648
- var COLOR_KEYS = Object.freeze([
649
- "background",
650
- "chrome",
651
- "panel",
652
- "raised",
653
- "stage",
654
- "rule",
655
- "text",
656
- "textMuted",
657
- "primary",
658
- "primaryStrong",
659
- "onPrimary",
660
- "warning",
661
- "danger",
662
- "onDanger",
663
- "question",
664
- "onQuestion",
665
- "resolved",
666
- "onResolved",
667
- "onImprove"
668
- ]);
669
- var AA_PAIRS = Object.freeze([
670
- ["text", "background"],
671
- ["text", "chrome"],
672
- ["text", "panel"],
673
- ["text", "raised"],
674
- ["text", "stage"],
675
- ["textMuted", "background"],
676
- ["textMuted", "panel"],
677
- ["primary", "background"],
678
- ["primaryStrong", "background"],
679
- ["onPrimary", "primary"],
680
- ["onPrimary", "primaryStrong"],
681
- ["warning", "background"],
682
- ["danger", "background"],
683
- ["onDanger", "danger"],
684
- ["onQuestion", "question"],
685
- ["onResolved", "resolved"],
686
- ["onImprove", "primaryStrong"]
687
- ]);
688
- function readJson(path, label) {
689
- try {
690
- return JSON.parse(readFileSync(path, "utf8"));
691
- } catch (error) {
692
- throw new ArtifactThemeError(
693
- ARTIFACT_THEME_ERROR_CODES.PARSE,
694
- `Unable to parse ${label}: ${error.message}`,
695
- { path }
696
- );
697
- }
698
- }
699
- function schemaCode(issue) {
700
- if (issue.rule === "required") return ARTIFACT_THEME_ERROR_CODES.TOKEN_MISSING;
701
- if (issue.rule === "additionalProperties") return ARTIFACT_THEME_ERROR_CODES.TOKEN_UNKNOWN;
702
- if (issue.rule === "pattern") return ARTIFACT_THEME_ERROR_CODES.FORMAT;
703
- if (issue.path.includes(".layout.motion")) return ARTIFACT_THEME_ERROR_CODES.MOTION;
704
- if (issue.path.includes(".layout.")) return ARTIFACT_THEME_ERROR_CODES.LAYOUT;
705
- return ARTIFACT_THEME_ERROR_CODES.SCHEMA;
706
- }
707
- function assertSchema(theme, schema) {
708
- const issues = validateJson(theme, schema);
709
- if (issues.length === 0) return;
710
- const first = issues[0];
711
- throw new ArtifactThemeError(
712
- schemaCode(first),
713
- `Invalid artifact theme at ${first.path}: ${first.detail}`,
714
- { issues }
715
- );
716
- }
717
- function assertLayout(layout) {
718
- if (layout.toolbarHeight !== 48 || layout.reviewRailWidth !== 344) {
719
- throw new ArtifactThemeError(
720
- ARTIFACT_THEME_ERROR_CODES.LAYOUT,
721
- "Artifact shell layout must keep a 48px toolbar and 344px review rail.",
722
- { toolbarHeight: layout.toolbarHeight, reviewRailWidth: layout.reviewRailWidth }
723
- );
724
- }
725
- const radii = ["radiusSmall", "radiusMedium", "radiusLarge"].map((key) => [key, layout[key]]);
726
- const invalidRadius = radii.find(
727
- ([, value]) => !Number.isInteger(value) || value < 0 || value > 32
728
- );
729
- if (invalidRadius) {
730
- throw new ArtifactThemeError(
731
- ARTIFACT_THEME_ERROR_CODES.LAYOUT,
732
- `${invalidRadius[0]} must be an integer from 0 through 32.`,
733
- { token: invalidRadius[0], value: invalidRadius[1] }
734
- );
735
- }
736
- if (!(layout.radiusSmall <= layout.radiusMedium && layout.radiusMedium <= layout.radiusLarge)) {
737
- throw new ArtifactThemeError(
738
- ARTIFACT_THEME_ERROR_CODES.LAYOUT,
739
- "Artifact shell radii must be ordered small <= medium <= large.",
740
- { radii: Object.fromEntries(radii) }
741
- );
742
- }
743
- }
744
- function assertMotion(layout) {
745
- for (const token of ["motionFastMs", "motionBaseMs"]) {
746
- const value = layout[token];
747
- if (!Number.isInteger(value) || value < 120 || value > 200) {
748
- throw new ArtifactThemeError(
749
- ARTIFACT_THEME_ERROR_CODES.MOTION,
750
- `${token} must be an integer from 120 through 200 milliseconds.`,
751
- { token, value }
752
- );
753
- }
754
- }
755
- if (layout.motionFastMs > layout.motionBaseMs) {
756
- throw new ArtifactThemeError(
757
- ARTIFACT_THEME_ERROR_CODES.MOTION,
758
- "motionFastMs must not exceed motionBaseMs.",
759
- { motionFastMs: layout.motionFastMs, motionBaseMs: layout.motionBaseMs }
760
- );
761
- }
762
- }
763
- function assertContrast(themes) {
764
- for (const themeName of THEME_NAMES) {
765
- const colors = themes[themeName];
766
- for (const [foreground, background] of AA_PAIRS) {
767
- const ratio = contrastRatio(colors[foreground], colors[background]);
768
- if (ratio == null || ratio < 4.5) {
769
- throw new ArtifactThemeError(
770
- ARTIFACT_THEME_ERROR_CODES.CONTRAST,
771
- `${themeName}.${foreground} on ${themeName}.${background} must meet WCAG AA (4.5:1).`,
772
- { theme: themeName, foreground, background, ratio }
773
- );
774
- }
775
- }
776
- }
777
- }
778
- function validateArtifactTheme(theme, { schema } = {}) {
779
- const contract = schema ?? readJson(ARTIFACT_THEME_SCHEMA_PATH, "artifact theme schema");
780
- assertSchema(theme, contract);
781
- assertLayout(theme.layout);
782
- assertMotion(theme.layout);
783
- assertContrast(theme.themes);
784
- return theme;
785
- }
786
- function pick(source, keys) {
787
- return Object.fromEntries(keys.map((key) => [key, source[key]]));
788
- }
789
- function normalizeArtifactTheme(theme) {
790
- validateArtifactTheme(theme);
791
- return {
792
- kind: theme.kind,
793
- schemaVersion: theme.schemaVersion,
794
- protocolVersion: theme.protocolVersion,
795
- name: theme.name,
796
- typography: pick(theme.typography, TYPOGRAPHY_KEYS),
797
- layout: pick(theme.layout, LAYOUT_KEYS),
798
- themes: Object.fromEntries(
799
- THEME_NAMES.map((themeName) => [themeName, pick(theme.themes[themeName], COLOR_KEYS)])
800
- )
801
- };
802
- }
803
- function loadArtifactTheme({
804
- registryPath = ARTIFACT_THEME_REGISTRY_PATH,
805
- schemaPath = ARTIFACT_THEME_SCHEMA_PATH
806
- } = {}) {
807
- const registry = readJson(registryPath, "artifact theme registry");
808
- const schema = readJson(schemaPath, "artifact theme schema");
809
- validateArtifactTheme(registry, { schema });
810
- return normalizeArtifactTheme(registry);
811
- }
812
- function kebab(value) {
813
- return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
814
- }
815
- function colorVariables(colors) {
816
- return COLOR_KEYS.map((key) => ` --planr-color-${kebab(key)}: ${colors[key]};`).join("\n");
817
- }
818
- function renderArtifactThemeCss(theme) {
819
- const value = normalizeArtifactTheme(theme);
820
- const { typography, layout, themes } = value;
821
- const foundations = [
822
- ` --planr-font-display: "${typography.display}", ui-sans-serif, system-ui, sans-serif;`,
823
- ` --planr-font-body: "${typography.body}", ui-sans-serif, system-ui, sans-serif;`,
824
- ` --planr-font-mono: "${typography.mono}", ui-monospace, SFMono-Regular, Consolas, monospace;`,
825
- ` --planr-toolbar-height: ${layout.toolbarHeight}px;`,
826
- ` --planr-review-rail-width: ${layout.reviewRailWidth}px;`,
827
- ` --planr-radius-small: ${layout.radiusSmall}px;`,
828
- ` --planr-radius-medium: ${layout.radiusMedium}px;`,
829
- ` --planr-radius-large: ${layout.radiusLarge}px;`,
830
- ` --planr-motion-fast: ${layout.motionFastMs}ms;`,
831
- ` --planr-motion-base: ${layout.motionBaseMs}ms;`
832
- ].join("\n");
833
- return [
834
- "/* Generated by scripts/generate-artifact-shell.mjs. Do not edit. */",
835
- ":root,",
836
- '[data-planr-theme="dark"] {',
837
- foundations,
838
- colorVariables(themes.dark),
839
- "}",
840
- "",
841
- '[data-planr-theme="light"] {',
842
- colorVariables(themes.light),
843
- "}",
844
- "",
845
- "@media (prefers-color-scheme: light) {",
846
- " :root:not([data-planr-theme]),",
847
- ' [data-planr-theme="auto"] {',
848
- colorVariables(themes.light).replaceAll(/^/gm, " "),
849
- " }",
850
- "}",
851
- "",
852
- "@media (prefers-reduced-motion: reduce) {",
853
- " :root {",
854
- " --planr-motion-fast: 0ms;",
855
- " --planr-motion-base: 0ms;",
856
- " }",
857
- "}",
858
- ""
859
- ].join("\n");
860
- }
861
-
862
- // packages/artifact/lib/artifact/ui/shell.mjs
863
- var ARTIFACT_SHELL_VERSION = "1.2.1";
864
- var ARTIFACT_SHELL_ASSET_PATHS = Object.freeze({
865
- template: "templates/artifact-review-shell.html",
866
- stageRuntime: "templates/artifact-review-stage.js",
867
- manifest: "lib/artifact/ui/generated/artifact-shell-assets.json",
868
- themeCss: "lib/artifact/ui/generated/artifact-theme.css",
869
- themeJson: "lib/artifact/ui/generated/artifact-theme.json"
870
- });
871
- var ARTIFACT_SHELL_CSS = readFileSync2(new URL("./studio-shell.css", new URL("./runtime/packages/artifact/lib/artifact/ui/shell.mjs", import.meta.url).href), "utf8") + `
872
- * { box-sizing: border-box; }
873
- html, body { width: 100%; height: 100%; margin: 0; }
874
- body {
875
- overflow: hidden;
876
- background: var(--planr-color-background);
877
- color: var(--planr-color-text);
878
- font: 400 13px/1.45 var(--planr-font-body);
879
- -webkit-font-smoothing: antialiased;
880
- }
881
- button, input, select, textarea { font: inherit; }
882
- button { color: inherit; }
883
- button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible,
884
- [tabindex]:focus-visible {
885
- outline: 2px solid var(--planr-color-primary);
886
- outline-offset: 2px;
887
- }
888
- [hidden] { display: none !important; }
889
- .planr-visually-hidden {
890
- position: fixed;
891
- width: 1px;
892
- height: 1px;
893
- overflow: hidden;
894
- clip-path: inset(50%);
895
- white-space: nowrap;
896
- }
897
- .planr-shell {
898
- height: 100%;
899
- display: grid;
900
- grid-template-rows: var(--planr-toolbar-height) minmax(0, 1fr);
901
- background: var(--planr-color-background);
902
- }
903
- .planr-toolbar {
904
- position: relative;
905
- z-index: 40;
906
- min-width: 0;
907
- display: flex;
908
- align-items: center;
909
- gap: 10px;
910
- padding: 0 10px 0 14px;
911
- border-bottom: 1px solid var(--planr-color-rule);
912
- background: color-mix(in srgb, var(--planr-color-chrome) 96%, transparent);
913
- }
914
- .planr-brand { min-width: 0; display: flex; align-items: center; gap: 9px; }
915
- .planr-mark { display: inline-grid; place-items: center; width: 22px; height: 22px; flex: none; color: var(--planr-color-primary); contain: paint; }
916
- .planr-mark svg { display: block; width: 100%; height: 100%; }
917
- .planr-title-block { min-width: 0; display: flex; align-items: baseline; gap: 8px; }
918
- .planr-title-block strong {
919
- max-width: 260px;
920
- overflow: hidden;
921
- color: var(--planr-color-text);
922
- font: 650 13px/1 var(--planr-font-display);
923
- letter-spacing: -.01em;
924
- text-overflow: ellipsis;
925
- white-space: nowrap;
926
- }
927
- .planr-title-block span, .planr-privacy {
928
- color: var(--planr-color-text-muted);
929
- font: 10px/1 var(--planr-font-mono);
930
- white-space: nowrap;
931
- }
932
- .planr-privacy { display: inline-flex; align-items: center; gap: 6px; font-family: var(--planr-font-body); }
933
- .planr-privacy::before {
934
- content: "";
935
- width: 6px;
936
- height: 6px;
937
- border-radius: 50%;
938
- background: var(--planr-color-primary);
939
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--planr-color-primary) 14%, transparent);
940
- }
941
- .planr-toolbar-spacer { flex: 1; }
942
- .planr-room-manager { display: inline-flex; align-items: center; gap: 5px; }
943
- .planr-room-manager button { height: 28px; border: 1px solid var(--planr-color-rule); border-radius: var(--planr-radius-small); background: var(--planr-color-panel); color: var(--planr-color-text-muted); font: 650 10px/1 var(--planr-font-body); padding: 0 8px; }
944
- .planr-room-manager button:last-child { border-color: color-mix(in srgb, var(--planr-color-danger) 55%, var(--planr-color-rule)); color: var(--planr-color-danger); }
945
- .planr-shell[data-planr-room-comments-paused] [data-planr-mode="comment"],
946
- .planr-shell[data-planr-room-comments-paused] [data-planr-action="add-comment"] { cursor: not-allowed; opacity: .48; }
947
- .planr-domain-toolbar { min-width: 0; display: inline-flex; align-items: center; gap: 6px; }
948
- .planr-segment {
949
- height: 30px;
950
- display: inline-flex;
951
- align-items: center;
952
- gap: 2px;
953
- padding: 2px;
954
- border: 1px solid var(--planr-color-rule);
955
- border-radius: var(--planr-radius-medium);
956
- background: var(--planr-color-background);
957
- }
958
- .planr-segment button, .planr-toolbar-action {
959
- height: 24px;
960
- border: 0;
961
- border-radius: var(--planr-radius-small);
962
- background: transparent;
963
- color: var(--planr-color-text-muted);
964
- cursor: pointer;
965
- transition: color var(--planr-motion-fast), background var(--planr-motion-fast), transform var(--planr-motion-fast);
966
- }
967
- .planr-segment button { min-width: 26px; padding: 0 8px; font-size: 11px; font-weight: 650; }
968
- .planr-segment button[aria-pressed="true"] {
969
- background: var(--planr-color-primary);
970
- color: var(--planr-color-background);
971
- }
972
- .planr-segment button:disabled { opacity: .45; cursor: not-allowed; }
973
- .planr-toolbar-action {
974
- height: 30px;
975
- padding: 0 12px;
976
- border: 1px solid var(--planr-color-rule);
977
- color: var(--planr-color-text);
978
- font-weight: 700;
979
- text-transform: capitalize;
980
- }
981
- .planr-toolbar-action:hover, .planr-segment button:not(:disabled):hover { background: var(--planr-color-raised); color: var(--planr-color-text); }
982
- .planr-toolbar-action:active, .planr-segment button:not(:disabled):active { transform: scale(.97); }
983
- .planr-share { border-color: var(--planr-color-primary); background: var(--planr-color-primary); color: var(--planr-color-background); }
984
- .planr-count {
985
- min-width: 18px;
986
- height: 18px;
987
- display: inline-grid;
988
- place-items: center;
989
- padding-inline: 4px;
990
- border-radius: 999px;
991
- background: var(--planr-color-raised);
992
- color: var(--planr-color-text-muted);
993
- font: 10px/1 var(--planr-font-mono);
994
- }
995
- .planr-floating-actions {
996
- position: fixed;
997
- z-index: 45;
998
- top: 50%;
999
- right: max(12px, env(safe-area-inset-right));
1000
- display: flex;
1001
- flex-direction: column;
1002
- gap: 4px;
1003
- padding: 5px;
1004
- border: 1px solid var(--planr-color-rule);
1005
- border-radius: var(--planr-radius-large);
1006
- background: color-mix(in srgb, var(--planr-color-chrome) 94%, transparent);
1007
- box-shadow: 0 12px 36px color-mix(in srgb, var(--planr-color-background) 38%, transparent);
1008
- backdrop-filter: blur(16px);
1009
- transform: translateY(-50%);
1010
- }
1011
- .planr-floating-actions > button,
1012
- .planr-floating-actions > .planr-more > button {
1013
- position: relative;
1014
- width: 40px;
1015
- height: 40px;
1016
- display: grid;
1017
- place-items: center;
1018
- border: 0;
1019
- border-radius: var(--planr-radius-medium);
1020
- background: transparent;
1021
- color: var(--planr-color-text);
1022
- cursor: pointer;
1023
- transition: color var(--planr-motion-fast), background var(--planr-motion-fast), transform var(--planr-motion-fast);
1024
- }
1025
- .planr-floating-actions button:hover,
1026
- .planr-floating-actions button[aria-pressed="true"],
1027
- .planr-floating-actions button[aria-expanded="true"] {
1028
- background: var(--planr-color-raised);
1029
- color: var(--planr-color-primary);
1030
- }
1031
- .planr-floating-actions button:active { transform: scale(.96); }
1032
- .planr-floating-actions button:disabled { cursor: not-allowed; opacity: .48; }
1033
- .planr-floating-actions svg {
1034
- width: 20px;
1035
- height: 20px;
1036
- fill: none;
1037
- stroke: currentColor;
1038
- stroke-linecap: round;
1039
- stroke-linejoin: round;
1040
- stroke-width: 1.8;
1041
- }
1042
- .planr-floating-actions svg circle { fill: currentColor; stroke: none; }
1043
- .planr-floating-actions [data-planr-action="feedback"] .planr-count {
1044
- position: absolute;
1045
- top: 2px;
1046
- right: 1px;
1047
- min-width: 16px;
1048
- height: 16px;
1049
- padding-inline: 3px;
1050
- background: var(--planr-color-primary);
1051
- color: var(--planr-color-background);
1052
- font-size: 9px;
1053
- }
1054
- .planr-floating-actions [data-planr-tooltip]::after {
1055
- content: attr(data-planr-tooltip);
1056
- position: absolute;
1057
- top: 50%;
1058
- right: calc(100% + 10px);
1059
- width: max-content;
1060
- max-width: 220px;
1061
- padding: 6px 8px;
1062
- border-radius: var(--planr-radius-small);
1063
- background: var(--planr-color-text);
1064
- color: var(--planr-color-background);
1065
- font: 650 10px/1.2 var(--planr-font-body);
1066
- opacity: 0;
1067
- pointer-events: none;
1068
- transform: translate(4px, -50%);
1069
- transition: opacity var(--planr-motion-fast), transform var(--planr-motion-fast);
1070
- }
1071
- .planr-floating-actions [data-planr-tooltip]:hover::after,
1072
- .planr-floating-actions [data-planr-tooltip]:focus-visible::after {
1073
- opacity: 1;
1074
- transform: translate(0, -50%);
1075
- }
1076
- .planr-action-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
1077
- .planr-more { position: relative; }
1078
- .planr-more-menu {
1079
- position: absolute;
1080
- right: calc(100% + 10px);
1081
- bottom: 0;
1082
- width: 250px;
1083
- padding: 8px;
1084
- border: 1px solid var(--planr-color-rule);
1085
- border-radius: var(--planr-radius-medium);
1086
- background: var(--planr-color-panel);
1087
- box-shadow: 0 16px 48px color-mix(in srgb, var(--planr-color-background) 42%, transparent);
1088
- }
1089
- .planr-more-menu > div:first-child { display: grid; gap: 2px; padding: 7px 8px 10px; }
1090
- .planr-more-menu strong { font-size: 12px; }
1091
- .planr-more-menu span { color: var(--planr-color-text-muted); font-size: 10px; }
1092
- .planr-more-menu > button {
1093
- width: 100%;
1094
- min-height: 36px;
1095
- padding: 0 8px;
1096
- border: 0;
1097
- border-radius: var(--planr-radius-small);
1098
- background: transparent;
1099
- text-align: left;
1100
- cursor: pointer;
1101
- }
1102
- .planr-more-menu > button:hover { background: var(--planr-color-raised); }
1103
- .planr-comments-scrim {
1104
- position: fixed;
1105
- z-index: 40;
1106
- inset: 0;
1107
- border: 0;
1108
- background: color-mix(in srgb, var(--planr-color-background) 8%, transparent);
1109
- cursor: default;
1110
- opacity: 1;
1111
- transition: opacity var(--planr-motion-fast);
1112
- }
1113
- .planr-shell[data-planr-rail-open="false"] .planr-comments-scrim {
1114
- opacity: 0;
1115
- pointer-events: none;
1116
- }
1117
- .planr-workspace {
1118
- min-width: 0;
1119
- min-height: 0;
1120
- display: grid;
1121
- grid-template-columns: minmax(0, 1fr) var(--planr-review-rail-width);
1122
- transition: grid-template-columns var(--planr-motion-base);
1123
- }
1124
- .planr-shell[data-planr-rail-open="false"] .planr-workspace { grid-template-columns: minmax(0, 1fr) 0; }
1125
- .planr-stage {
1126
- position: relative;
1127
- min-width: 0;
1128
- min-height: 0;
1129
- overflow: hidden;
1130
- background-color: var(--planr-color-stage);
1131
- background-image: radial-gradient(color-mix(in srgb, var(--planr-color-text-muted) 20%, transparent) 1px, transparent 1px);
1132
- background-size: 20px 20px;
1133
- }
1134
- .planr-stage-heading {
1135
- position: absolute;
1136
- z-index: 12;
1137
- inset: 0 0 auto;
1138
- height: 34px;
1139
- display: flex;
1140
- align-items: center;
1141
- justify-content: space-between;
1142
- padding: 0 14px;
1143
- color: var(--planr-color-text-muted);
1144
- font: 10px/1 var(--planr-font-mono);
1145
- pointer-events: none;
1146
- }
1147
- .planr-stage-controls {
1148
- position: absolute;
1149
- z-index: 13;
1150
- inset: 34px 0 auto;
1151
- min-width: 0;
1152
- min-height: 42px;
1153
- display: flex;
1154
- align-items: center;
1155
- gap: 8px;
1156
- padding: 5px 14px 7px;
1157
- background: linear-gradient(var(--planr-color-stage) 72%, transparent);
1158
- }
1159
- .planr-view-modes { flex: none; }
1160
- .planr-variants {
1161
- min-width: 0;
1162
- display: flex;
1163
- align-items: center;
1164
- gap: 5px;
1165
- overflow: auto;
1166
- scrollbar-width: none;
1167
- }
1168
- .planr-variants button {
1169
- flex: none;
1170
- height: 28px;
1171
- max-width: 220px;
1172
- overflow: hidden;
1173
- padding: 0 10px;
1174
- border: 1px solid var(--planr-color-rule);
1175
- border-radius: var(--planr-radius-small);
1176
- background: var(--planr-color-chrome);
1177
- color: var(--planr-color-text-muted);
1178
- cursor: pointer;
1179
- font-size: 10px;
1180
- font-weight: 650;
1181
- text-overflow: ellipsis;
1182
- white-space: nowrap;
1183
- }
1184
- .planr-variants button span { font-family: var(--planr-font-mono); }
1185
- .planr-variants button[aria-selected="true"] { border-color: var(--planr-color-primary); color: var(--planr-color-text); }
1186
- .planr-stage-scroll { position: absolute; inset: 76px 0 0; overflow: auto; padding: 8px 34px 64px; }
1187
- .planr-stage-surface {
1188
- width: max-content;
1189
- min-width: 100%;
1190
- transform: scale(var(--planr-shell-zoom));
1191
- transform-origin: top left;
1192
- transition: transform var(--planr-motion-fast);
1193
- }
1194
- .planr-frame-grid { width: max-content; display: grid; grid-auto-flow: column; grid-auto-columns: max-content; gap: 12px; }
1195
- .planr-frame-grid[data-planr-layout="single"] .planr-frame-label { display: none; }
1196
- .planr-artifact-panel {
1197
- position: relative;
1198
- width: var(--planr-artifact-width);
1199
- height: var(--planr-artifact-height);
1200
- }
1201
- .planr-frame {
1202
- width: 100%;
1203
- height: 100%;
1204
- overflow: hidden;
1205
- border: 0;
1206
- border-radius: var(--planr-radius-medium);
1207
- background: var(--planr-color-chrome);
1208
- box-shadow: inset 0 0 0 1px var(--planr-color-rule), 0 18px 60px color-mix(in srgb, var(--planr-color-background) 52%, transparent);
1209
- }
1210
- .planr-frame iframe { width: 100%; height: 100%; display: block; border: 0; background: var(--planr-color-chrome); }
1211
- .planr-frame-label {
1212
- position: absolute;
1213
- z-index: 4;
1214
- inset: 10px auto auto 10px;
1215
- padding: 5px 7px;
1216
- border-radius: var(--planr-radius-small);
1217
- background: color-mix(in srgb, var(--planr-color-background) 78%, transparent);
1218
- color: var(--planr-color-text);
1219
- font: 9px/1 var(--planr-font-mono);
1220
- pointer-events: none;
1221
- }
1222
- ${ARTIFACT_ANNOTATION_CSS}.planr-stage-status {
1223
- position: absolute;
1224
- z-index: 20;
1225
- inset: 76px 0 0;
1226
- display: grid;
1227
- place-items: center;
1228
- padding: 24px;
1229
- background: color-mix(in srgb, var(--planr-color-stage) 94%, transparent);
1230
- text-align: center;
1231
- }
1232
- .planr-stage-status > div {
1233
- max-width: 400px;
1234
- padding: 24px;
1235
- border: 1px solid var(--planr-color-rule);
1236
- border-radius: var(--planr-radius-large);
1237
- background: var(--planr-color-chrome);
1238
- box-shadow: 0 18px 60px color-mix(in srgb, var(--planr-color-background) 50%, transparent);
1239
- }
1240
- .planr-stage-status strong { display: block; margin-bottom: 7px; font: 650 18px/1.2 var(--planr-font-display); }
1241
- .planr-stage-status p { margin: 0; color: var(--planr-color-text-muted); }
1242
- .planr-review-rail {
1243
- min-width: 0;
1244
- display: grid;
1245
- grid-template-rows: auto auto minmax(0, 1fr) auto;
1246
- overflow: hidden;
1247
- border-left: 1px solid var(--planr-color-rule);
1248
- background: var(--planr-color-panel);
1249
- transition: opacity var(--planr-motion-fast), transform var(--planr-motion-base);
1250
- }
1251
- .planr-domain-rail { max-height: 44vh; overflow: auto; padding: 12px 14px; border-top: 1px solid var(--planr-color-rule); }
1252
- .planr-domain-rail[hidden] { display: none; }
1253
- .planr-domain-rail h3 { margin: 0 0 8px; font: 650 12px/1.2 var(--planr-font-display); }
1254
- .planr-domain-rail details { border-top: 1px solid var(--planr-color-rule); }
1255
- .planr-domain-rail summary { padding: 9px 0; color: var(--planr-color-text); cursor: pointer; font-weight: 700; }
1256
- .planr-domain-section-body { padding: 1px 0 10px; }
1257
- .planr-domain-rail fieldset { margin: 0 0 9px; padding: 9px; border: 1px solid var(--planr-color-rule); border-radius: var(--planr-radius-small); }
1258
- .planr-domain-rail legend { padding: 0 4px; color: var(--planr-color-text); font-size: 11px; font-weight: 700; }
1259
- .planr-domain-rail label { display: grid; gap: 5px; margin-bottom: 8px; color: var(--planr-color-text-muted); font-size: 11px; }
1260
- .planr-domain-rail input, .planr-domain-rail select, .planr-domain-rail textarea {
1261
- width: 100%; border: 1px solid var(--planr-color-rule); border-radius: var(--planr-radius-small);
1262
- background: var(--planr-color-background); color: var(--planr-color-text); padding: 7px 8px;
1263
- }
1264
- .planr-domain-actions { display: flex; flex-wrap: wrap; gap: 6px; }
1265
- .planr-domain-remix { display: grid; grid-template-columns: 1fr 1fr; gap: 0 8px; }
1266
- .planr-domain-remix label:last-child { grid-column: 1 / -1; }
1267
- .planr-domain-section-body > p { margin: 8px 0 0; color: var(--planr-color-text-muted); font-size: 10px; }
1268
- .planr-domain-actions button, .planr-domain-toolbar button {
1269
- min-height: 28px; border: 1px solid var(--planr-color-rule); border-radius: var(--planr-radius-small);
1270
- background: var(--planr-color-raised); color: var(--planr-color-text); padding: 0 9px; cursor: pointer;
1271
- }
1272
- .planr-shell[data-planr-rail-open="false"] .planr-review-rail { opacity: 0; pointer-events: none; }
1273
- .planr-review-rail > header {
1274
- min-height: 48px;
1275
- display: flex;
1276
- align-items: center;
1277
- justify-content: space-between;
1278
- padding: 0 14px;
1279
- border-bottom: 1px solid var(--planr-color-rule);
1280
- }
1281
- .planr-review-rail h2 { margin: 0; font: 650 13px/1 var(--planr-font-display); }
1282
- .planr-review-metrics { display: flex; align-items: center; gap: 6px; }
1283
- .planr-review-header-actions { display: flex; align-items: center; gap: 8px; }
1284
- .planr-rail-close {
1285
- width: 32px;
1286
- height: 32px;
1287
- display: none;
1288
- place-items: center;
1289
- border: 1px solid var(--planr-color-rule);
1290
- border-radius: var(--planr-radius-small);
1291
- background: var(--planr-color-raised);
1292
- color: var(--planr-color-text);
1293
- font: 20px/1 var(--planr-font-body);
1294
- cursor: pointer;
1295
- }
1296
- .planr-identity { padding: 10px 14px 0; border-bottom: 1px solid var(--planr-color-rule); }
1297
- .planr-identity label { margin-bottom: 5px; }
1298
- .planr-identity-status { min-height: 16px; margin: 0 0 8px !important; color: var(--planr-color-text-muted); font-size: 10px !important; }
1299
- .planr-identity-status[data-planr-identity-ready="true"] { color: var(--planr-color-primary); }
1300
- .planr-identity-status[data-planr-identity-ready="true"]::before { margin-right: 4px; content: '\u2713'; font-weight: 800; }
1301
- .planr-feedback-slot { overflow: auto; padding: 14px; }
1302
- .planr-feedback-slot > p {
1303
- margin: 0;
1304
- padding: 18px;
1305
- border: 1px dashed var(--planr-color-rule);
1306
- border-radius: var(--planr-radius-medium);
1307
- color: var(--planr-color-text-muted);
1308
- text-align: center;
1309
- }
1310
- .planr-thread-list { display: grid; gap: 10px; }
1311
- .planr-review-empty {
1312
- margin: 0;
1313
- padding: 18px;
1314
- border: 1px dashed var(--planr-color-rule);
1315
- border-radius: var(--planr-radius-medium);
1316
- color: var(--planr-color-text-muted);
1317
- text-align: center;
1318
- }
1319
- .planr-thread {
1320
- padding: 11px;
1321
- border: 1px solid var(--planr-color-rule);
1322
- border-left: 3px solid var(--planr-color-danger);
1323
- border-radius: var(--planr-radius-medium);
1324
- background: var(--planr-color-chrome);
1325
- }
1326
- .planr-thread[data-planr-intent="improve"] { border-left-color: var(--planr-color-primary-strong); }
1327
- .planr-thread[data-planr-intent="question"] { border-left-color: var(--planr-color-question); }
1328
- .planr-thread[data-planr-status="resolved"], .planr-thread[data-planr-status="addressed"] { border-left-color: var(--planr-color-resolved); opacity: .82; }
1329
- .planr-thread > header { display: flex; align-items: center; gap: 7px; color: var(--planr-color-text-muted); font-size: 10px; }
1330
- .planr-thread > header strong { color: var(--planr-color-text); font-size: 11px; }
1331
- .planr-thread > header time { margin-left: auto; font-family: var(--planr-font-mono); }
1332
- .planr-review-byline { display: flex; align-items: center; gap: 6px; }
1333
- .planr-intent { color: var(--planr-color-text-muted); text-transform: capitalize; }
1334
- .planr-thread-comment { margin: 9px 0; white-space: pre-wrap; overflow-wrap: anywhere; }
1335
- .planr-thread-actions { display: flex; gap: 6px; }
1336
- .planr-thread-actions button { min-height: 28px; padding-inline: 8px; font-size: 10px; }
1337
- .planr-replies { display: grid; gap: 7px; margin: 10px 0 0 12px; padding-left: 10px; border-left: 1px solid var(--planr-color-rule); list-style: none; }
1338
- .planr-reply { margin: 0; }
1339
- .planr-reply header { display: flex; gap: 6px; color: var(--planr-color-text-muted); font-size: 9px; }
1340
- .planr-reply header time { margin-left: auto; font-family: var(--planr-font-mono); }
1341
- .planr-reply p { margin: 4px 0; white-space: pre-wrap; overflow-wrap: anywhere; }
1342
- .planr-reply-editor { margin-top: 8px; }
1343
- .planr-thread .planr-reply-toggle { min-height: 28px; padding: 2px 0; border-color: transparent; background: transparent; color: var(--planr-color-text-muted); font-size: 12px; font-weight: 550; }
1344
- .planr-thread .planr-reply-toggle:hover, .planr-thread .planr-reply-toggle[aria-expanded="true"] { color: var(--planr-color-primary-strong); }
1345
- .planr-reply-form { display: grid; gap: 6px; margin-top: 6px; }
1346
- .planr-reply-form[hidden] { display: none; }
1347
- .planr-reply-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
1348
- .planr-reply-form textarea { min-height: 64px; max-height: 180px; resize: vertical; font: 13px/1.5 var(--planr-font-body); }
1349
- .planr-reply-controls { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
1350
- .planr-reply-hint { font-size: 11px; color: var(--planr-color-text-muted); }
1351
- .planr-reply-form .planr-reply-send { display: grid; place-items: center; flex: 0 0 30px; width: 30px; min-width: 30px; height: 30px; min-height: 30px; padding: 0; border-radius: 7px; }
1352
- .planr-reply-form .planr-reply-send:disabled { opacity: .35; cursor: not-allowed; }
1353
- ${ARTIFACT_ANNOTATION_MOBILE_CSS}
1354
- .planr-decision-slot { padding: 12px; border-top: 1px solid var(--planr-color-rule); background: var(--planr-color-chrome); }
1355
- .planr-decision-slot label { display: block; margin-bottom: 6px; color: var(--planr-color-text-muted); font-size: 11px; }
1356
- .planr-decision-slot textarea {
1357
- width: 100%;
1358
- min-height: 58px;
1359
- resize: vertical;
1360
- padding: 9px;
1361
- border: 1px solid var(--planr-color-rule);
1362
- border-radius: var(--planr-radius-small);
1363
- background: var(--planr-color-panel);
1364
- color: var(--planr-color-text);
1365
- }
1366
- .planr-decision-slot > div { display: grid; grid-template-columns: 1fr 1.2fr; gap: 8px; margin-top: 8px; }
1367
- .planr-decision-slot button {
1368
- min-height: 32px;
1369
- border: 1px solid var(--planr-color-rule);
1370
- border-radius: var(--planr-radius-small);
1371
- background: transparent;
1372
- cursor: pointer;
1373
- font-weight: 700;
1374
- }
1375
- .planr-decision-slot button[data-planr-decision="approved"] { border-color: var(--planr-color-primary); color: var(--planr-color-primary); }
1376
- .planr-decision-slot button[data-planr-decision="changes_requested"] { border-color: var(--planr-color-danger); background: var(--planr-color-danger); color: var(--planr-color-on-danger); }
1377
- .planr-decision-slot button[aria-pressed="true"] { box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 25%, transparent); }
1378
- .planr-decision-slot > p { min-height: 16px; margin: 7px 0 0; color: var(--planr-color-text-muted); font-size: 10px; }
1379
- [data-planr-slot="dialogs"] { position: fixed; z-index: 80; inset: 0; pointer-events: none; }
1380
- .planr-dialog-backdrop {
1381
- position: fixed;
1382
- inset: 0;
1383
- display: grid;
1384
- place-items: center;
1385
- padding: 20px;
1386
- background: color-mix(in srgb, var(--planr-color-background) 76%, transparent);
1387
- backdrop-filter: blur(8px);
1388
- pointer-events: auto;
1389
- }
1390
- .planr-share-dialog {
1391
- width: min(560px, 100%);
1392
- max-height: calc(100vh - 40px);
1393
- overflow: auto;
1394
- border: 1px solid var(--planr-color-rule);
1395
- border-radius: var(--planr-radius-large);
1396
- background: var(--planr-color-chrome);
1397
- box-shadow: 0 28px 100px color-mix(in srgb, var(--planr-color-background) 68%, transparent);
1398
- animation: planr-dialog-in var(--planr-motion-base);
1399
- }
1400
- .planr-share-dialog > header {
1401
- display: flex;
1402
- align-items: flex-start;
1403
- justify-content: space-between;
1404
- gap: 18px;
1405
- padding: 18px 18px 12px;
1406
- }
1407
- .planr-share-dialog h2 { margin: 0 0 4px; font: 650 18px/1.15 var(--planr-font-display); letter-spacing: -.025em; }
1408
- .planr-share-dialog p { margin: 0; color: var(--planr-color-text-muted); font-size: 12px; }
1409
- .planr-dialog-close {
1410
- width: 32px;
1411
- height: 32px;
1412
- flex: none;
1413
- border: 1px solid var(--planr-color-rule);
1414
- border-radius: var(--planr-radius-small);
1415
- background: transparent;
1416
- color: var(--planr-color-text-muted);
1417
- cursor: pointer;
1418
- font-size: 18px;
1419
- }
1420
- .planr-share-receipt {
1421
- margin: 8px 18px 10px;
1422
- overflow: hidden;
1423
- border: 1px solid var(--planr-color-rule);
1424
- border-radius: var(--planr-radius-medium);
1425
- background: var(--planr-color-panel);
1426
- }
1427
- .planr-share-receipt-row {
1428
- width: 100%;
1429
- min-height: 68px;
1430
- display: grid;
1431
- grid-template-columns: 30px minmax(0, 1fr) auto;
1432
- align-items: center;
1433
- gap: 10px;
1434
- padding: 11px 12px;
1435
- border: 0;
1436
- border-bottom: 1px solid var(--planr-color-rule);
1437
- background: transparent;
1438
- color: var(--planr-color-text);
1439
- text-align: left;
1440
- cursor: pointer;
1441
- }
1442
- .planr-share-receipt-row:last-child { border-bottom: 0; }
1443
- .planr-share-receipt-row.is-selected {
1444
- background: color-mix(in srgb, var(--planr-color-primary) 8%, var(--planr-color-panel));
1445
- box-shadow: inset 3px 0 var(--planr-color-primary);
1446
- }
1447
- .planr-share-receipt-row:disabled { opacity: .55; cursor: not-allowed; }
1448
- .planr-share-receipt-row strong { display: block; margin-bottom: 3px; font-size: 12px; }
1449
- .planr-share-receipt-row small { display: block; color: var(--planr-color-text-muted); font-size: 10.5px; }
1450
- .planr-share-receipt-icon {
1451
- width: 28px;
1452
- height: 28px;
1453
- display: grid;
1454
- place-items: center;
1455
- border-radius: var(--planr-radius-small);
1456
- background: var(--planr-color-raised);
1457
- font: 12px/1 var(--planr-font-mono);
1458
- }
1459
- .planr-share-receipt-size {
1460
- color: var(--planr-color-primary);
1461
- font: 9px/1.25 var(--planr-font-mono);
1462
- letter-spacing: .04em;
1463
- text-align: right;
1464
- text-transform: uppercase;
1465
- }
1466
- .planr-share-threshold { padding: 0 18px; font: 10px/1.4 var(--planr-font-mono); }
1467
- .planr-share-ttl { margin: 12px 18px 0; padding: 12px; border: 1px solid var(--planr-color-rule); border-radius: var(--planr-radius-medium); background: var(--planr-color-panel); }
1468
- .planr-share-ttl label { display: flex; align-items: center; justify-content: space-between; gap: 12px; color: var(--planr-color-text); font-weight: 700; }
1469
- .planr-share-ttl select {
1470
- min-height: 34px;
1471
- padding: 0 28px 0 9px;
1472
- border: 1px solid var(--planr-color-rule);
1473
- border-radius: var(--planr-radius-small);
1474
- background: var(--planr-color-chrome);
1475
- color: var(--planr-color-text);
1476
- }
1477
- .planr-share-ttl p { margin-top: 8px; font-size: 10.5px; }
1478
- .planr-owner-custody { margin: 12px 18px 0; padding: 12px; border: 1px solid var(--planr-color-rule); border-radius: var(--planr-radius-medium); background: color-mix(in srgb, var(--planr-color-warning) 7%, var(--planr-color-panel)); }
1479
- .planr-owner-custody strong, .planr-live-capability strong { display: block; margin-bottom: 3px; color: var(--planr-color-warning); }
1480
- .planr-owner-custody p, .planr-live-capability p { margin: 4px 0 0; font-size: 10.5px; }
1481
- .planr-share-result { margin: 12px 18px 0; padding: 12px; border: 1px solid var(--planr-color-primary); border-radius: var(--planr-radius-medium); background: color-mix(in srgb, var(--planr-color-primary) 6%, var(--planr-color-panel)); }
1482
- .planr-share-result > label { display: block; margin-bottom: 6px; color: var(--planr-color-text-muted); font-size: 10px; }
1483
- .planr-share-result > div { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 7px; }
1484
- .planr-share-result input {
1485
- min-width: 0;
1486
- padding: 8px 9px;
1487
- border: 1px solid var(--planr-color-rule);
1488
- border-radius: var(--planr-radius-small);
1489
- background: var(--planr-color-chrome);
1490
- color: var(--planr-color-text);
1491
- font: 10px/1.3 var(--planr-font-mono);
1492
- }
1493
- .planr-live-capability { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--planr-color-rule); }
1494
- .planr-live-capability > div { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 7px; margin-top: 7px; }
1495
- .planr-share-result button, .planr-share-dialog footer button, .planr-hosted-viewer button {
1496
- min-height: 34px;
1497
- padding: 0 11px;
1498
- border: 1px solid var(--planr-color-rule);
1499
- border-radius: var(--planr-radius-small);
1500
- background: transparent;
1501
- color: var(--planr-color-text);
1502
- cursor: pointer;
1503
- font-weight: 700;
1504
- }
1505
- .planr-share-result button[data-planr-copy-state], .planr-toolbar-action[data-planr-copy-state] {
1506
- min-width: 96px;
1507
- transition: border-color var(--planr-motion-fast), background var(--planr-motion-fast), color var(--planr-motion-fast), transform var(--planr-motion-fast);
1508
- }
1509
- .planr-share-result button[data-planr-copy-state]::before, .planr-toolbar-action[data-planr-copy-state]::before {
1510
- display: inline-grid;
1511
- width: 17px;
1512
- height: 17px;
1513
- place-items: center;
1514
- margin-right: 6px;
1515
- border-radius: 50%;
1516
- content: '';
1517
- font: 800 11px/1 var(--planr-font-mono);
1518
- vertical-align: -1px;
1519
- }
1520
- .planr-share-result button[data-planr-copy-state="copied"], .planr-toolbar-action[data-planr-copy-state="copied"] {
1521
- border-color: var(--planr-color-primary);
1522
- background: color-mix(in srgb, var(--planr-color-primary) 12%, transparent);
1523
- color: var(--planr-color-primary-strong);
1524
- animation: planr-copy-confirm var(--planr-motion-base);
1525
- }
1526
- .planr-share-result button[data-planr-copy-state="copied"]::before, .planr-toolbar-action[data-planr-copy-state="copied"]::before { background: var(--planr-color-primary); color: var(--planr-color-background); content: '\u2713'; }
1527
- .planr-share-result button[data-planr-copy-state="error"], .planr-toolbar-action[data-planr-copy-state="error"] { border-color: var(--planr-color-danger); color: var(--planr-color-danger); }
1528
- .planr-share-result button[data-planr-copy-state="error"]::before, .planr-toolbar-action[data-planr-copy-state="error"]::before { border: 1px solid currentColor; content: '!'; }
1529
- .planr-deletion-receipt { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--planr-color-rule); }
1530
- .planr-deletion-receipt strong { display: block; margin-bottom: 3px; color: var(--planr-color-warning); }
1531
- .planr-deletion-receipt code { display: block; margin: 9px 0; padding: 9px; overflow-wrap: anywhere; border-radius: var(--planr-radius-small); background: var(--planr-color-background); color: var(--planr-color-text); }
1532
- .planr-share-error { margin: 10px 18px 0 !important; color: var(--planr-color-danger) !important; }
1533
- .planr-share-dialog > footer { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 18px 18px; }
1534
- .planr-share-dialog footer .planr-share-confirm { border-color: var(--planr-color-primary); background: var(--planr-color-primary); color: var(--planr-color-background); }
1535
- .planr-share-dialog footer button:disabled { opacity: .55; cursor: wait; }
1536
- .planr-hosted-viewer {
1537
- position: fixed;
1538
- z-index: 70;
1539
- inset: var(--planr-toolbar-height) 0 0;
1540
- display: grid;
1541
- place-items: center;
1542
- padding: 24px;
1543
- background: var(--planr-color-stage);
1544
- }
1545
- .planr-hosted-viewer > div {
1546
- width: min(420px, 100%);
1547
- padding: 28px;
1548
- border: 1px solid var(--planr-color-rule);
1549
- border-radius: var(--planr-radius-large);
1550
- background: var(--planr-color-chrome);
1551
- text-align: center;
1552
- box-shadow: 0 18px 60px color-mix(in srgb, var(--planr-color-background) 50%, transparent);
1553
- }
1554
- .planr-hosted-viewer .planr-mark { width: 40px; height: 40px; margin-bottom: 20px; }
1555
- .planr-hosted-viewer strong { display: block; margin-bottom: 7px; font: 650 19px/1.2 var(--planr-font-display); }
1556
- .planr-hosted-viewer p { margin: 0; color: var(--planr-color-text-muted); }
1557
- .planr-hosted-viewer button { margin-top: 16px; border-color: var(--planr-color-primary); color: var(--planr-color-primary); }
1558
- @keyframes planr-dialog-in { from { opacity: 0; transform: translateY(8px) scale(.985); } }
1559
- @keyframes planr-copy-confirm { 50% { transform: translateY(-1px); } }
1560
- @media (max-width: 900px) {
1561
- .planr-title-block > span, .planr-privacy, .planr-toolbar .planr-segment:first-of-type { display: none; }
1562
- .planr-title-block strong { max-width: 170px; }
1563
- .planr-workspace, .planr-shell[data-planr-rail-open="false"] .planr-workspace { grid-template-columns: minmax(0, 1fr); }
1564
- .planr-review-rail {
1565
- position: fixed;
1566
- z-index: 50;
1567
- inset: auto 0 0;
1568
- height: min(52vh, 480px);
1569
- height: min(52dvh, 480px);
1570
- max-height: calc(100dvh - var(--planr-toolbar-height));
1571
- padding-bottom: env(safe-area-inset-bottom, 0px);
1572
- overscroll-behavior: contain;
1573
- border: 1px solid var(--planr-color-rule);
1574
- border-radius: var(--planr-radius-large) var(--planr-radius-large) 0 0;
1575
- box-shadow: 0 18px 60px color-mix(in srgb, var(--planr-color-background) 52%, transparent);
1576
- }
1577
- .planr-shell[data-planr-rail-open="false"] .planr-review-rail { opacity: 0; visibility: hidden; transform: translate3d(0, calc(100% + env(safe-area-inset-bottom, 0px)), 0); }
1578
- .planr-rail-close { display: grid; }
1579
- .planr-stage-scroll { padding-left: 14px; }
1580
- }
1581
- @media (max-width: 620px) {
1582
- .planr-toolbar {
1583
- gap: 5px;
1584
- padding-left: max(8px, env(safe-area-inset-left));
1585
- padding-right: max(8px, env(safe-area-inset-right));
1586
- }
1587
- .planr-brand { max-width: 128px; }
1588
- .planr-title-block strong { max-width: 96px; }
1589
- .planr-toolbar [data-planr-mode] { min-width: 42px; padding-inline: 7px; }
1590
- .planr-toolbar [data-planr-mode="interact"] { font-size: 0; }
1591
- .planr-toolbar [data-planr-mode="interact"]::before { content: "View"; font-size: 11px; }
1592
- .planr-toolbar-action { padding-inline: 8px; }
1593
- .planr-stage-controls { padding-inline: 10px; }
1594
- .planr-dialog-backdrop { align-items: end; padding: 0; }
1595
- .planr-share-dialog { width: 100%; max-height: min(78vh, 680px); border-radius: var(--planr-radius-large) var(--planr-radius-large) 0 0; }
1596
- }
1597
- @media (max-width: 390px) {
1598
- .planr-toolbar { gap: 5px; padding-inline: 8px; }
1599
- .planr-brand { max-width: 20px; }
1600
- .planr-title-block { display: none; }
1601
- .planr-toolbar-action[data-planr-action="feedback"] { min-width: 32px; padding-inline: 6px; }
1602
- .planr-toolbar-action[data-planr-action="feedback"] .planr-feedback-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
1603
- .planr-variants button { max-width: 150px; padding-inline: 8px; }
1604
- .planr-share-receipt-row { grid-template-columns: 28px minmax(0, 1fr); }
1605
- .planr-share-receipt-size { grid-column: 2; text-align: left; }
1606
- .planr-share-result > div { grid-template-columns: 1fr; }
1607
- }
1608
- /* Document presentation: the artifact owns the page; the iframe is only an
1609
- opaque-origin security boundary and has no visible canvas treatment. */
1610
- html[data-planr-presentation="document"],
1611
- html[data-planr-presentation="document"] body {
1612
- height: auto;
1613
- min-height: 100%;
1614
- }
1615
- html[data-planr-presentation="document"] body { overflow: visible; }
1616
- .planr-shell[data-planr-presentation="document"] {
1617
- height: auto;
1618
- min-height: 100vh;
1619
- display: block;
1620
- }
1621
- .planr-shell[data-planr-presentation="document"] .planr-workspace,
1622
- .planr-shell[data-planr-presentation="document"][data-planr-rail-open="false"] .planr-workspace {
1623
- display: block;
1624
- }
1625
- .planr-shell[data-planr-presentation="document"] .planr-stage {
1626
- overflow: visible;
1627
- background: transparent;
1628
- }
1629
- .planr-shell[data-planr-presentation="document"] .planr-stage-scroll {
1630
- position: static;
1631
- overflow: visible;
1632
- padding: 0;
1633
- }
1634
- .planr-shell[data-planr-presentation="document"] .planr-stage-surface {
1635
- width: 100%;
1636
- min-width: 100%;
1637
- transform: none;
1638
- }
1639
- .planr-shell[data-planr-presentation="document"] .planr-frame-grid {
1640
- width: 100%;
1641
- display: block;
1642
- }
1643
- .planr-shell[data-planr-presentation="document"] .planr-artifact-panel {
1644
- width: 100%;
1645
- max-width: 100%;
1646
- min-width: 0;
1647
- height: var(--planr-document-height, max(var(--planr-artifact-height), 100vh));
1648
- min-height: 100vh;
1649
- }
1650
- .planr-shell[data-planr-presentation="document"] .planr-frame {
1651
- overflow: visible;
1652
- border-radius: 0;
1653
- background: transparent;
1654
- box-shadow: none;
1655
- }
1656
- .planr-shell[data-planr-presentation="document"] .planr-frame iframe {
1657
- width: 100%;
1658
- max-width: 100%;
1659
- background: transparent;
1660
- }
1661
- .planr-shell[data-planr-presentation="document"] .planr-frame-label { display: none; }
1662
- .planr-shell[data-planr-presentation="document"] .planr-stage-status { inset: 0; min-height: 100vh; }
1663
- .planr-shell[data-planr-presentation="document"] .planr-review-rail {
1664
- position: fixed;
1665
- z-index: 50;
1666
- inset: 0 0 0 auto;
1667
- width: min(var(--planr-review-rail-width), 100vw);
1668
- border-left: 1px solid var(--planr-color-rule);
1669
- box-shadow: -18px 0 60px color-mix(in srgb, var(--planr-color-background) 34%, transparent);
1670
- }
1671
- .planr-shell[data-planr-presentation="document"][data-planr-rail-open="false"] .planr-review-rail {
1672
- opacity: 1;
1673
- transform: translateX(100%);
1674
- }
1675
- @media (max-width: 900px) {
1676
- .planr-shell[data-planr-presentation="document"] .planr-floating-actions {
1677
- top: auto;
1678
- right: max(12px, env(safe-area-inset-right));
1679
- bottom: max(12px, env(safe-area-inset-bottom));
1680
- flex-direction: row;
1681
- transform: none;
1682
- }
1683
- .planr-shell[data-planr-presentation="document"] .planr-floating-actions > button,
1684
- .planr-shell[data-planr-presentation="document"] .planr-floating-actions > .planr-more > button {
1685
- width: 44px;
1686
- height: 44px;
1687
- }
1688
- .planr-shell[data-planr-presentation="document"] .planr-floating-actions [data-planr-tooltip]::after { display: none; }
1689
- .planr-shell[data-planr-presentation="document"] .planr-more-menu {
1690
- right: 0;
1691
- bottom: calc(100% + 10px);
1692
- }
1693
- .planr-shell[data-planr-presentation="document"] .planr-review-rail {
1694
- inset: auto 0 0;
1695
- width: 100%;
1696
- max-height: 100dvh;
1697
- }
1698
- .planr-shell[data-planr-presentation="document"][data-planr-rail-open="false"] .planr-review-rail {
1699
- transform: translate3d(0, calc(100% + env(safe-area-inset-bottom, 0px)), 0);
1700
- }
1701
- }
1702
- @media (prefers-reduced-motion: reduce) {
1703
- *, *::before, *::after {
1704
- animation-duration: 0s !important;
1705
- animation-iteration-count: 1 !important;
1706
- scroll-behavior: auto !important;
1707
- transition-duration: 0s !important;
1708
- }
1709
- }
1710
- `;
1711
- var DEFAULT_ARTIFACT_SHELL_INPUT = Object.freeze({
1712
- envelope: Object.freeze({ artifacts: Object.freeze([]) }),
1713
- viewer: Object.freeze({ mode: "single", status: "loading" }),
1714
- shell: Object.freeze({
1715
- title: "OpenPlanr artifact review",
1716
- privacy: "local",
1717
- theme: "auto",
1718
- railOpen: false,
1719
- feedbackCount: 0,
1720
- zoom: 72
1721
- })
1722
- });
1723
- function renderArtifactShellDocument(input = DEFAULT_ARTIFACT_SHELL_INPUT, { theme, stageRuntimeUrl = "./artifact-review-stage.js" } = {}) {
1724
- const model = normalizeArtifactShellModel(input);
1725
- const canonicalTheme = theme ?? loadArtifactTheme();
1726
- const themeCss = renderArtifactThemeCss(canonicalTheme);
1727
- const shellMarkup = renderArtifactShellMarkup(model);
1728
- const modelData = renderArtifactShellModelData(model);
1729
- const stagePayload = createArtifactStagePayload(input.envelope, {
1730
- viewer: input.viewer ?? input.envelope?.viewer
1731
- });
1732
- const reviewState = Object.freeze({
1733
- schemaVersion: "1.0.0",
1734
- reviewOf: digestArtifactEnvelope({
1735
- schemaVersion: input.envelope?.schemaVersion ?? "1.0.0",
1736
- ...input.envelope?.sources ? { sources: input.envelope.sources } : {},
1737
- artifacts: input.envelope?.artifacts ?? [],
1738
- viewer: input.envelope?.viewer ?? input.viewer ?? {}
1739
- }),
1740
- review: input.envelope?.review ?? null
1741
- });
1742
- return `<!doctype html>
1743
- <html lang="en" data-planr-theme="${model.theme}" data-planr-presentation="${model.presentation}" data-planr-artifact-shell="${ARTIFACT_SHELL_VERSION}">
1744
- <head>
1745
- <meta charset="utf-8">
1746
- <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
1747
- <meta name="robots" content="noindex,nofollow,noarchive">
1748
- <meta name="referrer" content="no-referrer">
1749
- <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline' data: blob:; script-src 'self' 'unsafe-inline' data: blob:; frame-src blob:; img-src data: blob:; media-src data: blob:; font-src data:; connect-src 'self'; worker-src data: blob:; object-src 'none'; form-action 'none'; base-uri 'none'">
1750
- <title>${escapeHtml(model.title)} \xB7 OpenPlanr</title>
1751
- <style>
1752
- ${themeCss}${ARTIFACT_SHELL_CSS}</style>
1753
- </head>
1754
- <body>
1755
- ${shellMarkup}
1756
- <script type="application/json" id="planr-artifact-shell-model">${modelData}</script>
1757
- <script type="application/json" id="planr-artifact-stage-payload">${embedJson(stagePayload)}</script>
1758
- <script type="application/json" id="planr-artifact-review-state">${embedJson(reviewState)}</script>
1759
- <script src="${escapeHtml(stageRuntimeUrl)}" defer></script>
1760
- </body>
1761
- </html>
1762
- `;
1763
- }
1764
-
1765
- export {
1766
- contrastRatio,
1767
- AA_NORMAL,
1768
- escapeHtml,
1769
- embedJson,
1770
- renderPlanrMark,
1771
- renderArtifactShellDocument
1772
- };