scrum-skills 0.3.2 → 0.3.4

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 (365) hide show
  1. package/.agents/skills/diagram-design/LICENSE +4 -0
  2. package/.agents/skills/diagram-design/SKILL.md +423 -0
  3. package/.agents/skills/diagram-design/UPSTREAM.json +88 -0
  4. package/.agents/skills/diagram-design/UPSTREAM.md +23 -0
  5. package/.agents/skills/diagram-design/assets/example-architecture-containment.html +205 -0
  6. package/.agents/skills/diagram-design/assets/example-architecture-delta.html +193 -0
  7. package/.agents/skills/diagram-design/assets/example-architecture.html +183 -0
  8. package/.agents/skills/diagram-design/assets/example-axonometric-plan-campus.html +108 -0
  9. package/.agents/skills/diagram-design/assets/example-axonometric-plan-coffee-shop.html +121 -0
  10. package/.agents/skills/diagram-design/assets/example-axonometric-plan-warehouse.html +127 -0
  11. package/.agents/skills/diagram-design/assets/example-axonometric-plan.html +114 -0
  12. package/.agents/skills/diagram-design/assets/example-bar.html +129 -0
  13. package/.agents/skills/diagram-design/assets/example-beeswarm.html +384 -0
  14. package/.agents/skills/diagram-design/assets/example-box-plot.html +127 -0
  15. package/.agents/skills/diagram-design/assets/example-bubble.html +147 -0
  16. package/.agents/skills/diagram-design/assets/example-bump.html +142 -0
  17. package/.agents/skills/diagram-design/assets/example-data-flow.html +143 -0
  18. package/.agents/skills/diagram-design/assets/example-datalake.html +269 -0
  19. package/.agents/skills/diagram-design/assets/example-db-schema.html +302 -0
  20. package/.agents/skills/diagram-design/assets/example-dependency.html +224 -0
  21. package/.agents/skills/diagram-design/assets/example-deployment.html +190 -0
  22. package/.agents/skills/diagram-design/assets/example-dp-integration.html +81 -0
  23. package/.agents/skills/diagram-design/assets/example-dp-security-matrix.html +88 -0
  24. package/.agents/skills/diagram-design/assets/example-er.html +202 -0
  25. package/.agents/skills/diagram-design/assets/example-exploded-ai-stack.html +85 -0
  26. package/.agents/skills/diagram-design/assets/example-exploded-keyboard.html +84 -0
  27. package/.agents/skills/diagram-design/assets/example-exploded-phone.html +83 -0
  28. package/.agents/skills/diagram-design/assets/example-exploded-unboxing.html +84 -0
  29. package/.agents/skills/diagram-design/assets/example-exploded.html +83 -0
  30. package/.agents/skills/diagram-design/assets/example-fishbone.html +152 -0
  31. package/.agents/skills/diagram-design/assets/example-flowchart.html +163 -0
  32. package/.agents/skills/diagram-design/assets/example-gantt.html +137 -0
  33. package/.agents/skills/diagram-design/assets/example-heatmap.html +224 -0
  34. package/.agents/skills/diagram-design/assets/example-high-level-vertical.html +325 -0
  35. package/.agents/skills/diagram-design/assets/example-high-level.html +301 -0
  36. package/.agents/skills/diagram-design/assets/example-import-drawio.html +185 -0
  37. package/.agents/skills/diagram-design/assets/example-import-excalidraw.html +70 -0
  38. package/.agents/skills/diagram-design/assets/example-import-mermaid.html +70 -0
  39. package/.agents/skills/diagram-design/assets/example-it-state.html +128 -0
  40. package/.agents/skills/diagram-design/assets/example-journey.html +148 -0
  41. package/.agents/skills/diagram-design/assets/example-kanban.html +174 -0
  42. package/.agents/skills/diagram-design/assets/example-layers.html +123 -0
  43. package/.agents/skills/diagram-design/assets/example-line.html +111 -0
  44. package/.agents/skills/diagram-design/assets/example-loop.html +100 -0
  45. package/.agents/skills/diagram-design/assets/example-marimekko.html +148 -0
  46. package/.agents/skills/diagram-design/assets/example-medallion.html +159 -0
  47. package/.agents/skills/diagram-design/assets/example-nested.html +136 -0
  48. package/.agents/skills/diagram-design/assets/example-org-chart.html +45 -0
  49. package/.agents/skills/diagram-design/assets/example-polar.html +116 -0
  50. package/.agents/skills/diagram-design/assets/example-process.html +64 -0
  51. package/.agents/skills/diagram-design/assets/example-pyramid.html +119 -0
  52. package/.agents/skills/diagram-design/assets/example-quadrant-consultant.html +166 -0
  53. package/.agents/skills/diagram-design/assets/example-quadrant.html +135 -0
  54. package/.agents/skills/diagram-design/assets/example-radar.html +139 -0
  55. package/.agents/skills/diagram-design/assets/example-ridgeline.html +104 -0
  56. package/.agents/skills/diagram-design/assets/example-sankey.html +150 -0
  57. package/.agents/skills/diagram-design/assets/example-scatter.html +141 -0
  58. package/.agents/skills/diagram-design/assets/example-sequence-oauth.html +227 -0
  59. package/.agents/skills/diagram-design/assets/example-sequence.html +222 -0
  60. package/.agents/skills/diagram-design/assets/example-service-blueprint.html +185 -0
  61. package/.agents/skills/diagram-design/assets/example-slopegraph.html +119 -0
  62. package/.agents/skills/diagram-design/assets/example-state-lifecycle.html +92 -0
  63. package/.agents/skills/diagram-design/assets/example-state.html +147 -0
  64. package/.agents/skills/diagram-design/assets/example-story-map.html +184 -0
  65. package/.agents/skills/diagram-design/assets/example-streamgraph.html +99 -0
  66. package/.agents/skills/diagram-design/assets/example-swimlane.html +172 -0
  67. package/.agents/skills/diagram-design/assets/example-timeline.html +135 -0
  68. package/.agents/skills/diagram-design/assets/example-tree-block-decomposition.html +151 -0
  69. package/.agents/skills/diagram-design/assets/example-tree.html +173 -0
  70. package/.agents/skills/diagram-design/assets/example-treemap.html +107 -0
  71. package/.agents/skills/diagram-design/assets/example-uml-class.html +188 -0
  72. package/.agents/skills/diagram-design/assets/example-venn.html +110 -0
  73. package/.agents/skills/diagram-design/assets/example-wardley.html +153 -0
  74. package/.agents/skills/diagram-design/assets/example-waterfall.html +129 -0
  75. package/.agents/skills/diagram-design/assets/template-dark.html +99 -0
  76. package/.agents/skills/diagram-design/assets/template-full.html +421 -0
  77. package/.agents/skills/diagram-design/assets/template-motion.html +448 -0
  78. package/.agents/skills/diagram-design/assets/template-terminal.html +188 -0
  79. package/.agents/skills/diagram-design/assets/template.html +100 -0
  80. package/.agents/skills/diagram-design/references/animation.md +143 -0
  81. package/.agents/skills/diagram-design/references/export-registry.md +78 -0
  82. package/.agents/skills/diagram-design/references/export.md +376 -0
  83. package/.agents/skills/diagram-design/references/import-drawio.md +181 -0
  84. package/.agents/skills/diagram-design/references/import-excalidraw.md +130 -0
  85. package/.agents/skills/diagram-design/references/import-mermaid.md +137 -0
  86. package/.agents/skills/diagram-design/references/layout-budget.md +97 -0
  87. package/.agents/skills/diagram-design/references/onboarding.md +368 -0
  88. package/.agents/skills/diagram-design/references/output-spec.md +277 -0
  89. package/.agents/skills/diagram-design/references/primitive-annotation.md +36 -0
  90. package/.agents/skills/diagram-design/references/primitive-icons.md +827 -0
  91. package/.agents/skills/diagram-design/references/primitive-sketchy.md +43 -0
  92. package/.agents/skills/diagram-design/references/primitive-terminal.md +76 -0
  93. package/.agents/skills/diagram-design/references/primitives-core.md +150 -0
  94. package/.agents/skills/diagram-design/references/profiles.md +183 -0
  95. package/.agents/skills/diagram-design/references/semantic-patterns.md +154 -0
  96. package/.agents/skills/diagram-design/references/style-guide.md +236 -0
  97. package/.agents/skills/diagram-design/references/style-vivid.md +148 -0
  98. package/.agents/skills/diagram-design/references/type-architecture-delta.md +143 -0
  99. package/.agents/skills/diagram-design/references/type-architecture.md +117 -0
  100. package/.agents/skills/diagram-design/references/type-axonometric-plan.md +83 -0
  101. package/.agents/skills/diagram-design/references/type-bar.md +108 -0
  102. package/.agents/skills/diagram-design/references/type-data-flow.md +371 -0
  103. package/.agents/skills/diagram-design/references/type-db-schema.md +48 -0
  104. package/.agents/skills/diagram-design/references/type-dependency.md +44 -0
  105. package/.agents/skills/diagram-design/references/type-deployment.md +45 -0
  106. package/.agents/skills/diagram-design/references/type-dp-integration.md +407 -0
  107. package/.agents/skills/diagram-design/references/type-dp-security-matrix.md +379 -0
  108. package/.agents/skills/diagram-design/references/type-er.md +25 -0
  109. package/.agents/skills/diagram-design/references/type-exploded.md +115 -0
  110. package/.agents/skills/diagram-design/references/type-fishbone.md +75 -0
  111. package/.agents/skills/diagram-design/references/type-flowchart.md +23 -0
  112. package/.agents/skills/diagram-design/references/type-gantt.md +45 -0
  113. package/.agents/skills/diagram-design/references/type-heatmap.md +80 -0
  114. package/.agents/skills/diagram-design/references/type-high-level.md +470 -0
  115. package/.agents/skills/diagram-design/references/type-it-state.md +468 -0
  116. package/.agents/skills/diagram-design/references/type-journey.md +55 -0
  117. package/.agents/skills/diagram-design/references/type-kanban.md +49 -0
  118. package/.agents/skills/diagram-design/references/type-layers.md +26 -0
  119. package/.agents/skills/diagram-design/references/type-line.md +337 -0
  120. package/.agents/skills/diagram-design/references/type-loop.md +223 -0
  121. package/.agents/skills/diagram-design/references/type-medallion.md +356 -0
  122. package/.agents/skills/diagram-design/references/type-nested.md +22 -0
  123. package/.agents/skills/diagram-design/references/type-org-chart.md +44 -0
  124. package/.agents/skills/diagram-design/references/type-polar.md +136 -0
  125. package/.agents/skills/diagram-design/references/type-process.md +490 -0
  126. package/.agents/skills/diagram-design/references/type-pyramid.md +33 -0
  127. package/.agents/skills/diagram-design/references/type-quadrant.md +81 -0
  128. package/.agents/skills/diagram-design/references/type-radar.md +82 -0
  129. package/.agents/skills/diagram-design/references/type-sankey.md +75 -0
  130. package/.agents/skills/diagram-design/references/type-scatter.md +276 -0
  131. package/.agents/skills/diagram-design/references/type-sequence.md +130 -0
  132. package/.agents/skills/diagram-design/references/type-service-blueprint.md +103 -0
  133. package/.agents/skills/diagram-design/references/type-state.md +30 -0
  134. package/.agents/skills/diagram-design/references/type-story-map.md +46 -0
  135. package/.agents/skills/diagram-design/references/type-swimlane.md +22 -0
  136. package/.agents/skills/diagram-design/references/type-timeline.md +20 -0
  137. package/.agents/skills/diagram-design/references/type-tree.md +24 -0
  138. package/.agents/skills/diagram-design/references/type-treemap.md +137 -0
  139. package/.agents/skills/diagram-design/references/type-uml-class.md +65 -0
  140. package/.agents/skills/diagram-design/references/type-venn.md +26 -0
  141. package/.agents/skills/diagram-design/references/type-wardley.md +39 -0
  142. package/.agents/skills/diagram-design/references/type-waterfall.md +75 -0
  143. package/.agents/skills/scrum-meta/SKILL.md +36 -36
  144. package/.agents/skills/scrum-planning/SKILL.md +61 -61
  145. package/.agents/skills/scrum-planning/references/schema.md +384 -336
  146. package/.agents/skills/scrum-report/SKILL.md +42 -42
  147. package/.agents/skills/scrum-sprint/SKILL.md +49 -49
  148. package/.agents/skills/scrum-tdd/SKILL.md +140 -127
  149. package/README.md +24 -1
  150. package/assets/board/200.html +1 -1
  151. package/assets/board/404.html +1 -1
  152. package/assets/board/_nuxt/4gQF_HS3.js +1 -0
  153. package/assets/board/_nuxt/5okfNy5D.js +1 -0
  154. package/assets/board/_nuxt/{Bb3Limos.js → B0C2jsdk.js} +1 -1
  155. package/assets/board/_nuxt/B1j6UC4U.js +1 -0
  156. package/assets/board/_nuxt/B3LKy6o2.js +1 -0
  157. package/assets/board/_nuxt/BAQQngAq.js +13 -0
  158. package/assets/board/_nuxt/BE6t7Q2m.js +1 -0
  159. package/assets/board/_nuxt/BGwhkDRl.js +1 -0
  160. package/assets/board/_nuxt/BLvbupFS.js +1 -0
  161. package/assets/board/_nuxt/BQgzP7ur.js +1 -0
  162. package/assets/board/_nuxt/BRZIF_wo.js +1 -0
  163. package/assets/board/_nuxt/BU8vdZUs.js +95 -0
  164. package/assets/board/_nuxt/BW3xJdEx.js +1 -0
  165. package/assets/board/_nuxt/{Cm9lkUvP.js → BY36DFyj.js} +1 -1
  166. package/assets/board/_nuxt/BZlZD94i.js +1 -0
  167. package/assets/board/_nuxt/BZvXNwev.js +3 -0
  168. package/assets/board/_nuxt/BiWrMOsL.js +1 -0
  169. package/assets/board/_nuxt/BkoKCNUY.js +1 -0
  170. package/assets/board/_nuxt/BlKmZhhF.js +1 -0
  171. package/assets/board/_nuxt/BmBpmU73.js +1 -0
  172. package/assets/board/_nuxt/BmrSh0rL.js +1 -0
  173. package/assets/board/_nuxt/BrWE0up6.js +1 -0
  174. package/assets/board/_nuxt/Bs52qkgk.js +1 -0
  175. package/assets/board/_nuxt/BuBzMkFZ.js +1 -0
  176. package/assets/board/_nuxt/Bubk0xn-.js +1 -0
  177. package/assets/board/_nuxt/BxuBMtk_.js +3 -0
  178. package/assets/board/_nuxt/By1KXXLR.js +1 -0
  179. package/assets/board/_nuxt/BygIGL69.js +2 -0
  180. package/assets/board/_nuxt/C-fx-vFO.js +1 -0
  181. package/assets/board/_nuxt/C1iO5KH3.js +1 -0
  182. package/assets/board/_nuxt/C2YPmTzt.js +1 -0
  183. package/assets/board/_nuxt/C3SpAhCW.js +1 -0
  184. package/assets/board/_nuxt/C3ZRWz5L.js +1 -0
  185. package/assets/board/_nuxt/C4WdPP6K.js +1 -0
  186. package/assets/board/_nuxt/C6o03JHe.js +1 -0
  187. package/assets/board/_nuxt/C8qB5llI.js +1 -0
  188. package/assets/board/_nuxt/C9MgRdhu.js +1 -0
  189. package/assets/board/_nuxt/CCA81-4P.js +1 -0
  190. package/assets/board/_nuxt/{D2O8Q8x9.js → CFCM18fF.js} +1 -1
  191. package/assets/board/_nuxt/CGXljzd_.js +1 -0
  192. package/assets/board/_nuxt/CI0scS-N.js +1 -0
  193. package/assets/board/_nuxt/CJs9B42o.js +1 -0
  194. package/assets/board/_nuxt/COmtTtfB.js +1 -0
  195. package/assets/board/_nuxt/CPYm4J_K.js +1 -0
  196. package/assets/board/_nuxt/CXG7GZes.js +1 -0
  197. package/assets/board/_nuxt/CYGiZn-X.js +1 -0
  198. package/assets/board/_nuxt/CaE8VlUp.js +1 -0
  199. package/assets/board/_nuxt/Cajxc4Dw.js +1 -0
  200. package/assets/board/_nuxt/CcGiNUgA.js +1 -0
  201. package/assets/board/_nuxt/Ccgv3lDj.js +1 -0
  202. package/assets/board/_nuxt/CdPGFZyy.js +1 -0
  203. package/assets/board/_nuxt/{DfR3IZN_.js → Cdf_T8Xa.js} +1 -1
  204. package/assets/board/_nuxt/CgQ30j_6.js +1 -0
  205. package/assets/board/_nuxt/Ck0-FqVI.js +1 -0
  206. package/assets/board/_nuxt/CkWKLtjO.js +1 -0
  207. package/assets/board/_nuxt/CoipdpDu.js +1 -0
  208. package/assets/board/_nuxt/Cq7hsCKB.js +1 -0
  209. package/assets/board/_nuxt/D166WVUG.js +1 -0
  210. package/assets/board/_nuxt/D1V1gysQ.js +1 -0
  211. package/assets/board/_nuxt/D4Dpzo9e.js +1 -0
  212. package/assets/board/_nuxt/D5i92OZO.js +1 -0
  213. package/assets/board/_nuxt/D6dUp4Nm.js +9 -0
  214. package/assets/board/_nuxt/DFQDFspC.js +1 -0
  215. package/assets/board/_nuxt/DHX2tw9J.js +1 -0
  216. package/assets/board/_nuxt/DJM7u8P3.js +1 -0
  217. package/assets/board/_nuxt/{BPTrRhcw.js → DLr85ebo.js} +1 -1
  218. package/assets/board/_nuxt/DOMM1wfl.js +1 -0
  219. package/assets/board/_nuxt/DU6ArlUN.js +1 -0
  220. package/assets/board/_nuxt/{B_SlFcWp.js → DUgGsde6.js} +1 -1
  221. package/assets/board/_nuxt/DV4ti-Pq.js +1 -0
  222. package/assets/board/_nuxt/D_ct-Stz.js +2 -0
  223. package/assets/board/_nuxt/DbWAComO.js +1 -0
  224. package/assets/board/_nuxt/DbwlcHAt.js +1 -0
  225. package/assets/board/_nuxt/Dki9VkAL.js +3 -0
  226. package/assets/board/_nuxt/DlNJhOoc.js +1 -0
  227. package/assets/board/_nuxt/Dmg78zOY.js +3 -0
  228. package/assets/board/_nuxt/DqG7CtD4.js +1 -0
  229. package/assets/board/_nuxt/DqUSsCJ2.js +1 -0
  230. package/assets/board/_nuxt/Du2F4WXh.js +1 -0
  231. package/assets/board/_nuxt/DuRiEXn4.js +1 -0
  232. package/assets/board/_nuxt/DwCE3305.js +1 -0
  233. package/assets/board/_nuxt/DwzGxoX2.js +1 -0
  234. package/assets/board/_nuxt/DxBwVNyP.js +2 -0
  235. package/assets/board/_nuxt/DzmVW5-D.js +1 -0
  236. package/assets/board/_nuxt/I-sGtDIB.js +6 -0
  237. package/assets/board/_nuxt/JU9-x68N.js +1 -0
  238. package/assets/board/_nuxt/Lozm7hhE.js +1 -0
  239. package/assets/board/_nuxt/MMsTMkcB.js +1 -0
  240. package/assets/board/_nuxt/MS7CGmCB.js +1 -0
  241. package/assets/board/_nuxt/OKKaKILz.js +1 -0
  242. package/assets/board/_nuxt/{Csqgy925.js → P6qlvBHA.js} +1 -1
  243. package/assets/board/_nuxt/SrNUvNwO.js +1 -0
  244. package/assets/board/_nuxt/{DSaWoFHS.js → SywdkA98.js} +1 -1
  245. package/assets/board/_nuxt/TBIRpVLG.js +1 -0
  246. package/assets/board/_nuxt/TlTrMIMm.js +1 -0
  247. package/assets/board/_nuxt/Utb4TVOl.js +1 -0
  248. package/assets/board/_nuxt/Zv9-SOQF.js +1 -0
  249. package/assets/board/_nuxt/_id_.B6iqDPxe.css +1 -0
  250. package/assets/board/_nuxt/b7xtxFRl.js +1 -0
  251. package/assets/board/_nuxt/builds/latest.json +1 -1
  252. package/assets/board/_nuxt/builds/meta/08bebe14-0f1b-4d2a-8de4-e84e122d10e9.json +1 -0
  253. package/assets/board/_nuxt/diagrams.pyhqNtmr.css +1 -0
  254. package/assets/board/_nuxt/{entry.CKHePurH.css → entry.BBv-sBnP.css} +1 -1
  255. package/assets/board/_nuxt/error-404.CgJNdpB5.css +1 -0
  256. package/assets/board/_nuxt/error-500.WYSoH44y.css +1 -0
  257. package/assets/board/_nuxt/jbri6q1p.js +1 -0
  258. package/assets/board/_nuxt/q_8bxRMt.js +1 -0
  259. package/assets/board/burndown/index.html +1 -1
  260. package/assets/board/diagrams/index.html +1 -0
  261. package/assets/board/epics/index.html +1 -1
  262. package/assets/board/gantt/index.html +1 -1
  263. package/assets/board/index.html +1 -1
  264. package/assets/board/last-change/index.html +1 -1
  265. package/assets/board/milestones/index.html +1 -1
  266. package/assets/board/tests/index.html +1 -1
  267. package/bin/scrum-skills.mjs +13 -0
  268. package/package.json +2 -1
  269. package/templates/AGENTS.md +10 -0
  270. package/tools/diagram-import.mjs +238 -0
  271. package/tools/diagram-lint.mjs +518 -0
  272. package/tools/diagram.mjs +299 -0
  273. package/tools/last-change.mjs +326 -326
  274. package/tools/projects.mjs +29 -4
  275. package/tools/serve.mjs +27 -1
  276. package/tools/validate.mjs +781 -664
  277. package/assets/board/_nuxt/1eqboJxR.js +0 -1
  278. package/assets/board/_nuxt/2K7ag6ES.js +0 -1
  279. package/assets/board/_nuxt/51OWHj8c.js +0 -2
  280. package/assets/board/_nuxt/6gFtTBwm.js +0 -1
  281. package/assets/board/_nuxt/B3jkABw9.js +0 -1
  282. package/assets/board/_nuxt/B5n2_jZN.js +0 -1
  283. package/assets/board/_nuxt/BDK2Hj7B.js +0 -1
  284. package/assets/board/_nuxt/BDcnzXHq.js +0 -1
  285. package/assets/board/_nuxt/BaG8y0Wt.js +0 -1
  286. package/assets/board/_nuxt/BbwJq5pb.js +0 -1
  287. package/assets/board/_nuxt/BgLeKwx0.js +0 -1
  288. package/assets/board/_nuxt/Bi9Axj3V.js +0 -1
  289. package/assets/board/_nuxt/BmxvtaMq.js +0 -1
  290. package/assets/board/_nuxt/BodFvto3.js +0 -1
  291. package/assets/board/_nuxt/BpWeHLuN.js +0 -1
  292. package/assets/board/_nuxt/BuOKDFiJ.js +0 -1
  293. package/assets/board/_nuxt/C40iTe-x.js +0 -1
  294. package/assets/board/_nuxt/C7K0R7F-.js +0 -2
  295. package/assets/board/_nuxt/C8vL692X.js +0 -1
  296. package/assets/board/_nuxt/C9StZL3D.js +0 -3
  297. package/assets/board/_nuxt/CGI_ZV79.js +0 -1
  298. package/assets/board/_nuxt/CJ2mz0WY.js +0 -1
  299. package/assets/board/_nuxt/CJMBJQuf.js +0 -1
  300. package/assets/board/_nuxt/CK-lOYG9.js +0 -1
  301. package/assets/board/_nuxt/CK9_veoz.js +0 -1
  302. package/assets/board/_nuxt/CLBcBrYf.js +0 -1
  303. package/assets/board/_nuxt/CMUi2-Lj.js +0 -1
  304. package/assets/board/_nuxt/COf6E6h4.js +0 -1
  305. package/assets/board/_nuxt/CPCUMJnF.js +0 -1
  306. package/assets/board/_nuxt/CPcKlmSm.js +0 -1
  307. package/assets/board/_nuxt/CQTvWh4i.js +0 -1
  308. package/assets/board/_nuxt/CSEEUF8S.js +0 -1
  309. package/assets/board/_nuxt/CSSb154I.js +0 -13
  310. package/assets/board/_nuxt/CgDTd7jS.js +0 -1
  311. package/assets/board/_nuxt/ChG76uh9.js +0 -1
  312. package/assets/board/_nuxt/Ci0qbkgh.js +0 -1
  313. package/assets/board/_nuxt/CqoQ__I_.js +0 -1
  314. package/assets/board/_nuxt/CuJUHLl8.js +0 -1
  315. package/assets/board/_nuxt/CvLiA4_O.js +0 -1
  316. package/assets/board/_nuxt/Cvs12oA0.js +0 -3
  317. package/assets/board/_nuxt/CyEXFe3V.js +0 -1
  318. package/assets/board/_nuxt/Cz6rZcLK.js +0 -1
  319. package/assets/board/_nuxt/D2FhHl1o.js +0 -1
  320. package/assets/board/_nuxt/D3YCAmfu.js +0 -1
  321. package/assets/board/_nuxt/D5CE81jK.js +0 -1
  322. package/assets/board/_nuxt/D75vbfSb.js +0 -1
  323. package/assets/board/_nuxt/D99LbGfb.js +0 -9
  324. package/assets/board/_nuxt/DEfLc7p3.js +0 -6
  325. package/assets/board/_nuxt/DF-nsa1Z.js +0 -1
  326. package/assets/board/_nuxt/DIc8yx98.js +0 -1
  327. package/assets/board/_nuxt/DLkAKotw.js +0 -1
  328. package/assets/board/_nuxt/DRPlYvb3.js +0 -1
  329. package/assets/board/_nuxt/DRlQgul3.js +0 -1
  330. package/assets/board/_nuxt/DSLbmoWa.js +0 -1
  331. package/assets/board/_nuxt/DWO9c9yp.js +0 -1
  332. package/assets/board/_nuxt/DZo3dYLJ.js +0 -3
  333. package/assets/board/_nuxt/D_S6N7_b.js +0 -1
  334. package/assets/board/_nuxt/DajA-Tkt.js +0 -1
  335. package/assets/board/_nuxt/DbHiyab-.js +0 -1
  336. package/assets/board/_nuxt/Dc7Ql6eE.js +0 -1
  337. package/assets/board/_nuxt/Dd9ZukPU.js +0 -1
  338. package/assets/board/_nuxt/Dg2LiqmN.js +0 -1
  339. package/assets/board/_nuxt/DhuleNnm.js +0 -1
  340. package/assets/board/_nuxt/DkI1Qxpp.js +0 -95
  341. package/assets/board/_nuxt/DnDHGSYI.js +0 -1
  342. package/assets/board/_nuxt/DpXJ_tCU.js +0 -1
  343. package/assets/board/_nuxt/DqZgF3hU.js +0 -1
  344. package/assets/board/_nuxt/DqcxvfbD.js +0 -1
  345. package/assets/board/_nuxt/DsA2lVci.js +0 -1
  346. package/assets/board/_nuxt/Dtsa-1NS.js +0 -1
  347. package/assets/board/_nuxt/Du91iq0p.js +0 -1
  348. package/assets/board/_nuxt/Dx1wcYFo.js +0 -1
  349. package/assets/board/_nuxt/EYTShbt4.js +0 -1
  350. package/assets/board/_nuxt/MaXJprwN.js +0 -1
  351. package/assets/board/_nuxt/P9x67aq2.js +0 -1
  352. package/assets/board/_nuxt/S08nFESZ.js +0 -3
  353. package/assets/board/_nuxt/V0uynWE2.js +0 -1
  354. package/assets/board/_nuxt/Vo4wMbnS.js +0 -1
  355. package/assets/board/_nuxt/ZVTqot-_.js +0 -1
  356. package/assets/board/_nuxt/ZngEd3HB.js +0 -1
  357. package/assets/board/_nuxt/_id_.B2NDKSlX.css +0 -1
  358. package/assets/board/_nuxt/assMu_Wn.js +0 -1
  359. package/assets/board/_nuxt/builds/meta/8e23aec9-5b67-4569-b8bf-d4f07e50ffdf.json +0 -1
  360. package/assets/board/_nuxt/error-404.BFmXOnCT.css +0 -1
  361. package/assets/board/_nuxt/error-500.BZ-DdjQ6.css +0 -1
  362. package/assets/board/_nuxt/rlePnzpc.js +0 -1
  363. package/assets/board/_nuxt/uKzCKCTq.js +0 -1
  364. package/assets/board/_nuxt/vwxaNGfc.js +0 -1
  365. package/assets/board/_nuxt/yh6sf_D5.js +0 -1
