pmx-canvas 0.8.2 → 0.9.1

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 (338) hide show
  1. package/.github/extensions/pmx-canvas/runtime.json +1 -1
  2. package/.github/extensions/pmx-canvas/tools.json +601 -22
  3. package/CHANGELOG.md +59 -0
  4. package/Readme.md +131 -532
  5. package/dist/canvas/global.css +2724 -476
  6. package/dist/canvas/index.js +168 -107
  7. package/dist/canvas/mcp-app.html +2899 -596
  8. package/dist/json-render/index.js +20 -20
  9. package/dist/types/client/canvas/BarHint.d.ts +12 -2
  10. package/dist/types/client/canvas/BoardLinkDialog.d.ts +3 -1
  11. package/dist/types/client/canvas/BoardPinButton.d.ts +10 -0
  12. package/dist/types/client/canvas/BoardSwitcher.d.ts +1 -1
  13. package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
  14. package/dist/types/client/canvas/CommandBar.d.ts +3 -4
  15. package/dist/types/client/canvas/ConnectionBanner.d.ts +2 -1
  16. package/dist/types/client/canvas/ContextChip.d.ts +3 -0
  17. package/dist/types/client/canvas/CrossBoardReferences.d.ts +5 -0
  18. package/dist/types/client/canvas/EdgeLayer.d.ts +14 -3
  19. package/dist/types/client/canvas/EmptyState.d.ts +4 -4
  20. package/dist/types/client/canvas/HomeGraphView.d.ts +2 -0
  21. package/dist/types/client/canvas/HomeMapView.d.ts +1 -0
  22. package/dist/types/client/canvas/HomeReviewView.d.ts +6 -0
  23. package/dist/types/client/canvas/HomeView.d.ts +9 -7
  24. package/dist/types/client/canvas/KnowledgeDialog.d.ts +4 -0
  25. package/dist/types/client/canvas/LifecycleChrome.d.ts +5 -0
  26. package/dist/types/client/canvas/LifecycleFields.d.ts +7 -0
  27. package/dist/types/client/canvas/LifecyclePanel.d.ts +1 -0
  28. package/dist/types/client/canvas/MemoryInspector.d.ts +7 -0
  29. package/dist/types/client/canvas/NearPinLayer.d.ts +14 -0
  30. package/dist/types/client/canvas/NodeContextMark.d.ts +40 -7
  31. package/dist/types/client/canvas/RelationPresetsDialog.d.ts +4 -0
  32. package/dist/types/client/canvas/RelationsPanel.d.ts +4 -0
  33. package/dist/types/client/canvas/SessionPanel.d.ts +2 -0
  34. package/dist/types/client/canvas/canvas-area.d.ts +1 -1
  35. package/dist/types/client/canvas/graph-geometry.d.ts +27 -0
  36. package/dist/types/client/canvas/graph-model.d.ts +37 -0
  37. package/dist/types/client/canvas/memory-layout.d.ts +23 -0
  38. package/dist/types/client/canvas/use-chrome-height.d.ts +2 -0
  39. package/dist/types/client/canvas/use-focus-trap.d.ts +1 -0
  40. package/dist/types/client/canvas/use-memory-graph.d.ts +8 -0
  41. package/dist/types/client/canvas/use-pan-zoom.d.ts +4 -1
  42. package/dist/types/client/icons.d.ts +0 -10
  43. package/dist/types/client/nodes/AxStepControls.d.ts +1 -1
  44. package/dist/types/client/nodes/InlineMarkdownEditor.d.ts +4 -4
  45. package/dist/types/client/nodes/MarkdownNode.d.ts +5 -1
  46. package/dist/types/client/nodes/McpAppNode.d.ts +4 -4
  47. package/dist/types/client/nodes/viewer-runtime-state.d.ts +1 -1
  48. package/dist/types/client/state/boards-store.d.ts +81 -9
  49. package/dist/types/client/state/canvas-store.d.ts +14 -1
  50. package/dist/types/client/state/context-chip-store.d.ts +22 -0
  51. package/dist/types/client/state/context-status-store.d.ts +35 -0
  52. package/dist/types/client/state/human-store.d.ts +2 -1
  53. package/dist/types/client/state/intent-bridge.d.ts +11 -8
  54. package/dist/types/client/state/knowledge-store.d.ts +22 -0
  55. package/dist/types/client/state/near-pin-store.d.ts +44 -1
  56. package/dist/types/client/state/presence-store.d.ts +4 -4
  57. package/dist/types/client/state/presentation.d.ts +28 -0
  58. package/dist/types/client/state/relation-store.d.ts +10 -0
  59. package/dist/types/client/state/session-store.d.ts +41 -2
  60. package/dist/types/client/state/workspace-settings.d.ts +7 -0
  61. package/dist/types/client/types.d.ts +13 -1
  62. package/dist/types/client/utils/keyboard.d.ts +2 -0
  63. package/dist/types/client/utils/time-ago.d.ts +4 -0
  64. package/dist/types/mcp/context-uri-template.d.ts +3 -1
  65. package/dist/types/server/agent-presence.d.ts +10 -3
  66. package/dist/types/server/ax-context.d.ts +1 -1
  67. package/dist/types/server/canvas-db.d.ts +30 -7
  68. package/dist/types/server/canvas-operations.d.ts +24 -2
  69. package/dist/types/server/canvas-provenance.d.ts +22 -2
  70. package/dist/types/server/canvas-serialization.d.ts +2 -0
  71. package/dist/types/server/canvas-state.d.ts +93 -15
  72. package/dist/types/server/canvas-validation.d.ts +1 -1
  73. package/dist/types/server/context-brief.d.ts +94 -6
  74. package/dist/types/server/context-reads.d.ts +33 -7
  75. package/dist/types/server/edit-summary.d.ts +20 -0
  76. package/dist/types/server/index.d.ts +71 -10
  77. package/dist/types/server/knowledge-lifecycle.d.ts +221 -0
  78. package/dist/types/server/lifecycle-status.d.ts +10 -0
  79. package/dist/types/server/memory-graph.d.ts +9 -0
  80. package/dist/types/server/mutation-history.d.ts +2 -0
  81. package/dist/types/server/operations/ops/ax-shared.d.ts +1 -1
  82. package/dist/types/server/operations/ops/boards.d.ts +2 -1
  83. package/dist/types/server/operations/ops/lifecycle.d.ts +2 -0
  84. package/dist/types/server/operations/ops/memory-graph.d.ts +2 -0
  85. package/dist/types/server/operations/ops/nodes.d.ts +5 -0
  86. package/dist/types/server/operations/ops/query.d.ts +23 -0
  87. package/dist/types/server/operations/registry.d.ts +1 -0
  88. package/dist/types/server/placement.d.ts +7 -0
  89. package/dist/types/server/scope-fence.d.ts +2 -1
  90. package/dist/types/server/spatial-analysis.d.ts +6 -3
  91. package/dist/types/server/tour-control.d.ts +32 -0
  92. package/dist/types/server/wiki-links.d.ts +14 -0
  93. package/dist/types/server/workbench-auth.d.ts +2 -0
  94. package/dist/types/shared/agent-context.d.ts +2 -0
  95. package/dist/types/shared/agent-presence.d.ts +15 -12
  96. package/dist/types/shared/auto-arrange.d.ts +1 -0
  97. package/dist/types/shared/boards.d.ts +4 -4
  98. package/dist/types/shared/knowledge-lifecycle.d.ts +41 -0
  99. package/dist/types/shared/knowledge-presets.d.ts +6 -0
  100. package/dist/types/shared/lifecycle-status.d.ts +24 -0
  101. package/dist/types/shared/memory-graph.d.ts +53 -0
  102. package/dist/types/shared/relations.d.ts +68 -0
  103. package/dist/types/shared/semantic-attention.d.ts +2 -0
  104. package/dist/types/shared/tour.d.ts +38 -0
  105. package/dist/types/shared/workspace-settings.d.ts +11 -0
  106. package/docs/RELEASE.md +21 -3
  107. package/docs/adr-001-bun-only-runtime.md +7 -1
  108. package/docs/adr-002-shared-product-separate-runtimes.md +93 -0
  109. package/docs/api-reference.md +109 -0
  110. package/docs/ax-host-adapter-contract.md +1 -1
  111. package/docs/ax-state-contract.md +5 -4
  112. package/docs/cli.md +153 -15
  113. package/docs/demos/pmx-canvas-demo.mp4 +0 -0
  114. package/docs/design/AgentContext.dc.html +3 -3
  115. package/docs/design/BoardPins.dc.html +37 -22
  116. package/docs/design/Categories.dc.html +208 -0
  117. package/docs/design/CategoryEditor.dc.html +33 -0
  118. package/docs/design/Chrome.dc.html +52 -9
  119. package/docs/design/ContextChip.dc.html +224 -0
  120. package/docs/design/ContextChip600.dc.html +136 -0
  121. package/docs/design/EmptyState.dc.html +45 -0
  122. package/docs/design/Flows.dc.html +23 -1
  123. package/docs/design/HeaderMarks.dc.html +183 -0
  124. package/docs/design/Home.dc.html +19 -1
  125. package/docs/design/HomeGraph.dc.html +86 -202
  126. package/docs/design/HomeMap.dc.html +23 -1
  127. package/docs/design/HomeTeam.dc.html +32 -14
  128. package/docs/design/Lifecycle.dc.html +22 -0
  129. package/docs/design/Lifecycle600.dc.html +18 -0
  130. package/docs/design/LifecycleVariants.dc.html +157 -0
  131. package/docs/design/LinkAuthorship.dc.html +139 -0
  132. package/docs/design/LinksChanged.dc.html +203 -0
  133. package/docs/design/LinksOptions.dc.html +137 -0
  134. package/docs/design/LinksOptions600.dc.html +134 -0
  135. package/docs/design/NearPin.dc.html +9 -10
  136. package/docs/design/Pane600.dc.html +4 -3
  137. package/docs/design/Relations.dc.html +3 -2
  138. package/docs/design/Restore.dc.html +152 -0
  139. package/docs/design/SeeChange.dc.html +267 -0
  140. package/docs/design/Uses.dc.html +12 -6
  141. package/docs/design/canvas.json +146 -19
  142. package/docs/design.md +449 -16
  143. package/docs/environment.md +0 -1
  144. package/docs/evals/curation-effect.md +128 -0
  145. package/docs/http-api.md +459 -37
  146. package/docs/mcp.md +146 -18
  147. package/docs/node-types.md +58 -3
  148. package/docs/plans/design-gaps-2026-10-08.md +53 -0
  149. package/docs/plans/plan-009-tech-debt-backlog.md +379 -0
  150. package/docs/plans/plan-016-context-made-visible-wave-1.md +150 -5
  151. package/docs/plans/plan-017-knowledge-categories-and-lifecycle.md +175 -0
  152. package/docs/plans/plan-018-connected-memory-wave-2.md +594 -0
  153. package/docs/plans/plan-019-post-0.9-roadmap.md +198 -0
  154. package/docs/product-context-vision-2026-09.md +17 -1
  155. package/docs/product-vision-2026-09.md +1082 -43
  156. package/docs/product-vision-review-2026-09.md +13 -1
  157. package/docs/screenshots/workbench-live-dark.png +0 -0
  158. package/docs/screenshots/workbench-live-light.png +0 -0
  159. package/docs/sdk.md +62 -2
  160. package/package.json +1 -1
  161. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
  162. package/plugins/pmx-canvas/plugin.json +1 -1
  163. package/plugins/pmx-canvas/runtime.json +1 -1
  164. package/plugins/pmx-canvas/tools.json +601 -22
  165. package/skills/pmx-canvas/SKILL.md +216 -42
  166. package/skills/pmx-canvas/evals/evals.json +224 -0
  167. package/skills/pmx-canvas/references/full-reference.md +120 -21
  168. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
  169. package/skills/pmx-canvas/references/importing-context.md +132 -0
  170. package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
  171. package/skills/pmx-canvas/references/tours-and-recording.md +16 -1
  172. package/skills/pmx-canvas-testing/SKILL.md +20 -0
  173. package/src/cli/agent.ts +2 -0
  174. package/src/cli/commands/ax.ts +12 -0
  175. package/src/cli/commands/boards.ts +88 -11
  176. package/src/cli/commands/edges.ts +28 -0
  177. package/src/cli/commands/groups.ts +7 -0
  178. package/src/cli/commands/nodes.ts +1 -0
  179. package/src/cli/commands/query.ts +34 -2
  180. package/src/cli/commands/record.ts +199 -48
  181. package/src/cli/index.ts +6 -1
  182. package/src/client/App.tsx +177 -70
  183. package/src/client/canvas/AttentionHistory.tsx +0 -2
  184. package/src/client/canvas/BarHint.tsx +40 -2
  185. package/src/client/canvas/BoardCopyDialog.tsx +1 -1
  186. package/src/client/canvas/BoardFolderDialog.tsx +7 -7
  187. package/src/client/canvas/BoardLinkDialog.tsx +138 -33
  188. package/src/client/canvas/BoardPinButton.tsx +33 -0
  189. package/src/client/canvas/BoardSwitcher.tsx +26 -40
  190. package/src/client/canvas/CanvasNode.tsx +360 -237
  191. package/src/client/canvas/CanvasViewport.tsx +45 -7
  192. package/src/client/canvas/CommandBar.tsx +29 -23
  193. package/src/client/canvas/CommandPalette.tsx +5 -12
  194. package/src/client/canvas/ConnectionBanner.tsx +3 -3
  195. package/src/client/canvas/ContextChip.tsx +296 -0
  196. package/src/client/canvas/ContextMenu.tsx +63 -5
  197. package/src/client/canvas/CrossBoardReferences.tsx +60 -0
  198. package/src/client/canvas/EdgeLayer.tsx +339 -76
  199. package/src/client/canvas/EmptyState.tsx +33 -18
  200. package/src/client/canvas/ExpandedNodeOverlay.tsx +72 -40
  201. package/src/client/canvas/ExternalWriters.tsx +57 -42
  202. package/src/client/canvas/HomeGraphView.tsx +942 -0
  203. package/src/client/canvas/HomeMapView.tsx +641 -0
  204. package/src/client/canvas/HomeReviewView.tsx +167 -0
  205. package/src/client/canvas/HomeView.tsx +687 -160
  206. package/src/client/canvas/IntentLayer.tsx +19 -12
  207. package/src/client/canvas/KnowledgeDialog.tsx +488 -0
  208. package/src/client/canvas/LifecycleChrome.tsx +133 -0
  209. package/src/client/canvas/LifecycleFields.tsx +91 -0
  210. package/src/client/canvas/LifecyclePanel.tsx +543 -0
  211. package/src/client/canvas/MemoryInspector.tsx +104 -0
  212. package/src/client/canvas/Minimap.tsx +3 -3
  213. package/src/client/canvas/NearPinLayer.tsx +187 -0
  214. package/src/client/canvas/NodeContextMark.tsx +175 -97
  215. package/src/client/canvas/Presentation.tsx +23 -57
  216. package/src/client/canvas/RelationPresetsDialog.tsx +413 -0
  217. package/src/client/canvas/RelationsPanel.tsx +82 -0
  218. package/src/client/canvas/SelectionBar.tsx +3 -6
  219. package/src/client/canvas/SessionPanel.tsx +90 -50
  220. package/src/client/canvas/SessionReceipt.tsx +311 -39
  221. package/src/client/canvas/ShortcutOverlay.tsx +1 -1
  222. package/src/client/canvas/SnapshotPanel.tsx +27 -36
  223. package/src/client/canvas/ToolRail.tsx +367 -192
  224. package/src/client/canvas/TopBar.tsx +354 -124
  225. package/src/client/canvas/canvas-area.ts +10 -3
  226. package/src/client/canvas/graph-geometry.ts +195 -0
  227. package/src/client/canvas/graph-model.ts +254 -0
  228. package/src/client/canvas/memory-layout.ts +106 -0
  229. package/src/client/canvas/use-chrome-height.ts +20 -0
  230. package/src/client/canvas/use-focus-trap.ts +31 -5
  231. package/src/client/canvas/use-memory-graph.ts +58 -0
  232. package/src/client/canvas/use-node-drag.ts +2 -1
  233. package/src/client/canvas/use-pan-zoom.ts +64 -7
  234. package/src/client/icons.tsx +0 -63
  235. package/src/client/mcp-app/style.css +0 -6
  236. package/src/client/nodes/AxStepControls.tsx +74 -50
  237. package/src/client/nodes/BoardNode.tsx +5 -1
  238. package/src/client/nodes/ContextNode.tsx +18 -11
  239. package/src/client/nodes/ExtAppFrame.tsx +6 -3
  240. package/src/client/nodes/FileNode.tsx +46 -42
  241. package/src/client/nodes/HtmlNode.tsx +32 -0
  242. package/src/client/nodes/ImageNode.tsx +1 -1
  243. package/src/client/nodes/InlineFormatBar.tsx +6 -9
  244. package/src/client/nodes/InlineMarkdownEditor.tsx +56 -17
  245. package/src/client/nodes/MarkdownNode.tsx +377 -109
  246. package/src/client/nodes/McpAppNode.tsx +50 -20
  247. package/src/client/nodes/MdFormatBar.tsx +21 -18
  248. package/src/client/nodes/PromptNode.tsx +1 -1
  249. package/src/client/nodes/ResponseNode.tsx +1 -1
  250. package/src/client/nodes/viewer-runtime-state.ts +54 -22
  251. package/src/client/state/attention-bridge.ts +64 -15
  252. package/src/client/state/boards-store.ts +193 -39
  253. package/src/client/state/canvas-store.ts +99 -12
  254. package/src/client/state/context-chip-store.ts +70 -0
  255. package/src/client/state/context-status-store.ts +53 -0
  256. package/src/client/state/human-store.ts +13 -7
  257. package/src/client/state/intent-bridge.ts +51 -30
  258. package/src/client/state/knowledge-store.ts +43 -0
  259. package/src/client/state/near-pin-store.ts +115 -6
  260. package/src/client/state/presence-store.ts +7 -10
  261. package/src/client/state/presentation.ts +91 -0
  262. package/src/client/state/relation-store.ts +81 -0
  263. package/src/client/state/session-store.ts +144 -18
  264. package/src/client/state/sse-bridge.ts +235 -32
  265. package/src/client/state/workspace-settings.ts +11 -0
  266. package/src/client/theme/global.css +2724 -476
  267. package/src/client/types.ts +12 -0
  268. package/src/client/utils/keyboard.ts +10 -0
  269. package/src/client/utils/time-ago.ts +14 -0
  270. package/src/json-render/renderer/index.tsx +31 -0
  271. package/src/mcp/canvas-app.ts +12 -2
  272. package/src/mcp/context-uri-template.ts +7 -4
  273. package/src/mcp/server.ts +63 -41
  274. package/src/mcp/workbench-app.ts +39 -6
  275. package/src/server/agent-presence.ts +128 -28
  276. package/src/server/ax-context.ts +27 -13
  277. package/src/server/board-export.ts +12 -1
  278. package/src/server/canvas-db.ts +331 -42
  279. package/src/server/canvas-operations.ts +195 -83
  280. package/src/server/canvas-provenance.ts +53 -22
  281. package/src/server/canvas-serialization.ts +2 -0
  282. package/src/server/canvas-state.ts +950 -122
  283. package/src/server/canvas-validation.ts +9 -2
  284. package/src/server/context-brief.ts +345 -38
  285. package/src/server/context-reads.ts +178 -30
  286. package/src/server/demo-state.json +355 -24
  287. package/src/server/edit-summary.ts +74 -0
  288. package/src/server/html-surface.ts +8 -1
  289. package/src/server/index.ts +181 -11
  290. package/src/server/knowledge-lifecycle.ts +304 -0
  291. package/src/server/lifecycle-status.ts +232 -0
  292. package/src/server/memory-graph.ts +166 -0
  293. package/src/server/mutation-history.ts +18 -6
  294. package/src/server/operations/composites.ts +32 -11
  295. package/src/server/operations/http.ts +7 -2
  296. package/src/server/operations/index.ts +4 -0
  297. package/src/server/operations/mcp.ts +26 -1
  298. package/src/server/operations/ops/ax-presence.ts +1 -1
  299. package/src/server/operations/ops/ax-read.ts +57 -6
  300. package/src/server/operations/ops/ax-timeline.ts +28 -2
  301. package/src/server/operations/ops/backup.ts +5 -3
  302. package/src/server/operations/ops/batch.ts +35 -4
  303. package/src/server/operations/ops/boards.ts +188 -47
  304. package/src/server/operations/ops/canvas-wire.ts +31 -1
  305. package/src/server/operations/ops/edges.ts +36 -2
  306. package/src/server/operations/ops/groups.ts +6 -1
  307. package/src/server/operations/ops/lifecycle.ts +262 -0
  308. package/src/server/operations/ops/memory-graph.ts +45 -0
  309. package/src/server/operations/ops/nodes.ts +107 -24
  310. package/src/server/operations/ops/query.ts +281 -68
  311. package/src/server/operations/ops/snapshots.ts +73 -1
  312. package/src/server/operations/ops/validate.ts +5 -1
  313. package/src/server/operations/ops/viewport.ts +97 -3
  314. package/src/server/operations/registry.ts +74 -25
  315. package/src/server/placement.ts +29 -0
  316. package/src/server/scope-fence.ts +78 -6
  317. package/src/server/server.ts +115 -16
  318. package/src/server/spatial-analysis.ts +48 -23
  319. package/src/server/tour-control.ts +82 -0
  320. package/src/server/wiki-links.ts +137 -0
  321. package/src/server/workbench-auth.ts +11 -0
  322. package/src/shared/agent-context.ts +3 -0
  323. package/src/shared/agent-presence.ts +15 -15
  324. package/src/shared/auto-arrange.ts +2 -0
  325. package/src/shared/boards.ts +4 -4
  326. package/src/shared/knowledge-lifecycle.ts +22 -0
  327. package/src/shared/knowledge-presets.ts +80 -0
  328. package/src/shared/lifecycle-status.ts +26 -0
  329. package/src/shared/memory-graph.ts +74 -0
  330. package/src/shared/relations.ts +98 -0
  331. package/src/shared/semantic-attention.ts +15 -1
  332. package/src/shared/tour.ts +23 -5
  333. package/src/shared/workspace-settings.ts +13 -0
  334. package/dist/types/client/canvas/ContextPinBar.d.ts +0 -1
  335. package/dist/types/client/canvas/FocusFieldLayer.d.ts +0 -1
  336. package/dist/types/client/canvas/kind-colors.d.ts +0 -3
  337. package/dist/types/server/agent-context.d.ts +0 -22
  338. package/src/client/canvas/ContextPinBar.tsx +0 -25
