scrum-skills 0.3.2 → 0.3.3

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 (384) hide show
  1. package/.agents/skills/diagram-design/LICENSE +4 -0
  2. package/.agents/skills/diagram-design/SKILL.md +413 -0
  3. package/.agents/skills/diagram-design/UPSTREAM.json +76 -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 +146 -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 +224 -201
  150. package/assets/board/200.html +1 -1
  151. package/assets/board/404.html +1 -1
  152. package/assets/board/_nuxt/1XlYaCp9.js +1 -0
  153. package/assets/board/_nuxt/4gQF_HS3.js +1 -0
  154. package/assets/board/_nuxt/5okfNy5D.js +1 -0
  155. package/assets/board/_nuxt/{Bb3Limos.js → B0C2jsdk.js} +1 -1
  156. package/assets/board/_nuxt/B1j6UC4U.js +1 -0
  157. package/assets/board/_nuxt/B3LKy6o2.js +1 -0
  158. package/assets/board/_nuxt/BAQQngAq.js +13 -0
  159. package/assets/board/_nuxt/BE6t7Q2m.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/BW3xJdEx.js +1 -0
  164. package/assets/board/_nuxt/{Cm9lkUvP.js → BY36DFyj.js} +1 -1
  165. package/assets/board/_nuxt/BZlZD94i.js +1 -0
  166. package/assets/board/_nuxt/BZvXNwev.js +3 -0
  167. package/assets/board/_nuxt/BbxmvdIF.js +1 -0
  168. package/assets/board/_nuxt/BiWrMOsL.js +1 -0
  169. package/assets/board/_nuxt/BizDeOK5.js +1 -0
  170. package/assets/board/_nuxt/BkcaOYQ_.js +95 -0
  171. package/assets/board/_nuxt/BkoKCNUY.js +1 -0
  172. package/assets/board/_nuxt/BlKmZhhF.js +1 -0
  173. package/assets/board/_nuxt/BmBpmU73.js +1 -0
  174. package/assets/board/_nuxt/BrWE0up6.js +1 -0
  175. package/assets/board/_nuxt/Bs52qkgk.js +1 -0
  176. package/assets/board/_nuxt/BtzUbHO_.js +1 -0
  177. package/assets/board/_nuxt/BuBzMkFZ.js +1 -0
  178. package/assets/board/_nuxt/Bubk0xn-.js +1 -0
  179. package/assets/board/_nuxt/BxuBMtk_.js +3 -0
  180. package/assets/board/_nuxt/By1KXXLR.js +1 -0
  181. package/assets/board/_nuxt/BygIGL69.js +2 -0
  182. package/assets/board/_nuxt/C1iO5KH3.js +1 -0
  183. package/assets/board/_nuxt/C2YPmTzt.js +1 -0
  184. package/assets/board/_nuxt/C3SpAhCW.js +1 -0
  185. package/assets/board/_nuxt/C3ZRWz5L.js +1 -0
  186. package/assets/board/_nuxt/C4WdPP6K.js +1 -0
  187. package/assets/board/_nuxt/C6o03JHe.js +1 -0
  188. package/assets/board/_nuxt/C8qB5llI.js +1 -0
  189. package/assets/board/_nuxt/C9MgRdhu.js +1 -0
  190. package/assets/board/_nuxt/CCA81-4P.js +1 -0
  191. package/assets/board/_nuxt/{D2O8Q8x9.js → CFCM18fF.js} +1 -1
  192. package/assets/board/_nuxt/CGXljzd_.js +1 -0
  193. package/assets/board/_nuxt/CI0scS-N.js +1 -0
  194. package/assets/board/_nuxt/CJs9B42o.js +1 -0
  195. package/assets/board/_nuxt/COecDWbb.js +1 -0
  196. package/assets/board/_nuxt/COmtTtfB.js +1 -0
  197. package/assets/board/_nuxt/CPYm4J_K.js +1 -0
  198. package/assets/board/_nuxt/CReA4TEB.js +3 -0
  199. package/assets/board/_nuxt/CXG7GZes.js +1 -0
  200. package/assets/board/_nuxt/CYGiZn-X.js +1 -0
  201. package/assets/board/_nuxt/CaE8VlUp.js +1 -0
  202. package/assets/board/_nuxt/CcGiNUgA.js +1 -0
  203. package/assets/board/_nuxt/Ccgv3lDj.js +1 -0
  204. package/assets/board/_nuxt/CdPGFZyy.js +1 -0
  205. package/assets/board/_nuxt/{DfR3IZN_.js → Cdf_T8Xa.js} +1 -1
  206. package/assets/board/_nuxt/CgQ30j_6.js +1 -0
  207. package/assets/board/_nuxt/ChUHb39z.js +1 -0
  208. package/assets/board/_nuxt/Ck0-FqVI.js +1 -0
  209. package/assets/board/_nuxt/CkWKLtjO.js +1 -0
  210. package/assets/board/_nuxt/Cq7hsCKB.js +1 -0
  211. package/assets/board/_nuxt/CtFknnHZ.js +1 -0
  212. package/assets/board/_nuxt/D166WVUG.js +1 -0
  213. package/assets/board/_nuxt/D4Dpzo9e.js +1 -0
  214. package/assets/board/_nuxt/D5i92OZO.js +1 -0
  215. package/assets/board/_nuxt/D6dUp4Nm.js +9 -0
  216. package/assets/board/_nuxt/DFQDFspC.js +1 -0
  217. package/assets/board/_nuxt/DHX2tw9J.js +1 -0
  218. package/assets/board/_nuxt/DJM7u8P3.js +1 -0
  219. package/assets/board/_nuxt/{BPTrRhcw.js → DLr85ebo.js} +1 -1
  220. package/assets/board/_nuxt/DOMM1wfl.js +1 -0
  221. package/assets/board/_nuxt/DU6ArlUN.js +1 -0
  222. package/assets/board/_nuxt/{B_SlFcWp.js → DUgGsde6.js} +1 -1
  223. package/assets/board/_nuxt/DV4ti-Pq.js +1 -0
  224. package/assets/board/_nuxt/DZ--fXuU.js +1 -0
  225. package/assets/board/_nuxt/D_ct-Stz.js +2 -0
  226. package/assets/board/_nuxt/DbWAComO.js +1 -0
  227. package/assets/board/_nuxt/DbwlcHAt.js +1 -0
  228. package/assets/board/_nuxt/DjzLR9Bl.js +1 -0
  229. package/assets/board/_nuxt/Dki9VkAL.js +3 -0
  230. package/assets/board/_nuxt/DlNJhOoc.js +1 -0
  231. package/assets/board/_nuxt/DqG7CtD4.js +1 -0
  232. package/assets/board/_nuxt/DqUSsCJ2.js +1 -0
  233. package/assets/board/_nuxt/Du2F4WXh.js +1 -0
  234. package/assets/board/_nuxt/DuRiEXn4.js +1 -0
  235. package/assets/board/_nuxt/DxBwVNyP.js +2 -0
  236. package/assets/board/_nuxt/DzmVW5-D.js +1 -0
  237. package/assets/board/_nuxt/I-sGtDIB.js +6 -0
  238. package/assets/board/_nuxt/JU9-x68N.js +1 -0
  239. package/assets/board/_nuxt/Lozm7hhE.js +1 -0
  240. package/assets/board/_nuxt/MMsTMkcB.js +1 -0
  241. package/assets/board/_nuxt/MS7CGmCB.js +1 -0
  242. package/assets/board/_nuxt/OKKaKILz.js +1 -0
  243. package/assets/board/_nuxt/{Csqgy925.js → P6qlvBHA.js} +1 -1
  244. package/assets/board/_nuxt/SrNUvNwO.js +1 -0
  245. package/assets/board/_nuxt/{DSaWoFHS.js → SywdkA98.js} +1 -1
  246. package/assets/board/_nuxt/TBIRpVLG.js +1 -0
  247. package/assets/board/_nuxt/TlTrMIMm.js +1 -0
  248. package/assets/board/_nuxt/Zv9-SOQF.js +1 -0
  249. package/assets/board/_nuxt/_id_.ItzoSaBL.css +1 -0
  250. package/assets/board/_nuxt/builds/latest.json +1 -1
  251. package/assets/board/_nuxt/builds/meta/2218461a-f45b-41d6-ae44-b0d2332a9511.json +1 -0
  252. package/assets/board/_nuxt/burndown.CT8fx1Ge.css +1 -0
  253. package/assets/board/_nuxt/diagrams.D1ybqBem.css +1 -0
  254. package/assets/board/_nuxt/{entry.CKHePurH.css → entry.BCuHiFgF.css} +1 -1
  255. package/assets/board/_nuxt/epics.CUeDIEa0.css +1 -0
  256. package/assets/board/_nuxt/error-404.Y9imKiDC.css +1 -0
  257. package/assets/board/_nuxt/error-500.DufSBGVC.css +1 -0
  258. package/assets/board/_nuxt/gantt.CiC2Ts1t.css +1 -0
  259. package/assets/board/_nuxt/jbri6q1p.js +1 -0
  260. package/assets/board/_nuxt/last-change.C05Vc3BF.css +1 -0
  261. package/assets/board/_nuxt/milestones.Civ3sMiQ.css +1 -0
  262. package/assets/board/_nuxt/oSJF4yHw.js +1 -0
  263. package/assets/board/_nuxt/pages.BshWbOyo.css +1 -0
  264. package/assets/board/_nuxt/q_8bxRMt.js +1 -0
  265. package/assets/board/_nuxt/tests.Ci9fBCka.css +1 -0
  266. package/assets/board/burndown/index.html +1 -1
  267. package/assets/board/diagrams/index.html +1 -0
  268. package/assets/board/epics/index.html +1 -1
  269. package/assets/board/favicon.svg +16 -16
  270. package/assets/board/gantt/index.html +1 -1
  271. package/assets/board/index.html +1 -1
  272. package/assets/board/last-change/index.html +1 -1
  273. package/assets/board/milestones/index.html +1 -1
  274. package/assets/board/tests/index.html +1 -1
  275. package/bin/scrum-skills.mjs +204 -191
  276. package/docs/ai-assistant-guide.md +1008 -1008
  277. package/package.json +42 -41
  278. package/templates/AGENTS.md +84 -74
  279. package/tools/agile-tools.mjs +510 -510
  280. package/tools/ai.mjs +464 -464
  281. package/tools/diagram-import.mjs +238 -0
  282. package/tools/diagram-lint.mjs +518 -0
  283. package/tools/diagram.mjs +299 -0
  284. package/tools/git-commit.mjs +216 -216
  285. package/tools/last-change.mjs +326 -326
  286. package/tools/projects.mjs +240 -215
  287. package/tools/serve.mjs +180 -154
  288. package/tools/validate.mjs +781 -664
  289. package/assets/board/_nuxt/1eqboJxR.js +0 -1
  290. package/assets/board/_nuxt/2K7ag6ES.js +0 -1
  291. package/assets/board/_nuxt/51OWHj8c.js +0 -2
  292. package/assets/board/_nuxt/6gFtTBwm.js +0 -1
  293. package/assets/board/_nuxt/B3jkABw9.js +0 -1
  294. package/assets/board/_nuxt/B5n2_jZN.js +0 -1
  295. package/assets/board/_nuxt/BDK2Hj7B.js +0 -1
  296. package/assets/board/_nuxt/BDcnzXHq.js +0 -1
  297. package/assets/board/_nuxt/BaG8y0Wt.js +0 -1
  298. package/assets/board/_nuxt/BbwJq5pb.js +0 -1
  299. package/assets/board/_nuxt/BgLeKwx0.js +0 -1
  300. package/assets/board/_nuxt/Bi9Axj3V.js +0 -1
  301. package/assets/board/_nuxt/BmxvtaMq.js +0 -1
  302. package/assets/board/_nuxt/BodFvto3.js +0 -1
  303. package/assets/board/_nuxt/BpWeHLuN.js +0 -1
  304. package/assets/board/_nuxt/BuOKDFiJ.js +0 -1
  305. package/assets/board/_nuxt/C40iTe-x.js +0 -1
  306. package/assets/board/_nuxt/C7K0R7F-.js +0 -2
  307. package/assets/board/_nuxt/C8vL692X.js +0 -1
  308. package/assets/board/_nuxt/C9StZL3D.js +0 -3
  309. package/assets/board/_nuxt/CGI_ZV79.js +0 -1
  310. package/assets/board/_nuxt/CJ2mz0WY.js +0 -1
  311. package/assets/board/_nuxt/CJMBJQuf.js +0 -1
  312. package/assets/board/_nuxt/CK-lOYG9.js +0 -1
  313. package/assets/board/_nuxt/CK9_veoz.js +0 -1
  314. package/assets/board/_nuxt/CLBcBrYf.js +0 -1
  315. package/assets/board/_nuxt/CMUi2-Lj.js +0 -1
  316. package/assets/board/_nuxt/COf6E6h4.js +0 -1
  317. package/assets/board/_nuxt/CPCUMJnF.js +0 -1
  318. package/assets/board/_nuxt/CPcKlmSm.js +0 -1
  319. package/assets/board/_nuxt/CQTvWh4i.js +0 -1
  320. package/assets/board/_nuxt/CSEEUF8S.js +0 -1
  321. package/assets/board/_nuxt/CSSb154I.js +0 -13
  322. package/assets/board/_nuxt/CgDTd7jS.js +0 -1
  323. package/assets/board/_nuxt/ChG76uh9.js +0 -1
  324. package/assets/board/_nuxt/Ci0qbkgh.js +0 -1
  325. package/assets/board/_nuxt/CqoQ__I_.js +0 -1
  326. package/assets/board/_nuxt/CuJUHLl8.js +0 -1
  327. package/assets/board/_nuxt/CvLiA4_O.js +0 -1
  328. package/assets/board/_nuxt/Cvs12oA0.js +0 -3
  329. package/assets/board/_nuxt/CyEXFe3V.js +0 -1
  330. package/assets/board/_nuxt/Cz6rZcLK.js +0 -1
  331. package/assets/board/_nuxt/D2FhHl1o.js +0 -1
  332. package/assets/board/_nuxt/D3YCAmfu.js +0 -1
  333. package/assets/board/_nuxt/D5CE81jK.js +0 -1
  334. package/assets/board/_nuxt/D75vbfSb.js +0 -1
  335. package/assets/board/_nuxt/D99LbGfb.js +0 -9
  336. package/assets/board/_nuxt/DEfLc7p3.js +0 -6
  337. package/assets/board/_nuxt/DF-nsa1Z.js +0 -1
  338. package/assets/board/_nuxt/DIc8yx98.js +0 -1
  339. package/assets/board/_nuxt/DLkAKotw.js +0 -1
  340. package/assets/board/_nuxt/DRPlYvb3.js +0 -1
  341. package/assets/board/_nuxt/DRlQgul3.js +0 -1
  342. package/assets/board/_nuxt/DSLbmoWa.js +0 -1
  343. package/assets/board/_nuxt/DWO9c9yp.js +0 -1
  344. package/assets/board/_nuxt/DZo3dYLJ.js +0 -3
  345. package/assets/board/_nuxt/D_S6N7_b.js +0 -1
  346. package/assets/board/_nuxt/DajA-Tkt.js +0 -1
  347. package/assets/board/_nuxt/DbHiyab-.js +0 -1
  348. package/assets/board/_nuxt/Dc7Ql6eE.js +0 -1
  349. package/assets/board/_nuxt/Dd9ZukPU.js +0 -1
  350. package/assets/board/_nuxt/Dg2LiqmN.js +0 -1
  351. package/assets/board/_nuxt/DhuleNnm.js +0 -1
  352. package/assets/board/_nuxt/DkI1Qxpp.js +0 -95
  353. package/assets/board/_nuxt/DnDHGSYI.js +0 -1
  354. package/assets/board/_nuxt/DpXJ_tCU.js +0 -1
  355. package/assets/board/_nuxt/DqZgF3hU.js +0 -1
  356. package/assets/board/_nuxt/DqcxvfbD.js +0 -1
  357. package/assets/board/_nuxt/DsA2lVci.js +0 -1
  358. package/assets/board/_nuxt/Dtsa-1NS.js +0 -1
  359. package/assets/board/_nuxt/Du91iq0p.js +0 -1
  360. package/assets/board/_nuxt/Dx1wcYFo.js +0 -1
  361. package/assets/board/_nuxt/EYTShbt4.js +0 -1
  362. package/assets/board/_nuxt/MaXJprwN.js +0 -1
  363. package/assets/board/_nuxt/P9x67aq2.js +0 -1
  364. package/assets/board/_nuxt/S08nFESZ.js +0 -3
  365. package/assets/board/_nuxt/V0uynWE2.js +0 -1
  366. package/assets/board/_nuxt/Vo4wMbnS.js +0 -1
  367. package/assets/board/_nuxt/ZVTqot-_.js +0 -1
  368. package/assets/board/_nuxt/ZngEd3HB.js +0 -1
  369. package/assets/board/_nuxt/_id_.B2NDKSlX.css +0 -1
  370. package/assets/board/_nuxt/assMu_Wn.js +0 -1
  371. package/assets/board/_nuxt/builds/meta/8e23aec9-5b67-4569-b8bf-d4f07e50ffdf.json +0 -1
  372. package/assets/board/_nuxt/burndown.Do6IbM6o.css +0 -1
  373. package/assets/board/_nuxt/epics.Dmessplu.css +0 -1
  374. package/assets/board/_nuxt/error-404.BFmXOnCT.css +0 -1
  375. package/assets/board/_nuxt/error-500.BZ-DdjQ6.css +0 -1
  376. package/assets/board/_nuxt/gantt.Dmp00GUo.css +0 -1
  377. package/assets/board/_nuxt/last-change.1Su4GrCN.css +0 -1
  378. package/assets/board/_nuxt/milestones.U0xKCsEo.css +0 -1
  379. package/assets/board/_nuxt/pages.Dbj2IVk8.css +0 -1
  380. package/assets/board/_nuxt/rlePnzpc.js +0 -1
  381. package/assets/board/_nuxt/tests.dXlUX16A.css +0 -1
  382. package/assets/board/_nuxt/uKzCKCTq.js +0 -1
  383. package/assets/board/_nuxt/vwxaNGfc.js +0 -1
  384. package/assets/board/_nuxt/yh6sf_D5.js +0 -1