@@ -0,0 +1,147 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>p95 vs error rate, sized by traffic · Bubble</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
8
+ <style>
9
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
10
+ :root {
11
+ --color-paper: #f5f5f5;
12
+ --color-ink: #2d3142;
13
+ --color-muted: #4f5d75;
14
+ --color-accent: #bf4520;
15
+ --font-sans: 'Geist', system-ui, sans-serif;
16
+ --font-serif: 'Instrument Serif', serif;
17
+ --font-mono: 'Geist Mono', ui-monospace, monospace;
18
+ }
19
+ body { font-family: var(--font-sans); background: var(--color-paper); color: var(--color-ink); min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 3rem 2rem; }
20
+ .frame { max-width: 1200px; width: 100%; }
21
+ .eyebrow { font-family: var(--font-mono); font-size: 0.66rem; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
22
+ h1 { font-family: var(--font-serif); font-size: clamp(1.5rem, 2.4vw + 0.75rem, 2rem); font-weight: 400; letter-spacing: -0.02em; line-height: 1.15; margin-bottom: 1.5rem; }
23
+ svg { width: 100%; min-width: 760px; display: block; }
24
+ </style>
25
+ </head>
26
+ <body>
27
+ <div class="frame">
28
+ <p class="eyebrow">Bubble · Diagram Design</p>
29
+ <h1>The biggest risk is not the slowest service</h1>
30
+
31
+ <!-- X: 0-500ms p95 over 880px, x = 80 + 1.76·ms. Y: 0-4% error rate over
32
+ 380px, y = 420 - 95·pct. AREA encodes requests per second: r = 1.4·√v,
33
+ so area = π·1.96·v, exactly proportional. scripts/verify-bubble.py
34
+ derives all three maps from the values each bubble declares and flags
35
+ any bubble that disagrees with its peers. -->
36
+ <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="bubble-title bubble-desc">
37
+ <title id="bubble-title">The biggest risk is not the slowest service</title>
38
+ <desc id="bubble-desc">Bubble chart of nine services by p95 latency and error rate on zero-based axes, bubble area proportional to requests per second; Payments carries near-peak traffic at the highest error rate.</desc>
39
+ <defs>
40
+ <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
41
+ <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
42
+ </pattern>
43
+ </defs>
44
+
45
+ <rect width="100%" height="100%" fill="#f5f5f5"/>
46
+ <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
47
+
48
+ <!-- Axis captions -->
49
+ <text transform="rotate(-90 24 230)" x="24" y="230" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">ERROR RATE, %</text>
50
+ <text x="520" y="492" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">P95 LATENCY, MS</text>
51
+
52
+ <!-- Gridlines, same positions as the parent scatter -->
53
+ <line x1="80" y1="325" x2="960" y2="325" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
54
+ <line x1="80" y1="230" x2="960" y2="230" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
55
+ <line x1="80" y1="135" x2="960" y2="135" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
56
+ <line x1="80" y1="40" x2="960" y2="40" stroke="rgba(45,49,66,0.06)" stroke-width="0.8"/>
57
+ <line x1="256" y1="40" x2="256" y2="420" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
58
+ <line x1="432" y1="40" x2="432" y2="420" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
59
+ <line x1="608" y1="40" x2="608" y2="420" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
60
+ <line x1="784" y1="40" x2="784" y2="420" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
61
+
62
+ <!-- Axes: both start at zero. A bubble's position is read against the
63
+ origin, so a truncated axis here shifts every bubble's story. -->
64
+ <line x1="80" y1="40" x2="80" y2="420" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
65
+ <line x1="80" y1="420" x2="960" y2="420" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
66
+
67
+ <!-- Tick labels are BOUND: data-tick names the axis, data-value the number
68
+ the tick claims to sit at. verify-bubble.py cross-checks each against
69
+ the scale the bubbles themselves describe, so the printed axis and
70
+ the drawn positions cannot drift apart. -->
71
+ <text data-tick="y" data-value="1" x="72" y="329" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">1</text>
72
+ <text data-tick="y" data-value="2" x="72" y="234" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">2</text>
73
+ <text data-tick="y" data-value="3" x="72" y="139" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">3</text>
74
+ <text data-tick="y" data-value="4" x="72" y="44" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">4</text>
75
+ <text data-tick="y" data-value="0" x="72" y="424" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">0</text>
76
+
77
+ <text data-tick="x" data-value="0" x="80" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">0</text>
78
+ <text data-tick="x" data-value="100" x="256" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">100</text>
79
+ <text data-tick="x" data-value="200" x="432" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">200</text>
80
+ <text data-tick="x" data-value="300" x="608" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">300</text>
81
+ <text data-tick="x" data-value="400" x="784" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">400</text>
82
+ <text data-tick="x" data-value="500" x="960" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">500</text>
83
+
84
+ <!-- ─── BUBBLES, drawn LARGEST FIRST so a small bubble can never be buried
85
+ under a big one. AREA carries the third value, never radius: a radius
86
+ proportional to traffic would show a 6x service as 36x the ink. The
87
+ fill ramp runs faintest-on-largest — it compensates ink mass so small
88
+ bubbles stay visible, it is NOT a fourth encoding, and the legend says
89
+ which end is which in skin-neutral terms. Each bubble sits on a paper
90
+ underlay so gridlines do not show through the translucent fill. -->
91
+
92
+ <circle cx="229.6" cy="372.5" r="42" fill="#f5f5f5"/>
93
+ <circle data-name="Gateway" data-x="85" data-y="0.5" data-size="900" cx="229.6" cy="372.5" r="42" fill="rgba(45,49,66,0.14)" stroke="#4f5d75" stroke-width="1"/>
94
+
95
+ <!-- Payments FOCAL — and it is the risk, not the winner: near-peak traffic
96
+ riding the worst error rate. One accent bubble max; every other
97
+ service stays on the ink ramp. -->
98
+ <circle cx="537.6" cy="154" r="38.6" fill="#f5f5f5"/>
99
+ <circle data-name="Payments" data-x="260" data-y="2.8" data-size="760" cx="537.6" cy="154" r="38.6" fill="rgba(191,69,32,0.15)" stroke="#bf4520" stroke-width="1.2"/>
100
+
101
+ <circle cx="326.4" cy="334.5" r="34.9" fill="#f5f5f5"/>
102
+ <circle data-name="Auth" data-x="140" data-y="0.9" data-size="620" cx="326.4" cy="334.5" r="34.9" fill="rgba(45,49,66,0.17)" stroke="#4f5d75" stroke-width="1"/>
103
+
104
+ <circle cx="396.8" cy="353.5" r="32.5" fill="#f5f5f5"/>
105
+ <circle data-name="Catalog" data-x="180" data-y="0.7" data-size="540" cx="396.8" cy="353.5" r="32.5" fill="rgba(45,49,66,0.20)" stroke="#4f5d75" stroke-width="1"/>
106
+
107
+ <circle cx="643.2" cy="315.5" r="30.7" fill="#f5f5f5"/>
108
+ <circle data-name="Search" data-x="320" data-y="1.1" data-size="480" cx="643.2" cy="315.5" r="30.7" fill="rgba(45,49,66,0.23)" stroke="#4f5d75" stroke-width="1"/>
109
+
110
+ <circle cx="484.8" cy="287" r="25.4" fill="#f5f5f5"/>
111
+ <circle data-name="Media" data-x="230" data-y="1.4" data-size="330" cx="484.8" cy="287" r="25.4" fill="rgba(45,49,66,0.26)" stroke="#4f5d75" stroke-width="1"/>
112
+
113
+ <circle cx="819.2" cy="268" r="20.3" fill="#f5f5f5"/>
114
+ <circle data-name="Recommender" data-x="420" data-y="1.6" data-size="210" cx="819.2" cy="268" r="20.3" fill="rgba(45,49,66,0.29)" stroke="#4f5d75" stroke-width="1"/>
115
+
116
+ <circle cx="247.2" cy="211" r="17.1" fill="#f5f5f5"/>
117
+ <circle data-name="Notifications" data-x="95" data-y="2.2" data-size="150" cx="247.2" cy="211" r="17.1" fill="rgba(45,49,66,0.32)" stroke="#4f5d75" stroke-width="1"/>
118
+
119
+ <circle cx="889.6" cy="334.5" r="10.8" fill="#f5f5f5"/>
120
+ <circle data-name="Reports" data-x="460" data-y="0.9" data-size="60" cx="889.6" cy="334.5" r="10.8" fill="rgba(45,49,66,0.35)" stroke="#4f5d75" stroke-width="1"/>
121
+
122
+ <!-- Labels: the focal bubble plus the two poles of the area story — the
123
+ giant that is healthy and the sliver that is slow. Each label is
124
+ bound to its bubble by data-name, so verify-bubble.py can prove it
125
+ sits nearer its own bubble than anyone else's. -->
126
+ <rect x="506" y="99" width="64" height="12" rx="2" fill="#f5f5f5"/>
127
+ <text data-name="Payments" data-role="label" x="538" y="108" fill="#2d3142" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">PAYMENTS</text>
128
+
129
+ <rect x="198" y="316" width="64" height="12" rx="2" fill="#f5f5f5"/>
130
+ <text data-name="Gateway" data-role="label" x="230" y="325" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">GATEWAY</text>
131
+
132
+ <rect x="858" y="347" width="64" height="12" rx="2" fill="#f5f5f5"/>
133
+ <text data-name="Reports" data-role="label" x="890" y="356" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">REPORTS</text>
134
+
135
+ <!-- Legend -->
136
+ <line x1="40" y1="462" x2="960" y2="462" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
137
+ <text x="40" y="478" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
138
+ <text x="960" y="478" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.06em" text-anchor="end">P95 VS ERROR RATE, BUBBLE AREA ∝ REQUESTS PER SECOND · BOTH AXES START AT ZERO · ILLUSTRATIVE FIGURES, NOT MEASURED SERVICES</text>
139
+
140
+ <circle cx="52" cy="490" r="6" fill="rgba(191,69,32,0.15)" stroke="#bf4520" stroke-width="1.2"/>
141
+ <text x="68" y="494" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Payments · focal, highest error rate at near-peak traffic</text>
142
+ <circle cx="660" cy="490" r="5" fill="rgba(45,49,66,0.23)" stroke="#4f5d75" stroke-width="1"/>
143
+ <text x="676" y="494" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Service · faintest fill is the largest bubble</text>
144
+ </svg>
145
+ </div>
146
+ </body>
147
+ </html>
@@ -0,0 +1,142 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Package rank by quarter · Bump chart</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap" rel="stylesheet">
8
+ <style>
9
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
10
+ :root {
11
+ --color-paper: #f5f5f5;
12
+ --color-ink: #2d3142;
13
+ --color-muted: #4f5d75;
14
+ --color-accent: #bf4520;
15
+ --font-sans: 'Geist', system-ui, sans-serif;
16
+ --font-serif: 'Instrument Serif', serif;
17
+ --font-mono: 'Geist Mono', ui-monospace, monospace;
18
+ }
19
+ body { font-family: var(--font-sans); background: var(--color-paper); color: var(--color-ink); min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 3rem 2rem; }
20
+ .frame { max-width: 1200px; width: 100%; }
21
+ .eyebrow { font-family: var(--font-mono); font-size: 0.66rem; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-muted); margin-bottom: 0.5rem; }
22
+ h1 { font-family: var(--font-serif); font-size: clamp(1.5rem, 2.4vw + 0.75rem, 2rem); font-weight: 400; letter-spacing: -0.02em; line-height: 1.15; margin-bottom: 1.5rem; }
23
+ svg { width: 100%; min-width: 760px; display: block; }
24
+ </style>
25
+ </head>
26
+ <body>
27
+ <div class="frame">
28
+ <p class="eyebrow">Bump chart · Diagram Design</p>
29
+ <h1>The default everyone stopped choosing</h1>
30
+
31
+ <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="bump-title bump-desc">
32
+ <title id="bump-title">The default everyone stopped choosing</title>
33
+ <desc id="bump-desc">Bump chart ranking six internal packages by weekly downloads across four quarters; legacy-http slides from first to sixth while fetch-kit takes the top rank in the second quarter and keeps it.</desc>
34
+ <defs>
35
+ <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
36
+ <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
37
+ </pattern>
38
+ </defs>
39
+
40
+ <rect width="100%" height="100%" fill="#f5f5f5"/>
41
+ <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
42
+
43
+ <!-- Rank is ORDINAL: every vertex sits exactly on a rank row, y = 88 + 56 x
44
+ (rank - 1), and every snapshot's ranks are a permutation of 1..6.
45
+ scripts/verify-bump.py enforces both against the ranks each series
46
+ declares - there is no tolerance, because rank has no fractions. -->
47
+ <text transform="rotate(-90 24 228)" x="24" y="228" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">RANK BY WEEKLY DOWNLOADS · 1 = MOST</text>
48
+
49
+ <!-- One axis rule per snapshot. No gridlines: the dots are the readable
50
+ positions and each series prints its first and last rank. -->
51
+ <line x1="320" y1="64" x2="320" y2="392" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
52
+ <text data-axis="0" data-state="Q1" x="320" y="416" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">Q1</text>
53
+ <line x1="440" y1="64" x2="440" y2="392" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
54
+ <text data-axis="1" data-state="Q2" x="440" y="416" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">Q2</text>
55
+ <line x1="560" y1="64" x2="560" y2="392" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
56
+ <text data-axis="2" data-state="Q3" x="560" y="416" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">Q3</text>
57
+ <line x1="680" y1="64" x2="680" y2="392" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
58
+ <text data-axis="3" data-state="Q4" x="680" y="416" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">Q4</text>
59
+
60
+ <!-- Straight segments between adjacent snapshots - never splines, which
61
+ invent a trajectory between ranks that were only measured quarterly.
62
+ Ramp ordered by Q1 rank: opacity records the opening order. -->
63
+ <path data-series="authx" data-ranks="2,3,3,2" d="M320,144 L440,200 L560,200 L680,144" fill="none" stroke="rgba(45,49,66,0.80)" stroke-width="1.2"/>
64
+ <circle cx="320" cy="144" r="3" fill="rgba(45,49,66,0.80)"/>
65
+ <circle cx="440" cy="200" r="3" fill="rgba(45,49,66,0.80)"/>
66
+ <circle cx="560" cy="200" r="3" fill="rgba(45,49,66,0.80)"/>
67
+ <circle cx="680" cy="144" r="3" fill="rgba(45,49,66,0.80)"/>
68
+ <text data-series="authx" data-end="first" data-role="name" x="272" y="147.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">authx</text>
69
+ <text data-series="authx" data-end="first" data-role="rank" x="304" y="147.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end">#2</text>
70
+ <text data-series="authx" data-end="last" data-role="rank" x="696" y="147.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">#2</text>
71
+ <text data-series="authx" data-end="last" data-role="name" x="728" y="147.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif">authx</text>
72
+
73
+ <path data-series="fetch-kit" data-ranks="3,1,1,1" d="M320,200 L440,88 L560,88 L680,88" fill="none" stroke="rgba(45,49,66,0.75)" stroke-width="1.2"/>
74
+ <circle cx="320" cy="200" r="3" fill="rgba(45,49,66,0.75)"/>
75
+ <circle cx="440" cy="88" r="3" fill="rgba(45,49,66,0.75)"/>
76
+ <circle cx="560" cy="88" r="3" fill="rgba(45,49,66,0.75)"/>
77
+ <circle cx="680" cy="88" r="3" fill="rgba(45,49,66,0.75)"/>
78
+ <text data-series="fetch-kit" data-end="first" data-role="name" x="272" y="203.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">fetch-kit</text>
79
+ <text data-series="fetch-kit" data-end="first" data-role="rank" x="304" y="203.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end">#3</text>
80
+ <text data-series="fetch-kit" data-end="last" data-role="rank" x="696" y="91.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">#1</text>
81
+ <text data-series="fetch-kit" data-end="last" data-role="name" x="728" y="91.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif">fetch-kit</text>
82
+
83
+ <path data-series="queuelib" data-ranks="4,5,5,4" d="M320,256 L440,312 L560,312 L680,256" fill="none" stroke="rgba(45,49,66,0.70)" stroke-width="1.2"/>
84
+ <circle cx="320" cy="256" r="3" fill="rgba(45,49,66,0.70)"/>
85
+ <circle cx="440" cy="312" r="3" fill="rgba(45,49,66,0.70)"/>
86
+ <circle cx="560" cy="312" r="3" fill="rgba(45,49,66,0.70)"/>
87
+ <circle cx="680" cy="256" r="3" fill="rgba(45,49,66,0.70)"/>
88
+ <text data-series="queuelib" data-end="first" data-role="name" x="272" y="259.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">queuelib</text>
89
+ <text data-series="queuelib" data-end="first" data-role="rank" x="304" y="259.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end">#4</text>
90
+ <text data-series="queuelib" data-end="last" data-role="rank" x="696" y="259.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">#4</text>
91
+ <text data-series="queuelib" data-end="last" data-role="name" x="728" y="259.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif">queuelib</text>
92
+
93
+ <path data-series="logfmt" data-ranks="5,4,2,3" d="M320,312 L440,256 L560,144 L680,200" fill="none" stroke="rgba(45,49,66,0.66)" stroke-width="1.2"/>
94
+ <circle cx="320" cy="312" r="3" fill="rgba(45,49,66,0.66)"/>
95
+ <circle cx="440" cy="256" r="3" fill="rgba(45,49,66,0.66)"/>
96
+ <circle cx="560" cy="144" r="3" fill="rgba(45,49,66,0.66)"/>
97
+ <circle cx="680" cy="200" r="3" fill="rgba(45,49,66,0.66)"/>
98
+ <text data-series="logfmt" data-end="first" data-role="name" x="272" y="315.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">logfmt</text>
99
+ <text data-series="logfmt" data-end="first" data-role="rank" x="304" y="315.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end">#5</text>
100
+ <text data-series="logfmt" data-end="last" data-role="rank" x="696" y="203.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">#3</text>
101
+ <text data-series="logfmt" data-end="last" data-role="name" x="728" y="203.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif">logfmt</text>
102
+
103
+ <path data-series="schema-gen" data-ranks="6,6,6,5" d="M320,368 L440,368 L560,368 L680,312" fill="none" stroke="rgba(45,49,66,0.62)" stroke-width="1.2"/>
104
+ <circle cx="320" cy="368" r="3" fill="rgba(45,49,66,0.62)"/>
105
+ <circle cx="440" cy="368" r="3" fill="rgba(45,49,66,0.62)"/>
106
+ <circle cx="560" cy="368" r="3" fill="rgba(45,49,66,0.62)"/>
107
+ <circle cx="680" cy="312" r="3" fill="rgba(45,49,66,0.62)"/>
108
+ <text data-series="schema-gen" data-end="first" data-role="name" x="272" y="371.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">schema-gen</text>
109
+ <text data-series="schema-gen" data-end="first" data-role="rank" x="304" y="371.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end">#6</text>
110
+ <text data-series="schema-gen" data-end="last" data-role="rank" x="696" y="315.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">#5</text>
111
+ <text data-series="schema-gen" data-end="last" data-role="name" x="728" y="315.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif">schema-gen</text>
112
+
113
+ <!-- legacy-http FOCAL - and it is the series that FELL. The accent marks the
114
+ editorially focal line, never the winner. Focus is carried by stroke
115
+ weight, not tone, for the reason the slopegraph section gives: the
116
+ accent measures 4.71:1 on light paper, mid-ramp. Drawn last so its descent
117
+ crosses over, not under, the lines it overtakes downward. -->
118
+ <path data-series="legacy-http" data-ranks="1,2,4,6" d="M320,88 L440,144 L560,256 L680,368" fill="none" stroke="#bf4520" stroke-width="2.4"/>
119
+ <circle cx="320" cy="88" r="4" fill="#bf4520"/>
120
+ <circle cx="440" cy="144" r="4" fill="#bf4520"/>
121
+ <circle cx="560" cy="256" r="4" fill="#bf4520"/>
122
+ <circle cx="680" cy="368" r="4" fill="#bf4520"/>
123
+ <text data-series="legacy-http" data-end="first" data-role="name" x="272" y="91.5" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">legacy-http</text>
124
+ <text data-series="legacy-http" data-end="first" data-role="rank" x="304" y="91.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end">#1</text>
125
+ <text data-series="legacy-http" data-end="last" data-role="rank" x="696" y="371.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">#6</text>
126
+ <text data-series="legacy-http" data-end="last" data-role="name" x="728" y="371.5" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif">legacy-http</text>
127
+
128
+ <!-- Legend -->
129
+ <line x1="40" y1="462" x2="960" y2="462" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
130
+ <text x="40" y="478" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
131
+ <text x="960" y="478" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.06em" text-anchor="end">RANKED BY WEEKLY DOWNLOADS, TIES KEEP PRIOR ORDER · SAME MEASURE EVERY QUARTER · ILLUSTRATIVE FIGURES, NOT A MEASURED REGISTRY</text>
132
+
133
+ <line x1="40" y1="492" x2="64" y2="492" stroke="#bf4520" stroke-width="2.4"/>
134
+ <circle cx="52" cy="492" r="4" fill="#bf4520"/>
135
+ <text x="72" y="496" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">legacy-http · focal, first to sixth in a year</text>
136
+ <line x1="320" y1="492" x2="344" y2="492" stroke="rgba(45,49,66,0.80)" stroke-width="1.2"/>
137
+ <circle cx="332" cy="492" r="3" fill="rgba(45,49,66,0.80)"/>
138
+ <text x="352" y="496" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Other packages · opacity records the Q1 order</text>
139
+ </svg>
140
+ </div>
141
+ </body>
142
+ </html>
@@ -0,0 +1,143 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Analytics pipeline · Data flow</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&amp;family=Geist:wght@400;500;600&amp;family=Geist+Mono:wght@400;500;600&amp;display=swap" rel="stylesheet">
8
+ <style>
9
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
10
+ :root {
11
+ --paper: #f5f5f5; --paper-2: #ececec; --ink: #2d3142; --muted: #4f5d75;
12
+ --soft: #5a6580; --rule: rgba(45,49,66,0.12); --accent: #bf4520;
13
+ --accent-tint: rgba(191,69,32,0.08); --link: #2e5aa8;
14
+ --sans: 'Geist', system-ui, sans-serif; --serif: 'Instrument Serif', serif;
15
+ --mono: 'Geist Mono', ui-monospace, monospace;
16
+ }
17
+ body { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 3rem 2rem; background: var(--paper); color: var(--ink); font-family: var(--sans); }
18
+ .frame { width: 100%; max-width: 1200px; }
19
+ .eyebrow { margin-bottom: 0.5rem; color: var(--muted); font: 500 0.66rem var(--mono); letter-spacing: 0.18em; text-transform: uppercase; }
20
+ h1 { margin-bottom: 1.5rem; color: var(--ink); font: 400 clamp(1.5rem, 2.4vw + 0.75rem, 2rem)/1.15 var(--serif); letter-spacing: -0.02em; }
21
+ svg { display: block; width: 100%; min-width: 728px; }
22
+ .step-number, .step-label, .lane-label, .role-text, .chip-text, .legend-label { font-family: var(--mono); text-anchor: middle; }
23
+ .step-number { fill: var(--ink); font-size: 7px; font-weight: 600; }
24
+ .step-label { fill: var(--muted); font-size: 7px; font-weight: 500; letter-spacing: 0.12em; }
25
+ .lane-label { fill: var(--muted); font-size: 8px; font-weight: 500; letter-spacing: 0.14em; }
26
+ .role-text { fill: var(--ink); font-size: 6px; font-weight: 600; }
27
+ .node-title { fill: var(--ink); font: 600 9px var(--sans); text-anchor: middle; }
28
+ .node-sub { fill: var(--muted); font: 400 6.5px var(--mono); text-anchor: middle; }
29
+ .node-tool { fill: var(--soft); font: 400 6.5px var(--mono); text-anchor: middle; }
30
+ .chip-text { fill: #fff; font-size: 5px; font-weight: 700; }
31
+ .focal-text { fill: var(--accent); }
32
+ .legend-label { fill: var(--muted); font-size: 7px; font-weight: 500; letter-spacing: 0.12em; text-anchor: end; }
33
+ .legend-text { fill: var(--muted); font: 400 7px var(--sans); }
34
+ </style>
35
+ </head>
36
+ <body>
37
+ <main class="frame">
38
+ <p class="eyebrow">Data flow · Diagram Design</p>
39
+ <h1>Role-scoped analytics pipeline</h1>
40
+
41
+ <svg viewBox="0 0 728 356" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="data-flow-title data-flow-desc">
42
+ <title id="data-flow-title">Role-scoped analytics data flow</title>
43
+ <desc id="data-flow-desc">A Data Engineer ingests and stores commerce data, a Data Scientist transforms and analyzes it, and an Analyst publishes a dashboard.</desc>
44
+ <defs>
45
+ <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="11" cy="11" r="0.8" fill="rgba(45,49,66,0.10)"/></pattern>
46
+ <marker id="arr-muted" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#4f5d75"/></marker>
47
+ <marker id="arr-accent" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#bf4520"/></marker>
48
+ <marker id="arr-link" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto"><path d="M0 0 L6 3 L0 6 Z" fill="#2e5aa8"/></marker>
49
+ </defs>
50
+ <rect width="728" height="356" fill="#f5f5f5"/>
51
+ <rect width="728" height="356" fill="url(#dots)"/>
52
+ <rect x="0" y="36" width="728" height="80" fill="rgba(45,49,66,0.018)"/>
53
+ <rect x="0" y="196" width="728" height="80" fill="rgba(45,49,66,0.018)"/>
54
+
55
+ <!-- Header and lane structure -->
56
+ <line x1="0" y1="36" x2="728" y2="36" stroke="rgba(45,49,66,0.12)" stroke-width="0.8"/>
57
+ <line x1="0" y1="116" x2="728" y2="116" stroke="rgba(45,49,66,0.12)" stroke-width="0.8"/>
58
+ <line x1="0" y1="196" x2="728" y2="196" stroke="rgba(45,49,66,0.12)" stroke-width="0.8"/>
59
+ <line x1="0" y1="276" x2="728" y2="276" stroke="rgba(45,49,66,0.12)" stroke-width="0.8"/>
60
+ <line x1="140" y1="36" x2="140" y2="276" stroke="rgba(45,49,66,0.12)" stroke-width="0.8"/>
61
+
62
+ <g aria-label="Pipeline steps">
63
+ <rect x="180" y="6" width="32" height="16" rx="8" fill="rgba(45,49,66,0.12)"/><text x="196" y="14" class="step-number">01</text><text x="196" y="29" class="step-label">INGEST</text>
64
+ <rect x="292" y="6" width="32" height="16" rx="8" fill="rgba(45,49,66,0.12)"/><text x="308" y="14" class="step-number">02</text><text x="308" y="29" class="step-label">STORE</text>
65
+ <rect x="404" y="6" width="32" height="16" rx="8" fill="rgba(191,69,32,0.20)"/><text x="420" y="14" class="step-number focal-text">03</text><text x="420" y="29" class="step-label focal-text">TRANSFORM</text>
66
+ <rect x="516" y="6" width="32" height="16" rx="8" fill="rgba(45,49,66,0.12)"/><text x="532" y="14" class="step-number">04</text><text x="532" y="29" class="step-label">ANALYZE</text>
67
+ <rect x="628" y="6" width="32" height="16" rx="8" fill="rgba(45,49,66,0.12)"/><text x="644" y="14" class="step-number">05</text><text x="644" y="29" class="step-label">PUBLISH</text>
68
+ </g>
69
+
70
+ <g aria-label="Role lanes">
71
+ <text x="70" y="72" class="lane-label">DATA</text><text x="70" y="84" class="lane-label">ENGINEER</text>
72
+ <text x="70" y="152" class="lane-label">DATA</text><text x="70" y="164" class="lane-label">SCIENTIST</text>
73
+ <text x="70" y="232" class="lane-label">ANALYTICS</text><text x="70" y="244" class="lane-label">ANALYST</text>
74
+ </g>
75
+
76
+ <!-- Connectors first. Cross-lane paths use r=8 orthogonal elbows. -->
77
+ <path d="M246 76 H258" fill="none" stroke="#4f5d75" marker-end="url(#arr-muted)"/>
78
+ <path d="M358 76 H412 Q420 76 420 84 V124" fill="none" stroke="#bf4520" stroke-width="1.2" marker-end="url(#arr-accent)"/>
79
+ <path d="M470 156 H482" fill="none" stroke="#4f5d75" marker-end="url(#arr-muted)"/>
80
+ <path d="M582 156 H636 Q644 156 644 164 V204" fill="none" stroke="#2e5aa8" marker-end="url(#arr-link)"/>
81
+ <rect x="368" y="56" width="48" height="12" rx="2" fill="#f5f5f5"/>
82
+ <text x="392" y="65" fill="#bf4520" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">RAW TABLE</text>
83
+
84
+ <!-- Data Engineer: Capture Events -->
85
+ <rect x="146" y="44" width="100" height="64" rx="6" fill="#f5f5f5" stroke="rgba(45,49,66,0.25)"/>
86
+ <rect x="150" y="48" width="18" height="10" rx="3" fill="rgba(45,49,66,0.12)"/><text x="159" y="53" class="role-text">ENG</text>
87
+ <text x="196" y="67" class="node-title">Capture Events</text><text x="196" y="79" class="node-sub">shop events → batch</text><text x="196" y="91" class="node-tool">NiFi ingest</text>
88
+ <rect x="150" y="98" width="16" height="8" rx="3" fill="#7c8f6f"/><text x="158" y="104" class="chip-text">LS</text>
89
+ <rect x="226" y="98" width="16" height="8" rx="3" fill="#5e7a9b"/><text x="234" y="104" class="chip-text">DB</text>
90
+
91
+ <!-- Data Engineer: Land Records -->
92
+ <rect x="258" y="44" width="100" height="64" rx="6" fill="#f5f5f5" stroke="rgba(45,49,66,0.25)"/>
93
+ <rect x="262" y="48" width="18" height="10" rx="3" fill="rgba(45,49,66,0.12)"/><text x="271" y="53" class="role-text">ENG</text>
94
+ <text x="308" y="67" class="node-title">Land Records</text><text x="308" y="79" class="node-sub">events · orders</text><text x="308" y="91" class="node-tool">Object storage</text>
95
+ <rect x="262" y="98" width="16" height="8" rx="3" fill="#5e7a9b"/><text x="270" y="104" class="chip-text">DB</text>
96
+ <rect x="338" y="98" width="16" height="8" rx="3" fill="#5e7a9b"/><text x="346" y="104" class="chip-text">DB</text>
97
+
98
+ <!-- Data Scientist: Clean and Model (focal) -->
99
+ <rect x="370" y="124" width="100" height="64" rx="6" fill="rgba(191,69,32,0.07)" stroke="#bf4520" stroke-width="1.2"/>
100
+ <rect x="374" y="128" width="18" height="10" rx="3" fill="rgba(191,69,32,0.20)"/><text x="383" y="133" class="role-text focal-text">SCI</text>
101
+ <text x="420" y="147" class="node-title">Clean &amp; Model</text><text x="420" y="159" class="node-sub">raw → trusted table</text><text x="420" y="171" class="node-tool">Trino · notebooks</text>
102
+ <rect x="374" y="178" width="16" height="8" rx="3" fill="#5e7a9b"/><text x="382" y="184" class="chip-text">DB</text>
103
+ <rect x="450" y="178" width="16" height="8" rx="3" fill="#b8915a"/><text x="458" y="184" class="chip-text">TB</text>
104
+
105
+ <!-- Data Scientist: Curate Metrics -->
106
+ <rect x="482" y="124" width="100" height="64" rx="6" fill="#f5f5f5" stroke="rgba(45,49,66,0.25)"/>
107
+ <rect x="486" y="128" width="18" height="10" rx="3" fill="rgba(45,49,66,0.12)"/><text x="495" y="133" class="role-text">SCI</text>
108
+ <text x="532" y="147" class="node-title">Curate Metrics</text><text x="532" y="159" class="node-sub">conversion · revenue</text><text x="532" y="171" class="node-tool">Trino SQL</text>
109
+ <rect x="486" y="178" width="16" height="8" rx="3" fill="#b8915a"/><text x="494" y="184" class="chip-text">TB</text>
110
+ <rect x="562" y="178" width="16" height="8" rx="3" fill="#b8915a"/><text x="570" y="184" class="chip-text">TB</text>
111
+
112
+ <!-- Analyst: Publish Dashboard -->
113
+ <rect x="594" y="204" width="100" height="64" rx="6" fill="#f5f5f5" stroke="rgba(45,49,66,0.25)"/>
114
+ <rect x="598" y="208" width="18" height="10" rx="3" fill="rgba(45,49,66,0.12)"/><text x="607" y="213" class="role-text">ANL</text>
115
+ <text x="644" y="227" class="node-title">Publish Dashboard</text><text x="644" y="239" class="node-sub">metrics → decisions</text><text x="644" y="251" class="node-tool">BI workspace</text>
116
+ <rect x="598" y="258" width="16" height="8" rx="3" fill="#b8915a"/><text x="606" y="264" class="chip-text">TB</text>
117
+ <rect x="674" y="258" width="16" height="8" rx="3" fill="#9c6b50"/><text x="682" y="264" class="chip-text">FL</text>
118
+
119
+ <!-- Legend: steps -->
120
+ <text x="164" y="293" class="legend-label">STEPS</text>
121
+ <rect x="180" y="284" width="24" height="12" rx="6" fill="rgba(45,49,66,0.12)"/><text x="192" y="292" class="step-number">01</text><text x="212" y="293" class="legend-text">Ingest</text>
122
+ <rect x="272" y="284" width="24" height="12" rx="6" fill="rgba(45,49,66,0.12)"/><text x="284" y="292" class="step-number">02</text><text x="304" y="293" class="legend-text">Store</text>
123
+ <rect x="360" y="284" width="24" height="12" rx="6" fill="rgba(191,69,32,0.20)"/><text x="372" y="292" class="step-number focal-text">03</text><text x="392" y="293" class="legend-text">Transform</text>
124
+ <rect x="468" y="284" width="24" height="12" rx="6" fill="rgba(45,49,66,0.12)"/><text x="480" y="292" class="step-number">04</text><text x="500" y="293" class="legend-text">Analyze</text>
125
+ <rect x="568" y="284" width="24" height="12" rx="6" fill="rgba(45,49,66,0.12)"/><text x="580" y="292" class="step-number">05</text><text x="600" y="293" class="legend-text">Publish</text>
126
+
127
+ <!-- Legend: data types -->
128
+ <text x="164" y="314" class="legend-label">DATA TYPE</text>
129
+ <rect x="180" y="306" width="16" height="8" rx="3" fill="#7c8f6f"/><text x="188" y="312" class="chip-text">LS</text><text x="202" y="314" class="legend-text">Stream</text>
130
+ <rect x="252" y="306" width="16" height="8" rx="3" fill="#5e7a9b"/><text x="260" y="312" class="chip-text">DB</text><text x="274" y="314" class="legend-text">Dataset</text>
131
+ <rect x="332" y="306" width="16" height="8" rx="3" fill="#b8915a"/><text x="340" y="312" class="chip-text">TB</text><text x="354" y="314" class="legend-text">Table</text>
132
+ <rect x="404" y="306" width="16" height="8" rx="3" fill="#9c6b50"/><text x="412" y="312" class="chip-text">FL</text><text x="426" y="314" class="legend-text">Dashboard</text>
133
+ <text x="500" y="314" class="legend-text">left chip = input · right chip = output</text>
134
+
135
+ <!-- Legend: flow -->
136
+ <text x="164" y="336" class="legend-label">FLOW</text>
137
+ <line x1="180" y1="333" x2="204" y2="333" stroke="#4f5d75" marker-end="url(#arr-muted)"/><text x="212" y="336" class="legend-text">Standard handoff</text>
138
+ <line x1="324" y1="333" x2="348" y2="333" stroke="#bf4520" stroke-width="1.2" marker-end="url(#arr-accent)"/><text x="356" y="336" class="legend-text">Focal handoff</text>
139
+ <line x1="460" y1="333" x2="484" y2="333" stroke="#2e5aa8" marker-end="url(#arr-link)"/><text x="492" y="336" class="legend-text">Published output</text>
140
+ </svg>
141
+ </main>
142
+ </body>
143
+ </html>