@@ -38,7 +38,11 @@ body{margin:0}
38
38
  </div>
39
39
  </header>
40
40
 
41
- <div style="position: absolute; left: 52px; top: 96px; width: 1388px; height: 864px; overflow: hidden; background-color: #081524; background-image: radial-gradient(rgba(142,163,189,0.12) 1px, transparent 1.2px); background-size: 24px 24px">
41
+ <!-- 2026-10-17: match Graph's bottom inspector visually, not its interactions.
42
+ Map retains tiles, saved board positions and connection Open actions.
43
+ The shared dock reserves space, resizes vertically and scrolls its list internally. -->
44
+ <div style="position: absolute; left: 52px; top: 96px; width: 1108px; height: 554px; overflow: hidden; background-color: #081524; background-image: radial-gradient(rgba(142,163,189,0.12) 1px, transparent 1.2px); background-size: 24px 24px">
45
+ <div style="position: relative; width: 1388px; height: 864px; transform: scale(.64); transform-origin: top left">
42
46
 
43
47
  <div style="{{m.frame}} left: 40px; top: 130px; width: 560px; height: 520px; border-color: rgba(95,207,192,0.45); background: rgba(95,207,192,0.03)"></div>
44
48
  <span style="{{m.pill}} left: 56px; top: 120px; border-color: rgba(95,207,192,0.45)"><span style="{{m.hue}} background: #5FCFC0"></span>Tech Enabling<span style="{{m.n}}">12</span></span>