@@ -0,0 +1,139 @@
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>Storage backends · Capability radar</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
+
20
+ body {
21
+ font-family: var(--font-sans);
22
+ background: var(--color-paper);
23
+ color: var(--color-ink);
24
+ min-height: 100vh;
25
+ display: flex;
26
+ align-items: center;
27
+ justify-content: center;
28
+ padding: 3rem 2rem;
29
+ }
30
+
31
+ .frame { max-width: 1200px; width: 100%; }
32
+
33
+ .eyebrow {
34
+ font-family: var(--font-mono);
35
+ font-size: 0.66rem;
36
+ font-weight: 500;
37
+ letter-spacing: 0.18em;
38
+ text-transform: uppercase;
39
+ color: var(--color-muted);
40
+ margin-bottom: 0.5rem;
41
+ }
42
+
43
+ h1 {
44
+ font-family: var(--font-serif);
45
+ font-size: clamp(1.5rem, 2.4vw + 0.75rem, 2rem);
46
+ font-weight: 400;
47
+ letter-spacing: -0.02em;
48
+ line-height: 1.15;
49
+ color: var(--color-ink);
50
+ margin-bottom: 1.5rem;
51
+ }
52
+
53
+ svg { width: 100%; min-width: 900px; display: block; }
54
+ </style>
55
+ </head>
56
+ <body>
57
+ <div class="frame">
58
+ <p class="eyebrow">Radar · Diagram Design</p>
59
+ <h1>Storage backends · Capability radar</h1>
60
+
61
+ <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="radar-title radar-desc">
62
+ <title id="radar-title">Storage backends · Capability radar</title>
63
+ <desc id="radar-desc">Radar chart comparing MinIO, Amazon S3, Ceph, and Google Cloud Storage across five storage capabilities.</desc>
64
+ <defs>
65
+ <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
66
+ <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
67
+ </pattern>
68
+ </defs>
69
+
70
+ <rect width="100%" height="100%" fill="#f5f5f5"/>
71
+ <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
72
+
73
+ <!-- Concentric grid rings (f = 0.2, 0.4, 0.6, 0.8, 1.0) -->
74
+ <polygon points="500,208 530,230 519,266 481,266 470,230" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
75
+ <polygon points="500,176 561,220 538,292 462,292 439,220" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
76
+ <polygon points="500,144 591,211 556,317 444,317 409,211" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
77
+ <polygon points="500,112 622,201 575,343 425,343 378,201" fill="none" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
78
+ <polygon points="500,80 652,191 594,369 406,369 348,191" fill="none" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
79
+
80
+ <!-- Axis spokes (center to outer vertex) -->
81
+ <line x1="500" y1="240" x2="500" y2="80" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
82
+ <line x1="500" y1="240" x2="652" y2="191" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
83
+ <line x1="500" y1="240" x2="594" y2="369" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
84
+ <line x1="500" y1="240" x2="406" y2="369" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
85
+ <line x1="500" y1="240" x2="348" y2="191" stroke="rgba(45,49,66,0.20)" stroke-width="1"/>
86
+
87
+ <!-- Axis labels (one word per spoke, Geist sans 11px 600) -->
88
+ <text x="500" y="62" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Small-file handling</text>
89
+ <text x="669" y="189" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Large-object reads</text>
90
+ <text x="605" y="400" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Write throughput</text>
91
+ <text x="395" y="400" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">Operational simplicity</text>
92
+ <text x="331" y="189" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">Iceberg integration</text>
93
+
94
+ <!-- Scale ticks on first (top) axis only -->
95
+ <text x="494" y="82" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">10</text>
96
+ <text x="494" y="114" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">8</text>
97
+ <text x="494" y="146" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">6</text>
98
+ <text x="494" y="178" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">4</text>
99
+ <text x="494" y="210" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">2</text>
100
+
101
+ <!-- Non-focal series (smallest to largest, back to front) -->
102
+ <!-- Ceph · series-2 dusty-blue · [7,7,7,4,6] -->
103
+ <polygon points="500,128 606,206 566,330 462,292 409,211" fill="rgba(94,122,155,0.18)" stroke="#5e7a9b" stroke-width="1.5"/>
104
+ <!-- GCS · series-3 mustard · [6,9,8,6,7] -->
105
+ <polygon points="500,144 637,196 575,343 444,317 394,206" fill="rgba(184,145,90,0.18)" stroke="#b8915a" stroke-width="1.5"/>
106
+ <!-- Amazon S3 · series-1 sage · [6,10,9,5,8] -->
107
+ <polygon points="500,144 652,191 585,356 453,305 378,201" fill="rgba(124,143,111,0.18)" stroke="#7c8f6f" stroke-width="1.5"/>
108
+
109
+ <!-- Focal series · MinIO · accent · [9,8,9,9,9] -->
110
+ <polygon points="500,96 622,201 585,356 415,356 363,196" fill="rgba(191,69,32,0.18)" stroke="#bf4520" stroke-width="1.8"/>
111
+
112
+ <!-- Focal vertex dots (only on focal series) -->
113
+ <circle cx="500" cy="96" r="4" fill="#bf4520"/>
114
+ <circle cx="622" cy="201" r="4" fill="#bf4520"/>
115
+ <circle cx="585" cy="356" r="4" fill="#bf4520"/>
116
+ <circle cx="415" cy="356" r="4" fill="#bf4520"/>
117
+ <circle cx="363" cy="196" r="4" fill="#bf4520"/>
118
+
119
+ <!-- Legend -->
120
+ <line x1="40" y1="456" x2="960" y2="456" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
121
+ <text x="40" y="472" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
122
+
123
+ <rect x="40" y="484" width="16" height="8" fill="rgba(191,69,32,0.18)" stroke="#bf4520" stroke-width="1.5"/>
124
+ <text x="64" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">MinIO · recommended</text>
125
+
126
+ <rect x="220" y="484" width="16" height="8" fill="rgba(124,143,111,0.18)" stroke="#7c8f6f" stroke-width="1.5"/>
127
+ <text x="244" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Amazon S3</text>
128
+
129
+ <rect x="344" y="484" width="16" height="8" fill="rgba(94,122,155,0.18)" stroke="#5e7a9b" stroke-width="1.5"/>
130
+ <text x="368" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Ceph</text>
131
+
132
+ <rect x="424" y="484" width="16" height="8" fill="rgba(184,145,90,0.18)" stroke="#b8915a" stroke-width="1.5"/>
133
+ <text x="448" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Google Cloud Storage</text>
134
+
135
+ <text x="608" y="492" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">One coral. Position is the signal — color reserved for the recommended option.</text>
136
+ </svg>
137
+ </div>
138
+ </body>
139
+ </html>
@@ -0,0 +1,104 @@
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>Request latency by service · Ridgeline</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">Ridgeline · Diagram Design</p>
29
+ <h1>Checkout is slow in two different ways</h1>
30
+
31
+ <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="ridgeline-title ridgeline-desc">
32
+ <title id="ridgeline-title">Checkout is slow in two different ways</title>
33
+ <desc id="ridgeline-desc">Ridgeline chart of request-latency distributions for five services over one week; each ridge is the share of that service's requests falling in 40-millisecond bins, drawn on one shared amplitude scale, and checkout-api carries a second peak past 300 milliseconds that none of the other four show.</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
+ <!-- ONE amplitude on every ridge: y = baseline - 2.4 x (share in %). Per-ridge
44
+ normalisation would let a rare, flat distribution wear the same silhouette
45
+ as a tight one, which is the single lie this type is built to tell.
46
+ scripts/verify-ridgeline.py derives the amplitude from the figure and then
47
+ holds every vertex of every ridge to it. -->
48
+ <text transform="rotate(-90 24 264)" x="24" y="264" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">SHARE OF REQUESTS · 1% = 2.4PX ON EVERY RIDGE</text>
49
+
50
+ <!-- One baseline per ridge, 56px pitch. The baseline is where a bin of zero
51
+ requests sits, so it can never be moved to give a ridge more room. -->
52
+ <line data-ridge="static-cdn" data-role="baseline" x1="320" y1="152" x2="680" y2="152" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
53
+ <line data-ridge="auth-api" data-role="baseline" x1="320" y1="208" x2="680" y2="208" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
54
+ <line data-ridge="search-api" data-role="baseline" x1="320" y1="264" x2="680" y2="264" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
55
+ <line data-ridge="checkout-api" data-role="baseline" x1="320" y1="320" x2="680" y2="320" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
56
+ <line data-ridge="report-export" data-role="baseline" x1="320" y1="376" x2="680" y2="376" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
57
+
58
+ <!-- Shared x-scale: every ridge is sampled at the same 13 bins, 40ms wide,
59
+ labelled at the lower edge. Straight segments between bins - no smoothing,
60
+ because a spline through 13 bins invents extrema the sample never had. -->
61
+ <path data-ridge="static-cdn" data-baseline="152" data-bins="0,26,34,21,11,5,2,1,0,0,0,0,0" d="M320,152 L350,89.6 L380,70.4 L410,101.6 L440,125.6 L470,140 L500,147.2 L530,149.6 L560,152 L590,152 L620,152 L650,152 L680,152 Z" fill="rgba(45,49,66,0.12)" stroke="rgba(45,49,66,0.80)" stroke-width="1.2" stroke-linejoin="round"/>
62
+ <text data-ridge="static-cdn" data-role="name" x="304" y="155.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">static-cdn</text>
63
+ <text data-ridge="static-cdn" data-role="range" x="696" y="155.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">40–280 ms</text>
64
+ <path data-ridge="auth-api" data-baseline="208" data-bins="0,6,28,36,18,7,3,1,1,0,0,0,0" d="M320,208 L350,193.6 L380,140.8 L410,121.6 L440,164.8 L470,191.2 L500,200.8 L530,205.6 L560,205.6 L590,208 L620,208 L650,208 L680,208 Z" fill="rgba(45,49,66,0.12)" stroke="rgba(45,49,66,0.74)" stroke-width="1.2" stroke-linejoin="round"/>
65
+ <text data-ridge="auth-api" data-role="name" x="304" y="211.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">auth-api</text>
66
+ <text data-ridge="auth-api" data-role="range" x="696" y="211.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">40–320 ms</text>
67
+ <path data-ridge="search-api" data-baseline="264" data-bins="0,1,9,22,27,19,11,6,3,1,1,0,0" d="M320,264 L350,261.6 L380,242.4 L410,211.2 L440,199.2 L470,218.4 L500,237.6 L530,249.6 L560,256.8 L590,261.6 L620,261.6 L650,264 L680,264 Z" fill="rgba(45,49,66,0.12)" stroke="rgba(45,49,66,0.68)" stroke-width="1.2" stroke-linejoin="round"/>
68
+ <text data-ridge="search-api" data-role="name" x="304" y="267.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">search-api</text>
69
+ <text data-ridge="search-api" data-role="range" x="696" y="267.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">40–400 ms</text>
70
+
71
+ <!-- checkout-api FOCAL - and it is the ridge whose SHAPE is the story,
72
+ not the slowest service. Drawn last so its second peak reads over the
73
+ ridge below it rather than under. -->
74
+ <path data-ridge="checkout-api" data-baseline="320" data-bins="0,1,6,17,21,14,8,6,7,9,7,4,0" d="M320,320 L350,317.6 L380,305.6 L410,279.2 L440,269.6 L470,286.4 L500,300.8 L530,305.6 L560,303.2 L590,298.4 L620,303.2 L650,310.4 L680,320 Z" fill="rgba(191,69,32,0.16)" stroke="#bf4520" stroke-width="2.4" stroke-linejoin="round"/>
75
+ <text data-ridge="checkout-api" data-role="name" x="304" y="323.5" fill="#2d3142" font-size="11" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">checkout-api</text>
76
+ <text data-ridge="checkout-api" data-role="range" x="696" y="323.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">40–440 ms</text>
77
+ <path data-ridge="report-export" data-baseline="376" data-bins="0,0,1,3,7,12,17,19,16,12,9,4,0" d="M320,376 L350,376 L380,373.6 L410,368.8 L440,359.2 L470,347.2 L500,335.2 L530,330.4 L560,337.6 L590,347.2 L620,354.4 L650,366.4 L680,376 Z" fill="rgba(45,49,66,0.12)" stroke="rgba(45,49,66,0.62)" stroke-width="1.2" stroke-linejoin="round"/>
78
+ <text data-ridge="report-export" data-role="name" x="304" y="379.5" fill="#2d3142" font-size="11" font-weight="500" font-family="'Geist', sans-serif" text-anchor="end">report-export</text>
79
+ <text data-ridge="report-export" data-role="range" x="696" y="379.5" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace">80–440 ms</text>
80
+
81
+ <!-- Bin ticks on the shared latency scale. data-bin binds the printed number,
82
+ so a caption cannot be edited without its binding. -->
83
+ <text data-tick="0" data-bin="0" x="320" y="400" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">0</text>
84
+ <text data-tick="1" data-bin="120" x="410" y="400" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">120</text>
85
+ <text data-tick="2" data-bin="240" x="500" y="400" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">240</text>
86
+ <text data-tick="3" data-bin="360" x="590" y="400" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">360</text>
87
+ <text data-tick="4" data-bin="480" x="680" y="400" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">480</text>
88
+ <text x="500" y="424" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" letter-spacing="0.18em" text-anchor="middle">REQUEST LATENCY (MS), BIN LOWER EDGE</text>
89
+
90
+ <!-- Legend -->
91
+ <line x1="40" y1="462" x2="960" y2="462" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
92
+ <text x="40" y="478" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
93
+ <text x="960" y="478" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.06em" text-anchor="end">SHARE OF EACH SERVICE'S OWN REQUESTS PER 40 MS BIN · 1% = 2.4PX ON EVERY RIDGE · UNSMOOTHED · ILLUSTRATIVE FIGURES</text>
94
+
95
+ <rect x="40" y="486" width="24" height="10" fill="rgba(191,69,32,0.16)"/>
96
+ <line x1="40" y1="486" x2="64" y2="486" stroke="#bf4520" stroke-width="2.4"/>
97
+ <text x="72" y="496" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">checkout-api · focal, second peak past 300 ms</text>
98
+ <rect x="360" y="486" width="24" height="10" fill="rgba(45,49,66,0.12)"/>
99
+ <line x1="360" y1="486" x2="384" y2="486" stroke="rgba(45,49,66,0.80)" stroke-width="1.2"/>
100
+ <text x="392" y="496" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Other services · strongest tone is the fastest median</text>
101
+ </svg>
102
+ </div>
103
+ </body>
104
+ </html>
@@ -0,0 +1,150 @@
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>CI compute budget · Sankey</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
+
20
+ body {
21
+ font-family: var(--font-sans);
22
+ background: var(--color-paper);
23
+ color: var(--color-ink);
24
+ min-height: 100vh;
25
+ display: flex;
26
+ align-items: center;
27
+ justify-content: center;
28
+ padding: 3rem 2rem;
29
+ }
30
+
31
+ .frame { max-width: 1200px; width: 100%; }
32
+
33
+ .eyebrow {
34
+ font-family: var(--font-mono);
35
+ font-size: 0.66rem;
36
+ font-weight: 500;
37
+ letter-spacing: 0.18em;
38
+ text-transform: uppercase;
39
+ color: var(--color-muted);
40
+ margin-bottom: 0.5rem;
41
+ }
42
+
43
+ h1 {
44
+ font-family: var(--font-serif);
45
+ font-size: clamp(1.5rem, 2.4vw + 0.75rem, 2rem);
46
+ font-weight: 400;
47
+ letter-spacing: -0.02em;
48
+ line-height: 1.15;
49
+ color: var(--color-ink);
50
+ margin-bottom: 1.5rem;
51
+ }
52
+
53
+ svg { width: 100%; min-width: 900px; display: block; }
54
+ </style>
55
+ </head>
56
+ <body>
57
+ <div class="frame">
58
+ <p class="eyebrow">Sankey · Diagram Design</p>
59
+ <h1>CI compute budget · a month of pipeline minutes</h1>
60
+
61
+ <svg viewBox="0 0 1000 560" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="sankey-title sankey-desc">
62
+ <title id="sankey-title">CI compute budget · a month of pipeline minutes</title>
63
+ <desc id="sankey-desc">Sankey diagram showing 12,000 monthly CI minutes splitting into unit test, E2E, build, and lint stages, then merging into passed, failed, and flaked outcomes, with the flaky-rerun path highlighted as the one accent flow.</desc>
64
+
65
+ <rect width="100%" height="100%" fill="#f5f5f5"/>
66
+
67
+ <!-- Column headers -->
68
+ <text x="124" y="76" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">BUDGET</text>
69
+ <text x="504" y="76" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">TEST STAGE</text>
70
+ <text x="884" y="76" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.14em">OUTCOME</text>
71
+
72
+ <!-- Ribbons: col1 -> col2. Both control points sit on the midpoint x, so every band
73
+ meets its node bar horizontally at each end rather than arriving at a slant. -->
74
+ <path d="M132,120 C316,120 316,120 500,120 L500,224 C316,224 316,224 132,224 Z" fill="rgba(79,93,117,0.18)"/>
75
+ <path d="M132,224 C316,224 316,256 500,256 L500,336 C316,336 316,304 132,304 Z" fill="rgba(79,93,117,0.18)"/>
76
+ <path d="M132,304 C316,304 316,368 500,368 L500,408 C316,408 316,344 132,344 Z" fill="rgba(79,93,117,0.18)"/>
77
+ <path d="M132,344 C316,344 316,440 500,440 L500,456 C316,456 316,360 132,360 Z" fill="rgba(79,93,117,0.18)"/>
78
+
79
+ <!-- Ribbons: col2 -> col3, ordinary. Each source stacks its outgoing bands in target
80
+ order and each target stacks its incoming bands in source order, which is what
81
+ keeps every bar exactly saturated. Four sources feeding three outcomes cannot be
82
+ drawn crossing-free; what remains is the minimum. -->
83
+ <path d="M512,136 C696,136 696,148 880,148 L880,236 C696,236 696,224 512,224 Z" fill="rgba(79,93,117,0.18)"/>
84
+ <path d="M512,260 C696,260 696,236 880,236 L880,312 C696,312 696,336 512,336 Z" fill="rgba(79,93,117,0.18)"/>
85
+ <path d="M512,368 C696,368 696,312 880,312 L880,328 C696,328 696,384 512,384 Z" fill="rgba(79,93,117,0.18)"/>
86
+ <path d="M512,384 C696,384 696,344 880,344 L880,368 C696,368 696,408 512,408 Z" fill="rgba(79,93,117,0.18)"/>
87
+ <path d="M512,440 C696,440 696,328 880,328 L880,336 C696,336 696,448 512,448 Z" fill="rgba(79,93,117,0.18)"/>
88
+ <path d="M512,448 C696,448 696,368 880,368 L880,376 C696,376 696,456 512,456 Z" fill="rgba(79,93,117,0.18)"/>
89
+
90
+ <!-- Ribbons: col2 -> col3, flaky-rerun path (the one accent flow) -->
91
+ <path d="M512,120 C696,120 696,120 880,120 L880,136 C696,136 696,136 512,136 Z" fill="rgba(191,69,32,0.28)"/>
92
+ <path d="M512,256 C696,256 696,136 880,136 L880,140 C696,140 696,260 512,260 Z" fill="rgba(191,69,32,0.28)"/>
93
+
94
+ <!-- Nodes -->
95
+ <rect x="120" y="120" width="12" height="240" fill="#2d3142"/>
96
+ <rect x="500" y="120" width="12" height="104" fill="#2d3142"/>
97
+ <rect x="500" y="256" width="12" height="80" fill="#2d3142"/>
98
+ <rect x="500" y="368" width="12" height="40" fill="#2d3142"/>
99
+ <rect x="500" y="440" width="12" height="16" fill="#2d3142"/>
100
+ <rect x="880" y="120" width="12" height="20" fill="#2d3142"/>
101
+ <rect x="880" y="148" width="12" height="188" fill="#2d3142"/>
102
+ <rect x="880" y="344" width="12" height="32" fill="#2d3142"/>
103
+
104
+ <!-- Labels: column 1, outside, anchored end -->
105
+ <text x="104" y="236" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="end">CI minutes</text>
106
+ <text x="104" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="end">12,000 min</text>
107
+
108
+ <!-- Labels: column 2, centred in the gutter above the bar, where the bands separate. -->
109
+
110
+ <text x="504" y="96" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Unit tests</text>
111
+ <text x="504" y="112" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">5,200 min</text>
112
+
113
+ <text x="504" y="236" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">E2E</text>
114
+ <text x="504" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">4,000 min</text>
115
+
116
+ <text x="504" y="348" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Build</text>
117
+ <text x="504" y="364" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">2,000 min</text>
118
+
119
+ <text x="504" y="420" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="middle">Lint</text>
120
+ <text x="504" y="436" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="middle">800 min</text>
121
+
122
+ <!-- Labels: column 3, outside, anchored start -->
123
+
124
+ <text x="908" y="124" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Flaked</text>
125
+ <text x="908" y="136" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="start">1,000 min</text>
126
+
127
+ <text x="908" y="236" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Passed</text>
128
+ <text x="908" y="252" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="start">9,400 min</text>
129
+
130
+ <text x="908" y="356" fill="#2d3142" font-size="12" font-weight="600" font-family="'Geist', sans-serif" text-anchor="start">Failed</text>
131
+ <text x="908" y="372" fill="#4f5d75" font-size="9" font-family="'Geist Mono', monospace" text-anchor="start">1,600 min</text>
132
+
133
+ <!-- Legend -->
134
+ <line x1="40" y1="492" x2="960" y2="492" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
135
+ <text x="40" y="508" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
136
+
137
+ <rect x="40" y="520" width="16" height="8" fill="rgba(79,93,117,0.18)" stroke="#4f5d75" stroke-width="1"/>
138
+ <text x="64" y="528" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Flow · stage routing</text>
139
+
140
+ <rect x="220" y="520" width="16" height="8" fill="rgba(191,69,32,0.28)" stroke="#bf4520" stroke-width="1"/>
141
+ <text x="244" y="528" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Flaked path · reruns</text>
142
+
143
+ <rect x="420" y="520" width="16" height="8" fill="#2d3142"/>
144
+ <text x="444" y="528" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Node · stage total</text>
145
+
146
+ <text x="600" y="528" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif" font-style="italic">Two coral ribbons — flaky reruns burn ~8% of the monthly CI budget.</text>
147
+ </svg>
148
+ </div>
149
+ </body>
150
+ </html>
@@ -0,0 +1,141 @@
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>Deploy frequency vs lead time · Scatter</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 { --color-paper:#f5f5f5; --color-ink:#2d3142; --color-muted:#4f5d75; --color-accent:#bf4520; --font-sans:'Geist',system-ui,sans-serif; --font-serif:'Instrument Serif',serif; --font-mono:'Geist Mono',ui-monospace,monospace; }
11
+ 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; }
12
+ .frame { max-width: 1200px; width: 100%; }
13
+ .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; }
14
+ 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; }
15
+ svg { width: 100%; min-width: 760px; display: block; }
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <div class="frame">
20
+ <p class="eyebrow">Scatter · Diagram Design</p>
21
+ <h1>Deploy frequency vs. lead time · 12 teams</h1>
22
+
23
+ <!-- X: 0-20 deploys/week → 880px. x = 80 + f/20*880 = 80+44*f -->
24
+ <!-- Y: 0-24 days lead time → 380px. y = 420 - lt/24*380. High lt = high y (worse) -->
25
+ <svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="scatter-title scatter-desc">
26
+ <title id="scatter-title">Deploy frequency vs. lead time · 12 teams</title>
27
+ <desc id="scatter-desc">Scatter plot showing twelve engineering teams by deploy frequency and lead time, with Platform in the best-performing quadrant.</desc>
28
+ <defs>
29
+ <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
30
+ <circle cx="1" cy="1" r="0.9" fill="rgba(45,49,66,0.10)"/>
31
+ </pattern>
32
+ </defs>
33
+
34
+ <rect width="100%" height="100%" fill="#f5f5f5"/>
35
+ <rect width="100%" height="100%" fill="url(#dots)" opacity="0.55"/>
36
+
37
+ <!-- Axis labels -->
38
+ <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">LEAD TIME (DAYS)</text>
39
+ <text x="520" y="492" fill="#4f5d75" font-size="7" font-family="'Geist Mono', monospace" letter-spacing="0.14em" text-anchor="middle">DEPLOYS PER WEEK</text>
40
+
41
+ <!-- Gridlines -->
42
+ <!-- Horizontal (constant lead time) -->
43
+ <line x1="80" y1="325" x2="960" y2="325" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
44
+ <line x1="80" y1="230" x2="960" y2="230" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
45
+ <line x1="80" y1="135" x2="960" y2="135" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
46
+ <line x1="80" y1="40" x2="960" y2="40" stroke="rgba(45,49,66,0.06)" stroke-width="0.8"/>
47
+ <!-- Vertical (constant deploy freq) -->
48
+ <line x1="256" y1="40" x2="256" y2="420" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
49
+ <line x1="432" y1="40" x2="432" y2="420" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
50
+ <line x1="608" y1="40" x2="608" y2="420" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
51
+ <line x1="784" y1="40" x2="784" y2="420" stroke="rgba(45,49,66,0.08)" stroke-width="0.8"/>
52
+
53
+ <!-- Axes -->
54
+ <line x1="80" y1="40" x2="80" y2="420" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
55
+ <line x1="80" y1="420" x2="960" y2="420" stroke="rgba(45,49,66,0.25)" stroke-width="1"/>
56
+
57
+ <!-- Y-axis labels (lead time: 0 at bottom, 24 at top) -->
58
+ <text x="72" y="324" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">6</text>
59
+ <text x="72" y="234" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">12</text>
60
+ <text x="72" y="139" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">18</text>
61
+ <text x="72" y="44" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">24</text>
62
+ <text x="72" y="424" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="end">0</text>
63
+
64
+ <!-- X-axis labels (deploy frequency) -->
65
+ <text x="80" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">0</text>
66
+ <text x="256" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">4</text>
67
+ <text x="432" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">8</text>
68
+ <text x="608" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">12</text>
69
+ <text x="784" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">16</text>
70
+ <text x="960" y="440" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle">20</text>
71
+
72
+ <!-- Trend line (dashed, approximate) -->
73
+ <line x1="168" y1="103" x2="900" y2="388" stroke="rgba(45,49,66,0.18)" stroke-width="1" stroke-dasharray="4,3"/>
74
+
75
+ <!-- ─── DATA POINTS (non-focal first) ─── -->
76
+ <!-- (freq, lt) → (x=80+44*f, y=420-380*lt/24) -->
77
+ <!-- (2,20)→(168,103), (4,18)→(256,135), (4,16)→(256,167), (6,14)→(344,198) -->
78
+ <!-- (8,12)→(432,230), (8,10)→(432,262), (10,8)→(520,293), (12,6)→(608,325) -->
79
+ <!-- (12,10)→(608,262), (16,4)→(784,357), (18,3)→(872,372) FOCAL, (20,2)→(960,388) -->
80
+
81
+ <circle cx="168" cy="103" r="5" fill="#f5f5f5"/>
82
+ <circle cx="168" cy="103" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
83
+
84
+ <circle cx="256" cy="135" r="5" fill="#f5f5f5"/>
85
+ <circle cx="256" cy="135" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
86
+
87
+ <circle cx="256" cy="167" r="5" fill="#f5f5f5"/>
88
+ <circle cx="256" cy="167" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
89
+
90
+ <circle cx="344" cy="198" r="5" fill="#f5f5f5"/>
91
+ <circle cx="344" cy="198" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
92
+
93
+ <circle cx="432" cy="230" r="5" fill="#f5f5f5"/>
94
+ <circle cx="432" cy="230" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
95
+
96
+ <circle cx="432" cy="262" r="5" fill="#f5f5f5"/>
97
+ <circle cx="432" cy="262" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
98
+
99
+ <circle cx="520" cy="293" r="5" fill="#f5f5f5"/>
100
+ <circle cx="520" cy="293" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
101
+
102
+ <circle cx="608" cy="325" r="5" fill="#f5f5f5"/>
103
+ <circle cx="608" cy="325" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
104
+
105
+ <circle cx="608" cy="262" r="5" fill="#f5f5f5"/>
106
+ <circle cx="608" cy="262" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
107
+
108
+ <circle cx="784" cy="357" r="5" fill="#f5f5f5"/>
109
+ <circle cx="784" cy="357" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
110
+
111
+ <circle cx="960" cy="388" r="5" fill="#f5f5f5"/>
112
+ <circle cx="960" cy="388" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
113
+
114
+ <!-- FOCAL: Platform team (18,3) → (872,372) -->
115
+ <circle cx="872" cy="372" r="6" fill="#f5f5f5"/>
116
+ <circle cx="872" cy="372" r="6" fill="rgba(191,69,32,0.15)" stroke="#bf4520" stroke-width="1.2"/>
117
+
118
+ <!-- Focal label -->
119
+ <rect x="798" y="348" width="64" height="12" rx="2" fill="#f5f5f5"/>
120
+ <text x="830" y="357" fill="#bf4520" font-size="8" font-family="'Geist Mono', monospace" text-anchor="middle" letter-spacing="0.06em">PLATFORM</text>
121
+
122
+ <!-- Quadrant guides (optional) -->
123
+ <text x="88" y="56" fill="rgba(45,49,66,0.25)" font-size="8" font-family="'Geist Mono', monospace">HIGH LEAD TIME</text>
124
+ <text x="88" y="412" fill="rgba(45,49,66,0.25)" font-size="8" font-family="'Geist Mono', monospace">LOW LEAD TIME</text>
125
+
126
+ <!-- Legend -->
127
+ <line x1="40" y1="462" x2="960" y2="462" stroke="rgba(45,49,66,0.10)" stroke-width="0.8"/>
128
+ <text x="40" y="478" fill="#4f5d75" font-size="8" font-family="'Geist Mono', monospace" letter-spacing="0.18em">LEGEND</text>
129
+
130
+ <circle cx="52" cy="490" r="6" fill="rgba(191,69,32,0.15)" stroke="#bf4520" stroke-width="1.2"/>
131
+ <text x="68" y="494" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Platform team · best performer</text>
132
+
133
+ <circle cx="256" cy="490" r="5" fill="rgba(79,93,117,0.20)" stroke="#4f5d75" stroke-width="1"/>
134
+ <text x="272" y="494" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Engineering team</text>
135
+
136
+ <line x1="416" y1="490" x2="440" y2="490" stroke="rgba(45,49,66,0.18)" stroke-width="1" stroke-dasharray="4,3"/>
137
+ <text x="448" y="494" fill="#4f5d75" font-size="8.5" font-family="'Geist', sans-serif">Trend</text>
138
+ </svg>
139
+ </div>
140
+ </body>
141
+ </html>