@@ -90,6 +94,23 @@ body{margin:0}
90
94
  <div style="{{m.ghost}} left: 510px; top: 730px">Untitled<span style="{{m.meta}}">1 card</span></div>
91
95
  <span style="position: absolute; left: 576px; top: 438px; font-size: 11px; color: #8ea3bd; background: #081524; padding: 0 4px">[[DORA dashboard]]</span>
92
96
  </div>
97
+ </div>
98
+ <aside aria-label="Map filters" style="position:absolute;right:0;top:96px;width:280px;height:554px;box-sizing:border-box;padding:18px;background:#0b1828;border-left:1px solid #1b2c44;color:#8ea3bd">
99
+ <h2 style="font-size:12px;text-transform:uppercase">Filters</h2><p>Find boards and cards</p><p>Only in context</p><p>Folders · Unfiled</p><p>Portals · Wiki · Relations · Previous</p>
100
+ </aside>
101
+ <footer style="position:absolute;left:52px;right:0;top:650px;height:30px;box-sizing:border-box;border-top:1px solid #1b2c44;padding:6px 16px;font-size:11px;color:#8ea3bd">▣ Board · ⌖ In context · ━ Portal · ┄ Wiki · ━ Relation · Drag boards to save positions · drag background to pan · scroll to zoom</footer>
102
+ <section aria-label="Selection details" style="position:absolute;left:52px;right:0;top:680px;height:280px;background:#0b1828;border-top:1px solid #1b2c44;display:flex;flex-direction:column;font-size:14px">
103
+ <div role="separator" aria-label="Resize relation details" aria-orientation="horizontal" style="height:10px;flex-shrink:0;cursor:row-resize;text-align:center;color:#8ea3bd">━</div>
104
+ <header style="display:flex;gap:16px;align-items:start;padding:8px 16px;flex-shrink:0">
105
+ <div style="flex:1"><strong style="font-size:15px">Pricing research · 2 connections</strong><div style="font-size:13px;color:#8ea3bd">Research / Pricing</div><div style="display:flex;gap:8px;margin-top:8px"><button style="{{m.action}}">Open board</button><button style="{{m.action}}">Pin board</button><button style="{{m.action}}">Reset position</button></div></div>
106
+ <button style="{{m.action}}">Collapse details</button><button style="{{m.action}}" aria-label="Close details">×</button>
107
+ </header>
108
+ <div style="overflow:auto;min-height:0;padding:0 16px;color:#8ea3bd;font-size:14px">
109
+ <p>27 cards · 2 connected boards · Not in context</p><p>Connections</p>
110
+ <div style="border-top:1px solid #1b2c44;padding:10px 0;display:flex;align-items:center;justify-content:space-between"><span>→ wiki · [[DORA dashboard]]</span><button style="{{m.action}}">DORA dashboard</button></div>
111
+ <div style="border-top:1px solid #1b2c44;padding:10px 0;display:flex;align-items:center;justify-content:space-between"><span>← relation · supporting pricing research</span><button style="{{m.action}}">Competitor teardown</button></div>
112
+ </div>
113
+ </section>
93
114
 
94
115
  </div>
95
116
  </x-dc>
@@ -97,6 +118,7 @@ body{margin:0}
97
118
  class Component extends DCLogic {
98
119
  renderVals() {
99
120
  var m = {
121
+ action: 'border:1px solid #1b2c44;border-radius:6px;background:#0f1d31;color:#b9c6d6;padding:6px 10px;font:inherit;font-size:14px;min-height:36px;',
100
122
  frame: 'position:absolute;box-sizing:border-box;border-radius:14px;border:1.5px dashed;',
101
123
  pill: 'position:absolute;display:flex;align-items:center;gap:8px;height:22px;padding:0 10px;border-radius:999px;border:1px solid;background:#0f1d31;font-size:12px;font-weight:600;line-height:20px;',
102
124
  sub: 'position:absolute;height:18px;padding:0 8px;border-radius:999px;background:#081524;font-size:11px;font-weight:500;line-height:18px;color:#b9c6d6;',
@@ -21,14 +21,14 @@ body{margin:0}
21
21
  <span aria-label="Signed in" style="width: 30px; height: 30px; border-radius: 999px; background: #2a4566; color: #e6eef7; font-size: 11px; font-weight: 600; display: flex; align-items: center; justify-content: center; margin-bottom: 6px">You</span>
22
22
  </nav>
23
23
 
24
- <aside aria-label="Library" style="position: absolute; left: 52px; top: 0; width: 280px; height: 1000px; box-sizing: border-box; padding: 16px 12px; background: #0b1828; border-right: 1px solid #1b2c44; display: flex; flex-direction: column; gap: 14px">
24
+ <aside aria-label="Library" style="position: absolute; left: 52px; top: 0; width: 340px; height: 1000px; box-sizing: border-box; padding: 16px 12px; background: #0b1828; border-right: 1px solid #1b2c44; display: flex; flex-direction: column; gap: 14px">
25
25
  <button style="display: flex; align-items: center; gap: 8px; height: 36px; padding: 0 10px; border-radius: 8px; border: 1px solid #1b2c44; background: #0f1d31; color: #e6eef7; font-family: inherit; text-align: left">
26
26
  <svg width="16" height="16" viewBox="0 0 24 24" style="{{s.icon}}"><path d="{{i.team}}"></path></svg><span style="flex: 1; font-size: 13px; font-weight: 600">Tech Enabling team</span><span style="font-size: 11px; color: #6b7d94">12 members ▾</span></button>
27
27
 
28
28
  <div style="display: flex; flex-direction: column; gap: 2px">
29
29
  <span style="{{s.sec}}">Your pinned boards</span>
30
30
  <sc-for list="{{pinned}}" as="b" hint-placeholder-count="3">
31
- <div style="{{s.row}}"><span style="{{s.pinOn}}"><svg width="9" height="9" viewBox="0 0 24 24" style="{{s.ic2}}"><path d="{{i.pin}}"></path></svg></span><span style="{{s.name}}">{{b.name}}</span><span style="{{b.tag}}">{{b.scope}}</span></div>
31
+ <div style="{{s.row}}"><span style="{{s.pinOn}}"><svg width="9" height="9" viewBox="0 0 24 24" style="{{s.ic2}}"><path d="{{i.pin}}"></path></svg></span><span style="{{s.name}}">{{b.name}}</span><sc-if value="{{b.hasDue}}" hint-placeholder-val="{{ false }}"><span style="{{s.due}}"><svg width="10" height="10" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{i.glass}}"></path></svg>{{b.due}}</span></sc-if><span style="{{b.tag}}">{{b.scope}}</span></div>
32
32
  </sc-for>
33
33
  <span style="font-size: 11px; color: #6b7d94; padding: 2px 8px 0 32px">Only you see these pins · ≈ 19k tokens</span>
34
34
  </div>
@@ -36,19 +36,19 @@ body{margin:0}
36
36
  <div style="display: flex; flex-direction: column; gap: 2px">
37
37
  <div style="display: flex; align-items: center; gap: 8px; padding: 0 8px 4px"><svg width="13" height="13" viewBox="0 0 24 24" style="{{s.icon}}"><path d="{{i.team}}"></path></svg><span style="{{s.secInline}}">Workspace</span><span style="font-size: 11px; color: #6b7d94">shared</span></div>
38
38
  <sc-for list="{{workspace}}" as="f" hint-placeholder-count="5">
39
- <div style="{{f.style}}"><span style="width: {{f.indent}}px; flex-shrink: 0"></span><span style="width: 8px; height: 8px; border-radius: 3px; background: {{f.hue}}; flex-shrink: 0"></span><span style="{{s.name}}">{{f.name}}</span><span style="font-size: 11px; color: #6b7d94">{{f.role}}</span></div>
39
+ <div style="{{f.style}}"><span style="width: {{f.indent}}px; flex-shrink: 0"></span><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icon}} flex-shrink: 0"><path d="{{i.folder}}"></path></svg><span style="{{s.name}}">{{f.name}}</span><span style="{{f.tagSt}}"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{f.catIcon}}"></path></svg>{{f.tag}}</span><sc-if value="{{f.hasDue}}" hint-placeholder-val="{{ false }}"><span style="{{s.due}}"><svg width="10" height="10" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{i.glass}}"></path></svg>{{f.due}}</span></sc-if><span style="width: 50px; text-align: right; font-size: 11px; color: #6b7d94; flex-shrink: 0">{{f.role}}</span></div>
40
40
  </sc-for>
41
41
  </div>
42
42
 
43
43
  <div style="display: flex; flex-direction: column; gap: 2px">
44
44
  <div style="display: flex; align-items: center; gap: 8px; padding: 0 8px 4px"><svg width="13" height="13" viewBox="0 0 24 24" style="{{s.icon}}"><path d="{{i.person}}"></path></svg><span style="{{s.secInline}}">Personal</span><span style="font-size: 11px; color: #6b7d94">only you</span></div>
45
45
  <sc-for list="{{personal}}" as="f" hint-placeholder-count="4">
46
- <div style="{{f.style}}"><span style="width: {{f.indent}}px; flex-shrink: 0"></span><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icon}} flex-shrink: 0"><path d="{{f.icon}}"></path></svg><span style="{{s.name}}">{{f.name}}</span><span style="font-size: 11px; color: #6b7d94">{{f.n}}</span></div>
46
+ <div style="{{f.style}}"><span style="width: {{f.indent}}px; flex-shrink: 0"></span><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icon}} flex-shrink: 0"><path d="{{f.icon}}"></path></svg><span style="{{s.name}}">{{f.name}}</span><span style="{{f.tagSt}}"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{f.catIcon}}"></path></svg>{{f.tag}}</span><sc-if value="{{f.hasDue}}" hint-placeholder-val="{{ false }}"><span style="{{s.due}}"><svg width="10" height="10" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{i.glass}}"></path></svg>{{f.due}}</span></sc-if><span style="width: 20px; text-align: right; font-size: 11px; color: #6b7d94; flex-shrink: 0">{{f.n}}</span></div>
47
47
  </sc-for>
48
48
  </div>
49
49
  </aside>
50
50
 
51
- <main style="position: absolute; left: 332px; top: 0; width: 808px; height: 1000px; box-sizing: border-box; padding: 24px 32px; display: flex; flex-direction: column; gap: 18px">
51
+ <main style="position: absolute; left: 392px; top: 0; width: 748px; height: 1000px; box-sizing: border-box; padding: 24px 32px; display: flex; flex-direction: column; gap: 18px">
52
52
  <div style="display: flex; align-items: flex-start; gap: 16px">
53
53
  <div style="flex: 1">
54
54
  <div style="font-size: 12px; color: #6b7d94">Personal <span style="color: #3d5170">/</span> <span style="color: #b9c6d6">Pricing drafts</span></div>
@@ -67,6 +67,7 @@ body{margin:0}
67
67
  <div style="padding: 10px 12px; display: flex; flex-direction: column; gap: 4px">
68
68
  <div style="font-size: 13px; font-weight: 600">{{bd.name}}</div>
69
69
  <div style="display: flex; align-items: center; gap: 6px; font-size: 11px; color: #8ea3bd"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icon}}"><path d="{{bd.icon}}"></path></svg>{{bd.access}}</div>
70
+ <div style="display: flex; align-items: center; gap: 6px; font-size: 11px; color: #8ea3bd"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icon}}"><path d="{{i.research}}"></path></svg><span style="flex: 1">↳ Research</span><sc-if value="{{bd.hasDue}}" hint-placeholder-val="{{ false }}"><span style="{{s.due}}"><svg width="10" height="10" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{i.glass}}"></path></svg>{{bd.due}}</span></sc-if></div>
70
71
  </div>
71
72
  </article>
72
73
  </sc-for>
@@ -75,7 +76,7 @@ body{margin:0}
75
76
  <div style="display: flex; flex-direction: column; gap: 12px; padding: 18px; border-radius: 12px; border: 1px solid #2a4566; background: #0f1d31; box-shadow: 0 10px 30px rgba(0,0,0,0.5)">
76
77
  <div style="display: flex; align-items: baseline; gap: 10px"><span style="font-size: 15px; font-weight: 600; flex: 1">Move “Pricing research” to the workspace</span><span style="font-size: 11px; color: #6b7d94">from Personal / Pricing drafts</span></div>
77
78
  <label style="display: flex; flex-direction: column; gap: 4px"><span style="font-size: 12px; color: #8ea3bd">Workspace folder</span>
78
- <span style="display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px; border-radius: 6px; border: 1px solid #2a4566; background: #13243b; font-size: 13px"><span style="width: 8px; height: 8px; border-radius: 3px; background: #7C9CFF"></span>Research / Pricing<span style="flex: 1"></span><span style="color: #6b7d94">▾</span></span></label>
79
+ <span style="display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px; border-radius: 6px; border: 1px solid #2a4566; background: #13243b; font-size: 13px"><svg width="13" height="13" viewBox="0 0 24 24" style="{{s.icon}}"><path d="{{i.folder}}"></path></svg>Research / Pricing<span style="flex: 1"></span><span style="{{s.inh}}"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{i.research}}"></path></svg>↳ Research</span><span style="color: #6b7d94">▾</span></span></label>
79
80
  <div style="display: flex; flex-direction: column; gap: 6px; padding: 12px; border-radius: 8px; background: #13243b; font-size: 12px">
80
81
  <span style="font-weight: 600">What changes</span>
81
82
  <sc-for list="{{effects}}" as="e" hint-placeholder-count="4"><div style="display: flex; gap: 8px; color: #b9c6d6"><span style="color: {{e.c}}; flex-shrink: 0">{{e.g}}</span><span>{{e.t}}</span></div></sc-for>
@@ -86,6 +87,7 @@ body{margin:0}
86
87
 
87
88
  <aside aria-label="Board details" style="position: absolute; left: 1140px; top: 0; width: 300px; height: 1000px; box-sizing: border-box; padding: 20px 18px; background: #0b1828; border-left: 1px solid #1b2c44; display: flex; flex-direction: column; gap: 14px">
88
89
  <div style="display: flex; flex-direction: column; gap: 2px"><span style="font-size: 11px; color: #6b7d94">Workspace · Decisions</span><span style="font-size: 15px; font-weight: 600">Q4 pricing decision</span><span style="font-size: 11px; color: #8ea3bd">You can read · 3 editors · 12 members can read</span></div>
90
+ <div style="display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; border-radius: 8px; background: #0f1d31; border: 1px solid #1b2c44"><div style="display: flex; align-items: center; gap: 8px"><span style="{{s.inh}}"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{i.decision}}"></path></svg>↳ Decision</span><span style="font-size: 11px; color: #8ea3bd; flex: 1">durable</span><span style="{{s.due}}"><svg width="10" height="10" viewBox="0 0 24 24" style="{{s.icChip}}"><path d="{{i.glass}}"></path></svg>1 due</span></div><span style="font-size: 11px; color: #b9c6d6">No passive expiry. One card is due because a newer decision on C4 2026 OKR planning supersedes it.</span><span style="font-size: 11px; color: #6b7d94">Last validated 9 d ago by Mia · reviews are shared; pins are not</span></div>
89
91
  <div style="display: flex; flex-direction: column; gap: 4px">
90
92
  <span style="{{s.secInline}} padding: 0">Links · 4</span>
91
93
  <sc-for list="{{links}}" as="lk" hint-placeholder-count="4">
@@ -113,7 +115,13 @@ class Component extends DCLogic {
113
115
  lock: 'M7 11h10v9H7zM9 11V8a3 3 0 0 1 6 0v3',
114
116
  folder: 'M4 7a1 1 0 0 1 1-1h4l2 2h8a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1z',
115
117
  share: 'M8 12a2 2 0 1 0 0 .01M16 7a2 2 0 1 0 0 .01M16 17a2 2 0 1 0 0 .01M9.8 11l4.4-3M9.8 13l4.4 3',
116
- arrow: 'M5 12h14M13 6l6 6-6 6'
118
+ arrow: 'M5 12h14M13 6l6 6-6 6',
119
+ strategy: 'M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18M15.5 8.5l-2 5-5 2 2-5z',
120
+ decision: 'M6 3v18M6 7h10l3 3-3 3H6',
121
+ research: 'M10.5 4a6.5 6.5 0 1 0 0 13a6.5 6.5 0 1 0 0-13M15.5 15.5L20 20',
122
+ notes: 'M4 20l4.2-1L19 8.2 15.8 5 5 15.8z',
123
+ unknown: 'M9.5 9.5a2.5 2.5 0 1 1 3.5 2.3c-.6.3-1 .8-1 1.5v.7M12 16.8v.4',
124
+ glass: 'M7 3h10M7 21h10M8 3v3l4 6-4 6v3M16 3v3l-4 6 4 6v3'
117
125
  };
118
126
  var rowBase = 'display:flex;align-items:center;gap:8px;height:30px;padding:0 8px;border-radius:6px;';
119
127
  var pinOn = 'width:16px;height:16px;border-radius:999px;display:flex;align-items:center;justify-content:center;flex-shrink:0;background:#4BBCFF;color:#081524;';
@@ -128,24 +136,32 @@ class Component extends DCLogic {
128
136
  name: 'flex:1;min-width:0;font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;',
129
137
  icon: 'fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;color:#8ea3bd;',
130
138
  ic2: 'fill:none;stroke:currentColor;stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round;',
139
+ icCat: 'fill:none;stroke:#8ea3bd;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0;',
140
+ icChip: 'fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0;',
141
+ due: 'display:inline-flex;align-items:center;gap:3px;height:18px;box-sizing:border-box;padding:0 6px;border-radius:999px;border:1px solid rgba(244,197,66,0.6);color:#f4c542;font-size:11px;font-weight:500;flex-shrink:0;',
142
+ set: 'display:inline-flex;align-items:center;gap:4px;height:20px;box-sizing:border-box;padding:0 6px;border-radius:6px;border:1px solid #2a4566;color:#e6eef7;font-size:11px;flex-shrink:0;',
143
+ inh: 'display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 2px;color:#8ea3bd;font-size:11px;flex-shrink:0;',
144
+ unk: 'display:inline-flex;align-items:center;gap:4px;height:20px;box-sizing:border-box;padding:0 6px;border-radius:6px;border:1px dashed #3d5170;color:#8ea3bd;font-size:11px;flex-shrink:0;',
131
145
  pinOn: pinOn,
132
146
  tab: 'height:28px;padding:0 12px;border:0;border-radius:6px;background:transparent;color:#8ea3bd;font-family:inherit;font-size:12px;font-weight:500;',
133
147
  tabOn: 'height:28px;padding:0 12px;border:0;border-radius:6px;background:#1b2c44;color:#e6eef7;font-family:inherit;font-size:12px;font-weight:500;'
134
148
  };
135
149
  var pinned = [
136
150
  { name: 'Q4 pricing decision', scope: 'workspace', tag: tagW },
137
- { name: 'C4 2026 OKR planning', scope: 'workspace', tag: tagW },
151
+ { name: 'C4 2026 OKR planning', scope: 'workspace', tag: tagW, hasDue: true, due: '3 due' },
138
152
  { name: 'Pricing research', scope: 'personal', tag: tagP }
139
153
  ];
140
- function w(name, role, depth, hue, sel) { return { name: name, role: role, indent: depth * 16, hue: hue, style: rowBase + (sel ? 'background:#13243b;' : '') }; }
154
+ var cn = { strategy: 'Strategy', decision: 'Decision', research: 'Research', notes: 'Notes' };
155
+ function cat(c, mode) { return { catIcon: mode === 'unk' ? i.unknown : i[c], tag: mode === 'unk' ? 'unknown' : (mode === 'inh' ? '↳ ' : '') + cn[c], tagSt: mode === 'set' ? s.set : mode === 'inh' ? s.inh : s.unk }; }
156
+ function w(name, role, depth, c, mode, d, sel) { var o = cat(c, mode); o.name = name; o.role = role; o.indent = depth * 16; o.hasDue = !!d; o.due = d ? d + ' due' : ''; o.style = rowBase + (sel ? 'background:#13243b;' : ''); return o; }
141
157
  var workspace = [
142
- w('Tech Enabling', 'edit', 0, '#5FCFC0'), w('OKRs', 'edit', 1, '#5FCFC0'),
143
- w('Research', 'edit', 0, '#7C9CFF'), w('Decisions', 'read', 0, '#E58FB0'), w('Workshops', 'comment', 0, '#E59B6B')
158
+ w('Tech Enabling', 'edit', 0, 'strategy', 'set', 0), w('OKRs', 'edit', 1, 'strategy', 'inh', 3),
159
+ w('Research', 'edit', 0, 'research', 'set', 1), w('Decisions', 'read', 0, 'decision', 'set', 1), w('Workshops', 'comment', 0, 'notes', 'set', 0)
144
160
  ];
145
- function p(name, n, depth, sel, icon) { return { name: name, n: n, indent: depth * 16, icon: icon || i.folder, style: rowBase + (sel ? 'background:#13243b;' : '') }; }
146
- var personal = [p('Pricing drafts', 3, 0, true), p('1:1 prep', 4, 0), p('Reading notes', 9, 0), p('Scratch', 2, 0)];
161
+ function p(name, n, depth, c, mode, d, sel) { var o = cat(c, mode); o.name = name; o.n = n; o.indent = depth * 16; o.icon = i.folder; o.hasDue = !!d; o.due = d ? d + ' due' : ''; o.style = rowBase + (sel ? 'background:#13243b;' : ''); return o; }
162
+ var personal = [p('Pricing drafts', 3, 0, 'research', 'set', 1, true), p('1:1 prep', 4, 0, 'notes', 'set', 0), p('Reading notes', 9, 0, 'notes', 'set', 0), p('Scratch', 2, 0, '', 'unk', 0)];
147
163
  var boards = [
148
- { name: 'Pricing research', access: 'Only you', icon: i.lock, pinStyle: pinOn18, border: '1.5px solid #4BBCFF' },
164
+ { name: 'Pricing research', access: 'Only you', icon: i.lock, pinStyle: pinOn18, border: '1.5px solid #4BBCFF', hasDue: true, due: '1 due' },
149
165
  { name: 'Churn deep-dive', access: 'Shared with 2 people', icon: i.share, pinStyle: pinOff18, border: '1px solid #1b2c44' },
150
166
  { name: 'Price page copy', access: 'Only you', icon: i.lock, pinStyle: pinOff18, border: '1px solid #1b2c44' }
151
167
  ];
@@ -153,6 +169,7 @@ class Component extends DCLogic {
153
169
  { g: '+', c: '#2fd07f', t: 'All 12 members of Tech Enabling team can read it; editors of Research can change it.' },
154
170
  { g: '+', c: '#2fd07f', t: 'It can appear in teammates’ search, Map and Graph — and in their agents’ briefs if they pin it.' },
155
171
  { g: '=', c: '#8ea3bd', t: 'Your pins stay yours. Its links to your other personal boards stay locked for everyone else.' },
172
+ { g: '=', c: '#8ea3bd', t: 'It takes the new folder’s category (Research, unchanged here). Cards that set their own lifecycle keep it; review history moves with the board.' },
156
173
  { g: '!', c: '#f4c542', t: 'Moving is the step that shares it. Nothing becomes shared through a link, a pin or an agent edit.' }
157
174
  ];
158
175
  var links = [
@@ -166,6 +183,7 @@ class Component extends DCLogic {
166
183
  { t: 'Crossing over is explicit:', d: 'share (per-board roles) or move into a workspace folder.' },
167
184
  { t: 'Pins are yours;', d: 'the board README is the shared default.' },
168
185
  { t: 'Agents act as you,', d: 'with your rights, never reading others’ personal boards.' },
186
+ { t: 'A category is not access:', d: 'it says what a folder holds, never who may read it.' },
169
187
  { t: 'Local installs', d: 'have one scope; this arrives with step 5.' }
170
188
  ];
171
189
  return { s: s, i: i, pinned: pinned, workspace: workspace, personal: personal, boards: boards, effects: effects, links: links, rules: rules };
@@ -0,0 +1,22 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head><meta charset="utf-8"><title>V2 · Docked card review</title><script src="./support.js"></script></head>
4
+ <body><x-dc>
5
+ <helmet>
6
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&amp;family=IBM+Plex+Sans:wght@400;500;600&amp;display=swap">
7
+ <style>
8
+ body{margin:0}.v2{width:1440px;height:1420px;box-sizing:border-box;padding:48px;background:#081524;color:#e6eef7;font:13px/1.5 'IBM Plex Sans',system-ui,sans-serif}.v2 h1{font-size:28px;margin:0}.v2 p,.v2 small{color:#8ea3bd}.v2 .workspace{display:flex;height:600px;border:1px solid #1b2c44;border-radius:10px;overflow:hidden;margin:28px 0}.v2 .canvas{flex:1;padding:24px;background-image:radial-gradient(#1b2c44 1px,transparent 1px);background-size:24px 24px}.v2 .card{margin:48px auto;width:560px;height:370px;border:1px solid #1b2c44;border-radius:10px;background:#0f1d31;box-sizing:border-box;padding:20px}.v2 .dock{width:380px;flex-shrink:0;box-sizing:border-box;padding:16px;background:#0f1d31;border-left:1px solid #1b2c44}.v2 header{display:flex;align-items:center;gap:8px;border-bottom:1px solid #1b2c44;padding-bottom:12px}.v2 header strong{flex:1;font-size:15px}.v2 button,.v2 textarea{font:inherit;color:inherit;border:1px solid #1b2c44;border-radius:6px;background:#081524;padding:7px 10px;box-sizing:border-box}.v2 .primary{background:#4BBCFF;color:#081524;border-color:transparent;font-weight:600}.v2 .warning{border:1px solid #f4c542;color:#f4c542;border-radius:6px;padding:6px 8px}.v2 .note{display:flex;flex-direction:column;gap:6px;margin:20px 0}.v2 textarea{width:100%;height:90px}.v2 .settings{border-top:1px solid #1b2c44;margin-top:20px;padding-top:12px;color:#8ea3bd}.v2 .states{display:grid;grid-template-columns:1fr 1fr;gap:20px}.v2 .states section{background:#0f1d31;border:1px solid #1b2c44;border-radius:10px;padding:20px}.v2 .clocks{display:grid;grid-template-columns:1fr 1fr;gap:12px}.v2 .clocks div{padding:12px;border-radius:10px;background:#13243b}.v2 .clocks strong{display:block}.v2 .source{color:#b9c6d6;text-decoration:underline}
9
+ </style></helmet>
10
+ <main class="v2"><h1>V2 · Review beside the real card</h1><p>Selected 2026-10-14 · local implementation, validation ongoing. More → Review / due footer / expanded Review opens the dock and focuses the actual renderer.</p>
11
+ <div class="workspace">
12
+ <section class="canvas"><strong>Product metrics · board canvas</strong><article class="card"><header><strong>Churn by month</strong><span>⋯</span></header><h2 style="font-size:20px">September churn: 4.2%</h2><p>Calculated from the billing dashboard. Compare the monthly report and source observations before relying on this figure.</p><p class="source">Billing dashboard →</p><div style="display:flex;align-items:end;gap:12px;height:100px;margin:24px 0"><span style="width:44px;height:52px;background:#2a4566"></span><span style="width:44px;height:70px;background:#2a4566"></span><span style="width:44px;height:62px;background:#2a4566"></span><span style="width:44px;height:84px;background:#2a4566"></span></div><span class="warning">⧗ review due · source refreshed</span></article><small>Actual rendered card remains on the canvas, not a replacement excerpt. Expanded content also keeps its renderer beside the dock.</small></section>
13
+ <aside class="dock"><header><strong>Review card · Churn by month</strong><button>×</button></header><h3>Why review?</h3><p class="warning">⧗ Source needs a check: Billing dashboard</p><button>Open source →</button><p>Check the card and its sources before confirming.</p><label class="note">What did you check?<textarea>Compared September figure with the billing dashboard; 4.2% matches.</textarea></label><button class="primary">Checked, still correct</button> <button>Not now</button><div class="settings">▸ Settings and history</div><p>One check note; policy, clocks, other outcomes and history are secondary.</p></aside>
14
+ </div>
15
+ <div class="states">
16
+ <section><strong>Settings and history · disclosed</strong><p>↳ Metric · from Projects / Metrics. Inherit policy or set a card lifecycle override; never change category here.</p><div class="clocks"><div><span style="color:#B388FF">Read by agent</span><strong>2 hours ago</strong><small>Delivery only</small></div><div>Content changed<strong>40 minutes ago</strong><small>Content revision 7</small></div><div>Last validated<strong>41 days ago</strong><small>Evidence-backed check</small></div><div>Task relevance<strong>Card pinned</strong><small>Curation, not truth</small></div></div><p>Retain / Revise / Externalize / Retire / Unresolved. Uses the same check note; applied validating outcomes require evidence. Revise/externalize record work already performed, not automatic edits.</p><p>History: outcome · evidence · who · when. Retire stays dimmed/searchable; Restore and Undo retirement are audited and never validate. Recipe requests send steering, not execution.</p></section>
17
+ <section><strong>Guards and no-write dismissal</strong><p class="warning">⧗ Content or sources changed. Reload and recheck before applying.</p><button>Reload and recheck</button><p>Reload clears the old evidence draft. Never attach a fresh revision token to evidence for an older body or source.</p><p>Save dirty Markdown, reload and check again before validating. Missing evidence, failed load/save or stale revision blocks Checked, still correct.</p><p>Not now, × and Escape close without writing a review. Opening, reading, refreshing and restoration never validate.</p><p>At narrow widths the drawer becomes a lower dock; the card remains visible above (Lifecycle600). Needs review is not false. Review due stays amber outlined ⧗; changed since read is the separate filled △ header mark.</p></section>
18
+ </div><p>Brief qualification preserves due reasons, source warnings and unknown policy. Healthy cards gain no lifecycle badge. All nine themes reuse their warning token; no category hue or relation ink carries review status.</p>
19
+ </main></x-dc>
20
+ <script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":1440,"height":1420}}'>
21
+ class Component extends DCLogic { renderVals() { return {}; } }
22
+ </script></body></html>
@@ -0,0 +1,18 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head><meta charset="utf-8"><title>Selected review surfaces at 600 px</title><script src="./support.js"></script></head>
4
+ <body><x-dc><helmet>
5
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&amp;family=IBM+Plex+Sans:wght@400;500;600&amp;display=swap">
6
+ <style>
7
+ body{margin:0}.narrow{width:600px;height:1470px;box-sizing:border-box;padding:24px 16px;background:#081524;color:#e6eef7;font:12px/1.5 'IBM Plex Sans',system-ui,sans-serif}.narrow h1{font-size:20px;margin:0}.narrow h2{font-size:15px;margin:0}.narrow p{color:#8ea3bd}.narrow section{border:1px solid #1b2c44;border-radius:10px;background:#0f1d31;padding:14px;margin:16px 0}.narrow button,.narrow input,.narrow select,.narrow textarea{font:inherit;color:inherit;background:#081524;border:1px solid #1b2c44;border-radius:6px;padding:6px 8px;box-sizing:border-box}.narrow .selected{border-color:#e6eef7;background:#13243b}.narrow .primary{background:#4BBCFF;color:#081524;border-color:transparent;font-weight:600}.narrow header{display:flex;justify-content:space-between;align-items:center}.narrow .warning{color:#f4c542;border:1px solid #f4c542;border-radius:6px;padding:4px 7px}.narrow .lower{margin:0;padding:14px;border:0;border-top:1px solid #1b2c44;border-radius:0}.narrow label{display:flex;flex-direction:column;gap:5px;margin:10px 0}.narrow .workspace{border:1px solid #1b2c44;border-radius:10px;overflow:hidden;background:#0f1d31;margin:16px 0}.narrow .canvas{height:210px;padding:16px;box-sizing:border-box;background:#081524;background-image:radial-gradient(#1b2c44 1px,transparent 1px);background-size:24px 24px}.narrow .card{padding:12px;background:#0f1d31;border:1px solid #1b2c44;border-radius:10px;margin:12px auto;width:420px}.narrow small{color:#8ea3bd}
8
+ .narrow{height:1800px}
9
+ </style></helmet>
10
+ <main class="narrow"><h1>Selected directions · at 600 px</h1><p>C1 / H2 / V2 · selected 2026-10-14. Local implementation; validation ongoing.</p>
11
+ <section><header><h2>C1 · Workspace categories</h2><button>×</button></header><details><summary>Add from template</summary></details><label>Search categories<input placeholder="Search categories"></label><div style="display:flex;gap:6px"><button class="selected">⌕ Research</button><button>⚑ Decision</button><button>+ Add</button></div><div style="display:flex;gap:6px;margin-top:12px"><button>Basics</button><button class="selected">Review policy</button><button>Usage</button></div><label>Review frequency<select><option>Medium · every 90 days</option></select></label><label>How to check<input value="Check sources and conflicting evidence"></label><details><summary>Additional review triggers</summary></details><div style="text-align:right;margin-top:12px"><button>Cancel</button> <button class="primary">Save category</button></div><small>Neutral list; dirty-leave guard and assigned-folder deletion protection remain.</small></section>
12
+ <section><h2>H2 · Knowledge review</h2><p>Folders · Map · Graph · <strong style="color:#e6eef7">Review</strong></p><label>Review scope<select><option>Projects and descendants</option><option>Whole library</option></select></label><label>Find review cards<input type="search"></label><p>□ Source warnings only · Refresh queue</p><strong>Review needed: 2 cards · Showing 2</strong><div style="border:1px solid #1b2c44;border-radius:10px;padding:10px;margin:10px 0"><strong>Card: Churn by month</strong><p>Board: Product metrics<br>Why review: Billing dashboard changed<br>Last checked: 12 September</p><button>Open review</button></div><small>Second row: Launch assumptions · Launch plan · Scheduled check due · Never checked.</small><p>No review policy: 4 cards. Neutral, not overdue; explicit warnings still qualify.</p></section>
13
+ <h2>V2 · Lower dock, not a covering modal</h2>
14
+ <div class="workspace"><div class="canvas"><strong>Product metrics</strong><article class="card"><h2>Churn by month</h2><p>September churn: 4.2%. Calculated from the billing dashboard.</p><span class="warning">⧗ review due · source refreshed</span></article></div><section class="lower"><header><h2>Review card · Churn by month</h2><button>×</button></header><p class="warning">⧗ Source needs a check: Billing dashboard</p><button>Open source →</button><label>What did you check?<textarea rows="2" placeholder="A short note or source link"></textarea></label><button class="primary" style="opacity:0.5">Checked, still correct</button> <button>Not now</button><p>▸ Settings and history</p><small>Disabled until evidence and current saved content/source observations are checked. Close/Escape/Not now write nothing. Real card remains visible above.</small></section></div>
15
+ </main></x-dc>
16
+ <script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":600,"height":1800}}'>
17
+ class Component extends DCLogic { renderVals() { return {}; } }
18
+ </script></body></html>
@@ -0,0 +1,157 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Lifecycle on the board or in a menu</title>
6
+ <script src="./support.js"></script>
7
+ </head>
8
+ <body>
9
+ <x-dc>
10
+ <helmet>
11
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&amp;family=IBM+Plex+Sans:wght@400;500;600&amp;display=swap">
12
+ <style>
13
+ body{margin:0}
14
+ </style>
15
+ </helmet>
16
+ <div style="width: 1440px; height: 1100px; box-sizing: border-box; padding: 40px 48px; background: #081524; color: #e6eef7; font-family: 'IBM Plex Sans', system-ui, sans-serif; font-size: 13px; line-height: 1.5; display: flex; flex-direction: column; gap: 20px">
17
+
18
+ <div>
19
+ <h1 style="margin: 0; font-size: 28px; font-weight: 600; letter-spacing: -0.015em">How much lifecycle shows on the board — A, decided 2026-10-07</h1>
20
+ <p style="margin: 4px 0 0; font-size: 13px; color: #8ea3bd">Both move everything into the card’s ⋯ → Lifecycle: rate and decay type, inherited or set, the four clocks, outcome history. “Unknown” shows only on Home folders, never on a card. The one question is where “review due” lives.</p>
21
+ </div>
22
+
23
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 32px">
24
+ <sc-for list="{{variants}}" as="v" hint-placeholder-count="2">
25
+ <section style="display: flex; flex-direction: column; gap: 10px; min-width: 0">
26
+ <div style="display: flex; align-items: baseline; gap: 10px"><span style="{{s.letter}}">{{v.k}}</span><span style="font-size: 15px; font-weight: 600">{{v.name}}</span></div>
27
+ <span style="font-size: 12px; color: #8ea3bd">{{v.sub}}</span>
28
+ <div style="position: relative; height: 420px; border-radius: 10px; border: 1px solid #1b2c44; background-color: #081524; background-image: radial-gradient(rgba(142,163,189,0.14) 1px, transparent 1.2px); background-size: 24px 24px; overflow: hidden">
29
+ <div style="position: absolute; left: 0; right: 0; top: 0; height: 44px; display: flex; align-items: center; gap: 8px; padding: 0 12px; background: #0f1d31; border-bottom: 1px solid #1b2c44">
30
+ <span style="font-size: 13px; font-weight: 600; flex: 1">Pricing strategy 2027</span>
31
+ <span style="{{s.ctxChip}}">3 cards in context</span>
32
+ <span style="{{v.countSt}}"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.ic}}"><path d="{{i.glass}}"></path></svg>2 to review</span>
33
+ </div>
34
+ <sc-for list="{{v.cards}}" as="c" hint-placeholder-count="4">
35
+ <div style="{{c.node}}">
36
+ <div style="{{c.head}}"><span style="{{s.title}}">{{c.title}}</span>
37
+ <sc-if value="{{c.changed}}" hint-placeholder-val="{{ false }}"><span style="{{s.changedChip}}"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.ic}}"><path d="{{i.warn}}"></path></svg>changed</span></sc-if>
38
+ <sc-if value="{{c.pin}}" hint-placeholder-val="{{ false }}"><span style="{{s.pinOn}}"><svg width="10" height="10" viewBox="0 0 24 24" style="{{s.icPin}}"><path d="{{i.pin}}"></path></svg></span></sc-if>
39
+ </div>
40
+ <div style="{{s.body}}">{{c.body}}</div>
41
+ <sc-if value="{{c.due}}" hint-placeholder-val="{{ false }}"><div style="{{s.dueLine}}"><span style="{{s.reviewChip}}"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.ic}}"><path d="{{i.glass}}"></path></svg>review due</span><span style="font-size: 11px; color: #8ea3bd; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">{{c.dueWhy}}</span></div></sc-if>
42
+ </div>
43
+ </sc-for>
44
+ <sc-if value="{{v.popover}}" hint-placeholder-val="{{ false }}">
45
+ <div style="position: absolute; right: 12px; top: 50px; width: 290px; box-sizing: border-box; padding: 10px; border-radius: 10px; border: 1px solid #2a4566; background: #13243b; box-shadow: 0 10px 30px rgba(0,0,0,0.6); display: flex; flex-direction: column; gap: 4px">
46
+ <span style="font-size: 11px; color: #8ea3bd; padding: 0 4px 2px">To review on this board</span>
47
+ <sc-for list="{{queue}}" as="q" hint-placeholder-count="2"><div style="display: flex; flex-direction: column; padding: 6px 8px; border-radius: 6px; background: #0f1d31"><span style="font-size: 12px; font-weight: 500">{{q.t}}</span><span style="font-size: 11px; color: #8ea3bd">{{q.why}}</span></div></sc-for>
48
+ <span style="font-size: 11px; color: #8ea3bd; padding: 2px 4px 0">Click a row to jump to the card</span>
49
+ </div>
50
+ </sc-if>
51
+ </div>
52
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px">
53
+ <div style="{{s.panel}} padding: 12px 14px; gap: 4px"><span style="font-size: 12px; font-weight: 600; color: #e6eef7">Gains</span><sc-for list="{{v.pros}}" as="p" hint-placeholder-count="3"><span style="font-size: 11px; color: #b9c6d6">+ {{p}}</span></sc-for></div>
54
+ <div style="{{s.panel}} padding: 12px 14px; gap: 4px"><span style="font-size: 12px; font-weight: 600; color: #e6eef7">Costs</span><sc-for list="{{v.cons}}" as="p" hint-placeholder-count="3"><span style="font-size: 11px; color: #b9c6d6">− {{p}}</span></sc-for></div>
55
+ </div>
56
+ </section>
57
+ </sc-for>
58
+ </div>
59
+
60
+ <div style="display: grid; grid-template-columns: 420px minmax(0, 1fr); gap: 32px">
61
+ <section style="display: flex; flex-direction: column; gap: 10px">
62
+ <span style="{{s.label}}">Same in A and B — the card’s ⋯ menu</span>
63
+ <div style="position: relative; height: 230px; border-radius: 10px; border: 1px solid #1b2c44; background: #081524">
64
+ <div style="position: absolute; left: 16px; top: 16px; width: 300px; height: 40px; box-sizing: border-box; display: flex; align-items: center; gap: 6px; padding: 0 8px 0 12px; border-radius: 10px 10px 0 0; border: 1.5px solid #4BBCFF; border-bottom: 0; background: rgba(75,188,255,0.10)"><span style="{{s.title}}">Churn by month</span><span style="width: 24px; height: 24px; border-radius: 6px; background: #1b2c44; display: flex; align-items: center; justify-content: center">⋯</span></div>
65
+ <div role="menu" style="position: absolute; left: 150px; top: 52px; width: 250px; box-sizing: border-box; padding: 6px; border-radius: 10px; border: 1px solid #2a4566; background: #13243b; box-shadow: 0 10px 30px rgba(0,0,0,0.6); display: flex; flex-direction: column; gap: 2px">
66
+ <sc-for list="{{menu}}" as="m" hint-placeholder-count="6"><div style="{{m.st}}"><span style="flex: 1">{{m.n}}</span><span style="{{m.hintSt}}">{{m.h}}</span></div></sc-for>
67
+ </div>
68
+ </div>
69
+ <span style="font-size: 11px; color: #8ea3bd">Lifecycle… opens the tab drawn on Lifecycle and Restore. Its row shows a one-word summary so the menu itself answers “anything to do here?”.</span>
70
+ </section>
71
+
72
+ <section style="display: flex; flex-direction: column; gap: 10px">
73
+ <span style="{{s.label}}">Design session’s recommendation — A</span>
74
+ <div style="{{s.panel}} padding: 16px 18px; gap: 10px; border-color: #2a4566">
75
+ <span style="font-size: 15px; font-weight: 600">The human should see what the agent is told</span>
76
+ <span style="font-size: 12px; color: #b9c6d6">The brief already carries “review due: check the source before relying on it” on Churn by month. In B that card looks clean on the board while the agent is told to doubt it, so the human and the agent are looking at two different boards. That is the same gap the pin and the “changed” mark were designed to close.</span>
77
+ <span style="font-size: 12px; color: #b9c6d6">A costs one quiet line, on only the cards that are due — 2 of the 4 here, and on a real board usually a small share. Everything else (rates, clocks, history, inheritance, unknown) still goes into the menu, which keeps the maintainer’s “not on the board” for everything that isn’t a call to act.</span>
78
+ <span style="font-size: 12px; color: #b9c6d6">If B is chosen, keep one tie to the card: the count popover lists the cards and jumps to them, and the brief panel names them, so the mismatch is at least one click away.</span>
79
+ <span style="font-size: 11px; color: #8ea3bd">Either way the Lifecycle board’s at-rest card lines are replaced by the chosen variant once decided.</span>
80
+ </div>
81
+ </section>
82
+ </div>
83
+
84
+ </div>
85
+ </x-dc>
86
+ <script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":1440,"height":1100}}'>
87
+ class Component extends DCLogic {
88
+ renderVals() {
89
+ var i = {
90
+ glass: 'M7 3h10M7 21h10M8 3v3l4 6-4 6v3M16 3v3l-4 6 4 6v3',
91
+ warn: 'M12 4l9 16H3zM12 10v4M12 17v.5',
92
+ pin: 'M9 4h6l-.8 5.5 2.8 3H7l2.8-3zM12 12.5V20'
93
+ };
94
+ var W = '#f4c542';
95
+ var chip = 'display:inline-flex;align-items:center;gap:4px;height:20px;box-sizing:border-box;padding:0 7px;border-radius:999px;font-size:11px;font-weight:500;flex-shrink:0;';
96
+ var s = {
97
+ label: 'font-size:11px;font-weight:500;letter-spacing:0.06em;text-transform:uppercase;color:#6b7d94;',
98
+ panel: 'display:flex;flex-direction:column;border-radius:10px;border:1px solid #1b2c44;background:#0f1d31;',
99
+ letter: 'width:26px;height:26px;border-radius:999px;background:#1b2c44;font-size:13px;font-weight:600;text-align:center;line-height:26px;flex-shrink:0;',
100
+ ic: 'fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0;',
101
+ icPin: 'fill:none;stroke:currentColor;stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round;',
102
+ ctxChip: 'display:inline-flex;align-items:center;height:24px;padding:0 9px;border-radius:999px;border:1px solid rgba(75,188,255,0.3);color:#4BBCFF;font-size:11px;font-weight:500;',
103
+ changedChip: chip + 'color:' + W + ';background:rgba(244,197,66,0.14);',
104
+ reviewChip: chip + 'color:' + W + ';border:1px solid rgba(244,197,66,0.6);',
105
+ pinOn: 'width:18px;height:18px;border-radius:999px;background:#4BBCFF;color:#081524;display:flex;align-items:center;justify-content:center;flex-shrink:0;',
106
+ title: 'flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:12px;font-weight:600;',
107
+ body: 'padding:8px 12px;font-size:12px;color:#b9c6d6;',
108
+ dueLine: 'position:absolute;left:0;right:0;bottom:0;height:32px;box-sizing:border-box;display:flex;align-items:center;gap:8px;padding:0 10px;border-top:1px solid #1b2c44;'
109
+ };
110
+ var countOn = chip + 'height:24px;color:' + W + ';border:1px solid rgba(244,197,66,0.6);';
111
+ var countOpen = countOn + 'background:rgba(244,197,66,0.14);';
112
+ var nodeBase = 'position:absolute;box-sizing:border-box;border-radius:10px;background:#0f1d31;box-shadow:0 1px 2px rgba(0,0,0,0.4),0 6px 20px rgba(0,0,0,0.24);overflow:hidden;';
113
+ var headBase = 'display:flex;align-items:center;gap:6px;height:34px;padding:0 8px 0 12px;border-bottom:1px solid #1b2c44;';
114
+ function cards(showDue) {
115
+ function c(o) {
116
+ return {
117
+ title: o.title, body: o.body, pin: !!o.pin, changed: !!o.changed, due: showDue && !!o.due, dueWhy: o.dueWhy || '',
118
+ node: nodeBase + 'left:' + o.x + 'px;top:' + o.y + 'px;width:300px;height:' + o.h + 'px;' + (o.pin ? 'border:1.5px solid #4BBCFF;' : 'border:1px solid #1b2c44;'),
119
+ head: headBase + (o.pin ? 'background:rgba(75,188,255,0.10);' : '')
120
+ };
121
+ }
122
+ return [
123
+ c({ x: 16, y: 64, h: 140, pin: true, title: 'Positioning: premium SMB', body: 'Lead with reliability and support; do not compete on price below $20.' }),
124
+ c({ x: 16, y: 220, h: 180, pin: true, changed: true, due: true, title: 'Churn by month', body: 'Pro plan, monthly logo churn, last 12 months.', dueWhy: 'source refreshed' }),
125
+ c({ x: 332, y: 64, h: 140, title: 'Competitor price list', body: 'Six competitors, list prices as of September.' }),
126
+ c({ x: 332, y: 220, h: 180, pin: true, due: true, title: 'Win rate vs. Competitor B', body: 'Q3 win rate by segment, from the CRM export.', dueWhy: 'contradicted by Q3 loss reasons' })
127
+ ];
128
+ }
129
+ var queue = [
130
+ { t: 'Churn by month', why: 'fast · source refreshed · validated 41 d ago' },
131
+ { t: 'Win rate vs. Competitor B', why: 'contradicted by “Q3 loss reasons”' }
132
+ ];
133
+ var variants = [
134
+ { k: 'A', name: 'Review due on the card, only while due', sub: 'Chosen by the maintainer, 2026-10-07. Recommended by the roadmap and design sessions. The line appears when a review is due and goes away when an outcome is recorded.',
135
+ countSt: countOn, popover: false, cards: cards(true),
136
+ pros: ['You see on the card what the agent’s brief says about it', 'No click needed to find which cards are due', 'Quiet: nothing on cards that are fine'],
137
+ cons: ['One line of chrome on due cards', 'A board with many due cards gets busier', 'Two amber marks can meet on one card'] },
138
+ { k: 'B', name: 'Review due only in the menu, a count on the board', sub: 'Not chosen. Cards stay clean apart from “changed”; the count (and the context chip) opens the list.',
139
+ countSt: countOpen, popover: true, cards: cards(false),
140
+ pros: ['Cards stay completely clean', 'One place to work the reviews from', 'Scales to boards with many due cards'],
141
+ cons: ['A due card looks the same as a fine one', 'The agent is told to doubt a card you see as clean', 'Finding a card means opening the count first'] }
142
+ ];
143
+ var mBase = 'display:flex;align-items:center;height:28px;padding:0 10px;border-radius:6px;font-size:12px;';
144
+ var hint = 'font-size:11px;color:#6b7d94;';
145
+ var menu = [
146
+ { n: 'Focus', h: '', st: mBase, hintSt: hint },
147
+ { n: 'Rename…', h: '', st: mBase, hintSt: hint },
148
+ { n: 'Lifecycle…', h: '⧗ review due', st: mBase + 'background:#1b2c44;', hintSt: 'font-size:11px;color:' + W + ';' },
149
+ { n: 'Open in new tab', h: '', st: mBase, hintSt: hint },
150
+ { n: 'Delete', h: '⌫', st: mBase, hintSt: hint }
151
+ ];
152
+ return { i: i, s: s, variants: variants, queue: queue, menu: menu };
153
+ }
154
+ }
155
+ </script>
156
+ </body>
157
+ </html>
@@ -0,0 +1,139 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Who drew a link</title>
6
+ <script src="./support.js"></script>
7
+ </head>
8
+ <body>
9
+ <x-dc>
10
+ <helmet>
11
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&amp;family=IBM+Plex+Sans:wght@400;500;600&amp;display=swap">
12
+ <style>
13
+ body{margin:0}
14
+ </style>
15
+ </helmet>
16
+ <div style="width: 1440px; height: 1550px; box-sizing: border-box; padding: 40px 48px; background: #081524; color: #e6eef7; font-family: 'IBM Plex Sans', system-ui, sans-serif; font-size: 13px; line-height: 1.5; display: flex; flex-direction: column; gap: 22px">
17
+
18
+ <div>
19
+ <h1 style="margin: 0; font-size: 28px; font-weight: 600; letter-spacing: -0.015em">Who drew a link</h1>
20
+ <p style="margin: 4px 0 0; font-size: 13px; color: #8ea3bd">Decided with the maintainer 2026-10-08. Authorship on a link works like a card’s: it stays until a person edits, retypes or relabels the link, and a later read does not clear it. On the pill it is a glyph — ✦ for an agent, an initial for another person on a shared board — and the words are in the pill’s hint. “Not seen by &lt;agent&gt;” is a different thing: a temporary, worded state on a person’s new link that the agent’s next read clears.</p>
21
+ </div>
22
+
23
+ <sc-for list="{{themes}}" as="th" hint-placeholder-count="2">
24
+ <section style="{{th.section}}">
25
+ <span style="{{th.label}}">{{th.name}}</span>
26
+ <div style="display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px 16px">
27
+ <sc-for list="{{th.scenes}}" as="sc" hint-placeholder-count="12">
28
+ <div style="display: flex; flex-direction: column; gap: 6px; min-width: 0">
29
+ <div style="display: flex; flex-direction: column"><span style="{{th.caseName}}">{{sc.name}}</span><span style="{{th.caseNote}}">{{sc.note}}</span></div>
30
+ <div style="{{sc.frame}}">
31
+ <svg width="300" height="96" viewBox="0 0 300 96" style="position: absolute; left: 0; top: 0; fill: none; stroke-linecap: round"><path d="M70 48 L 226 48" style="{{sc.line}}"></path><path d="M230 48 l-9 -4.5 v9 z" style="{{sc.head}}"></path></svg>
32
+ <div style="{{sc.stubL}}"></div><div style="{{sc.stubR}}"></div>
33
+ <sc-if value="{{sc.hasPill}}" hint-placeholder-val="{{ true }}"><span style="{{sc.pill}}">
34
+ <sc-if value="{{sc.agent}}" hint-placeholder-val="{{ false }}"><svg width="12" height="12" viewBox="0 0 24 24" style="{{sc.sparkSt}}"><path d="{{i.spark}}"></path></svg></sc-if>
35
+ <sc-if value="{{sc.person}}" hint-placeholder-val="{{ false }}"><span style="{{sc.initialSt}}">M</span></sc-if>
36
+ <sc-if value="{{sc.hasLabel}}" hint-placeholder-val="{{ true }}"><span>{{sc.label}}</span></sc-if>
37
+ <sc-if value="{{sc.notSeen}}" hint-placeholder-val="{{ false }}"><span style="{{sc.nsSt}}"><svg width="11" height="11" viewBox="0 0 24 24" style="{{s.ic}}"><path d="{{i.eyeOff}}"></path></svg>{{sc.nsWord}}</span></sc-if>
38
+ </span></sc-if>
39
+ <sc-if value="{{sc.hasHint}}" hint-placeholder-val="{{ false }}"><span style="{{sc.hintSt}}">{{sc.hint}}</span></sc-if>
40
+ </div>
41
+ </div>
42
+ </sc-for>
43
+ </div>
44
+ </section>
45
+ </sc-for>
46
+
47
+ <section style="display: grid; grid-template-columns: 1fr 1fr; gap: 24px">
48
+ <div style="{{s.panel}} padding: 16px 18px; gap: 8px">
49
+ <span style="font-size: 13px; font-weight: 600">The rule</span>
50
+ <sc-for list="{{rules}}" as="r" hint-placeholder-count="6"><span style="font-size: 12px; color: #b9c6d6">{{r}}</span></sc-for>
51
+ </div>
52
+ <div style="{{s.panel}} padding: 16px 18px; gap: 8px">
53
+ <span style="font-size: 13px; font-weight: 600">Hints — styled BarHints, never a title attribute</span>
54
+ <sc-for list="{{hints}}" as="h" hint-placeholder-count="4"><div style="display: flex; align-items: center; gap: 10px"><span style="{{h.st}}">{{h.t}}</span><span style="font-size: 11px; color: #8ea3bd">{{h.when}}</span></div></sc-for>
55
+ </div>
56
+ </section>
57
+
58
+ </div>
59
+ </x-dc>
60
+ <script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":1440,"height":1550}}'>
61
+ class Component extends DCLogic {
62
+ renderVals() {
63
+ var i = {
64
+ spark: 'M12 2l2.2 6.6L21 11l-6.8 2.4L12 20l-2.2-6.6L3 11l6.8-2.4z',
65
+ eyeOff: 'M3 3l18 18M10.6 6.1A10 10 0 0 1 12 6c6.5 0 10 6 10 6a17 17 0 0 1-3 3.6M6.6 6.6C3.8 8.3 2 12 2 12s3.5 6 10 6a9.6 9.6 0 0 0 4.4-1'
66
+ };
67
+ var s = {
68
+ panel: 'display:flex;flex-direction:column;border-radius:10px;border:1px solid #1b2c44;background:#0f1d31;',
69
+ ic: 'fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0;'
70
+ };
71
+ function hexA(h, a) { var n = parseInt(h.slice(1), 16); return 'rgba(' + (n >> 16 & 255) + ',' + (n >> 8 & 255) + ',' + (n & 255) + ',' + a + ')'; }
72
+ var H = { name: 'Harbor', bg: '#081524', panel: '#0f1d31', soft: '#13243b', line: '#1b2c44', line2: '#2a4566', text: '#e6eef7', textSoft: '#b9c6d6', muted: '#8ea3bd', dim: '#6b7d94', agent: '#B388FF', sup: '#5FCFC0', rel: '#8ea3bd', shadow: '0 10px 30px rgba(0,0,0,0.6)' };
73
+ var D = { name: 'Daylight', bg: '#F6F7F9', panel: '#FFFFFF', soft: '#F2F4F7', line: '#DDE2E9', line2: '#C9D1DC', text: '#0B1726', textSoft: '#3a4a5e', muted: '#55657a', dim: '#7a8899', agent: '#7C4DDB', sup: '#1E8C80', rel: '#55657a', shadow: '0 10px 30px rgba(8,21,36,0.18)' };
74
+ var cases = [
75
+ { name: 'An agent drew it', note: 'labelled · ✦ stays until a person edits it', label: 'supports', author: 'agent' },
76
+ { name: 'An agent drew it, no label', note: 'the pill is just the mark', label: '', author: 'agent' },
77
+ { name: 'You drew it, alone on the board', note: 'today’s normal case: no mark', label: 'supports', author: null },
78
+ { name: 'You drew it, no label', note: 'no pill at all', label: '', author: null },
79
+ { name: 'Mia drew it — shared board', note: 'Part 3: another person, her initial', label: 'supports', author: 'person' },
80
+ { name: 'Mia drew it, no label', note: 'the initial alone', label: '', author: 'person' },
81
+ { name: 'Your new link, not seen yet', note: 'temporary: the next read clears it', label: 'supports', author: null, notSeen: 'word' },
82
+ { name: 'Mia’s new link, not seen yet', note: 'who drew it and the state together', label: 'supports', author: 'person', notSeen: 'word' },
83
+ { name: 'Short line or zoom below 60%', note: 'the state folds to its glyph; words in the hint', label: 'supports', author: 'person', notSeen: 'glyph' },
84
+ { name: 'Zoom below 35%', note: 'only the marks stay, no label', label: '', author: 'agent', zoomedOut: true },
85
+ { name: 'You relabel the agent’s link', note: 'it is yours now: ✦ goes', label: 'informs', author: null, relabelled: true },
86
+ { name: 'Hover the pill', note: 'the hint names who drew it and when', label: 'supports', author: 'agent', hint: '✦ Drawn by Codex · 14:06' }
87
+ ];
88
+ function scene(c, k) {
89
+ var ink = k.relabelled ? (c === H ? '#E58FB0' : '#B8467A') : k.label ? c.sup : c.rel;
90
+ var hasMark = !!k.author;
91
+ var hasPill = !!k.label || hasMark || !!k.notSeen;
92
+ var stub = 'position:absolute;top:28px;width:62px;height:40px;box-sizing:border-box;border-radius:8px;border:1px solid ' + c.line2 + ';background:' + c.panel + ';';
93
+ return {
94
+ name: k.name, note: k.note, label: k.label, hasLabel: !!k.label, hasPill: hasPill,
95
+ agent: k.author === 'agent', person: k.author === 'person',
96
+ notSeen: !!k.notSeen, nsWord: k.notSeen === 'word' ? 'not seen by Codex' : '',
97
+ hasHint: !!k.hint, hint: k.hint || '',
98
+ frame: 'position:relative;height:96px;border-radius:8px;border:1px solid ' + c.line + ';background:' + c.bg + ';overflow:visible;',
99
+ line: 'stroke:' + ink + ';stroke-width:1.5;' + (k.label ? '' : 'stroke-dasharray:2 4;'),
100
+ head: 'fill:' + ink + ';stroke:none;',
101
+ stubL: stub + 'left:8px;', stubR: stub + 'left:230px;',
102
+ pill: 'position:absolute;left:150px;top:48px;transform:translate(-50%,-50%);display:inline-flex;align-items:center;gap:5px;height:22px;box-sizing:border-box;padding:0 ' + (k.label ? '9px' : '5px') + ';border-radius:999px;border:1px solid ' + hexA(ink, 0.5) + ';background:' + c.panel + ';color:' + ink + ';font-size:11px;font-weight:600;white-space:nowrap;' + (k.zoomedOut ? 'transform:translate(-50%,-50%) scale(0.85);' : ''),
103
+ sparkSt: 'fill:' + c.agent + ';stroke:none;flex-shrink:0;',
104
+ initialSt: 'width:15px;height:15px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;background:' + c.soft + ';box-shadow:inset 0 0 0 1px ' + c.line2 + ';color:' + c.textSoft + ';font-size:9px;font-weight:600;',
105
+ nsSt: 'display:inline-flex;align-items:center;gap:3px;color:' + c.muted + ';font-weight:500;' + (k.label || hasMark ? 'padding-left:6px;border-left:1px solid ' + c.line2 + ';' : '') + (k.notSeen === 'glyph' ? 'padding-left:5px;' : ''),
106
+ hintSt: 'position:absolute;left:150px;top:64px;transform:translateX(-50%);padding:6px 9px;border-radius:8px;border:1px solid ' + c.line2 + ';background:' + c.soft + ';box-shadow:' + c.shadow + ';font-size:11px;color:' + c.text + ';white-space:nowrap;z-index:2;'
107
+ };
108
+ }
109
+ var themes = [H, D].map(function (c) {
110
+ return {
111
+ name: c.name,
112
+ section: 'display:flex;flex-direction:column;gap:12px;padding:18px 20px;border-radius:12px;background:' + c.bg + ';border:1px solid ' + c.line + ';',
113
+ label: 'font-size:11px;font-weight:500;letter-spacing:0.06em;text-transform:uppercase;color:' + c.dim + ';',
114
+ caseName: 'font-size:12px;font-weight:600;color:' + c.text + ';',
115
+ caseNote: 'font-size:11px;color:' + c.muted + ';',
116
+ scenes: cases.map(function (k) { return scene(c, k); })
117
+ };
118
+ });
119
+ var rules = [
120
+ '1 · Who drew it: an agent → violet ✦ before the label; another person on a shared board (Part 3) → their initial, neutral; the board’s only person → no mark.',
121
+ '2 · It stays until a person edits, retypes or relabels the link; then the link is theirs (no mark for the only person, their initial on a shared board). A read never clears it.',
122
+ '3 · Not seen by <agent>: a person’s new or edited link only, muted eye-off and words, after the authorship mark; cleared by the agent’s next read that carries either end. Agent links are never “not seen”.',
123
+ '4 · Folding: on a short line or below 60% zoom the state keeps only its eye-off glyph; below 35% labels go and only the marks stay. Authorship never folds — it is already a glyph.',
124
+ '5 · An unlabelled link gets a pill only when it carries a mark; otherwise it stays a bare line.',
125
+ '6 · The agent name is whichever agent drew it or is attached (Claude, Codex, Copilot…).'
126
+ ];
127
+ var hint = 'display:inline-flex;align-items:center;padding:6px 9px;border-radius:8px;border:1px solid #2a4566;background:#13243b;font-size:11px;color:#e6eef7;white-space:nowrap;';
128
+ var hints = [
129
+ { t: '✦ Drawn by Codex · 14:06', st: hint, when: 'an agent’s link' },
130
+ { t: 'Drawn by Mia Jensen · 14:06', st: hint, when: 'another person on a shared board' },
131
+ { t: 'Drawn by Mia Jensen · 14:06 · not seen by Codex yet', st: hint, when: 'both, when the state is folded to its glyph' },
132
+ { t: 'You relabelled it · 14:20 (drawn by Codex · 14:06)', st: hint, when: 'after a person takes it over' }
133
+ ];
134
+ return { i: i, s: s, themes: themes, rules: rules, hints: hints };
135
+ }
136
+ }
137
+ </script>
138
+ </body>
139
+ </html>