@taloswork/ose-shared 0.1.8 → 0.1.10

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 (208) hide show
  1. package/mcp/gen/mcp.json +2 -2
  2. package/package.json +3 -3
  3. package/skills/cozy-static-svg/SKILL.md +76 -0
  4. package/skills/cozy-static-svg/references/approved-preview.png +0 -0
  5. package/skills/cozy-static-svg/references/cross-platform.md +73 -0
  6. package/skills/cozy-static-svg/references/moon_keeps_watch.svg +229 -0
  7. package/skills/cozy-static-svg/references/style-anchor.md +271 -0
  8. package/skills/cozy-static-svg/scripts/artkit.py +321 -0
  9. package/skills/cozy-static-svg/scripts/to_png.py +333 -0
  10. package/skills/diagram-design/SKILL.md +568 -0
  11. package/skills/diagram-design/assets/example-architecture-dark.html +182 -0
  12. package/skills/diagram-design/assets/example-architecture-full.html +194 -0
  13. package/skills/diagram-design/assets/example-architecture.html +183 -0
  14. package/skills/diagram-design/assets/example-bar-dark.html +129 -0
  15. package/skills/diagram-design/assets/example-bar-full.html +105 -0
  16. package/skills/diagram-design/assets/example-bar.html +129 -0
  17. package/skills/diagram-design/assets/example-data-flow-dark.html +143 -0
  18. package/skills/diagram-design/assets/example-data-flow-full.html +185 -0
  19. package/skills/diagram-design/assets/example-data-flow.html +143 -0
  20. package/skills/diagram-design/assets/example-datalake-dark.html +243 -0
  21. package/skills/diagram-design/assets/example-datalake-full.html +248 -0
  22. package/skills/diagram-design/assets/example-datalake.html +269 -0
  23. package/skills/diagram-design/assets/example-dp-integration-dark.html +80 -0
  24. package/skills/diagram-design/assets/example-dp-integration-full.html +90 -0
  25. package/skills/diagram-design/assets/example-dp-integration.html +80 -0
  26. package/skills/diagram-design/assets/example-dp-security-matrix-dark.html +31 -0
  27. package/skills/diagram-design/assets/example-dp-security-matrix-full.html +32 -0
  28. package/skills/diagram-design/assets/example-dp-security-matrix.html +88 -0
  29. package/skills/diagram-design/assets/example-er-dark.html +202 -0
  30. package/skills/diagram-design/assets/example-er-full.html +205 -0
  31. package/skills/diagram-design/assets/example-er.html +202 -0
  32. package/skills/diagram-design/assets/example-flowchart-dark.html +156 -0
  33. package/skills/diagram-design/assets/example-flowchart-full.html +159 -0
  34. package/skills/diagram-design/assets/example-flowchart.html +156 -0
  35. package/skills/diagram-design/assets/example-gantt-dark.html +137 -0
  36. package/skills/diagram-design/assets/example-gantt-full.html +127 -0
  37. package/skills/diagram-design/assets/example-gantt.html +137 -0
  38. package/skills/diagram-design/assets/example-high-level-dark.html +251 -0
  39. package/skills/diagram-design/assets/example-high-level-full.html +247 -0
  40. package/skills/diagram-design/assets/example-high-level-vertical-dark.html +274 -0
  41. package/skills/diagram-design/assets/example-high-level-vertical-full.html +252 -0
  42. package/skills/diagram-design/assets/example-high-level-vertical.html +325 -0
  43. package/skills/diagram-design/assets/example-high-level.html +301 -0
  44. package/skills/diagram-design/assets/example-import-drawio.html +185 -0
  45. package/skills/diagram-design/assets/example-import-mermaid.html +70 -0
  46. package/skills/diagram-design/assets/example-it-state-dark.html +90 -0
  47. package/skills/diagram-design/assets/example-it-state-full.html +69 -0
  48. package/skills/diagram-design/assets/example-it-state.html +128 -0
  49. package/skills/diagram-design/assets/example-layers-dark.html +123 -0
  50. package/skills/diagram-design/assets/example-layers-full.html +126 -0
  51. package/skills/diagram-design/assets/example-layers.html +123 -0
  52. package/skills/diagram-design/assets/example-line-dark.html +111 -0
  53. package/skills/diagram-design/assets/example-line-full.html +105 -0
  54. package/skills/diagram-design/assets/example-line.html +111 -0
  55. package/skills/diagram-design/assets/example-loop-dark.html +100 -0
  56. package/skills/diagram-design/assets/example-loop-full.html +137 -0
  57. package/skills/diagram-design/assets/example-loop-terminal.html +347 -0
  58. package/skills/diagram-design/assets/example-loop.html +100 -0
  59. package/skills/diagram-design/assets/example-medallion-dark.html +159 -0
  60. package/skills/diagram-design/assets/example-medallion-full.html +201 -0
  61. package/skills/diagram-design/assets/example-medallion.html +159 -0
  62. package/skills/diagram-design/assets/example-nested-dark.html +132 -0
  63. package/skills/diagram-design/assets/example-nested-full.html +135 -0
  64. package/skills/diagram-design/assets/example-nested.html +136 -0
  65. package/skills/diagram-design/assets/example-org-chart-dark.html +45 -0
  66. package/skills/diagram-design/assets/example-org-chart-full.html +45 -0
  67. package/skills/diagram-design/assets/example-org-chart.html +45 -0
  68. package/skills/diagram-design/assets/example-paved-road-animated.html +546 -0
  69. package/skills/diagram-design/assets/example-policy-trace-animated.html +490 -0
  70. package/skills/diagram-design/assets/example-process-dark.html +64 -0
  71. package/skills/diagram-design/assets/example-process-full.html +74 -0
  72. package/skills/diagram-design/assets/example-process.html +64 -0
  73. package/skills/diagram-design/assets/example-pyramid-dark.html +119 -0
  74. package/skills/diagram-design/assets/example-pyramid-full.html +122 -0
  75. package/skills/diagram-design/assets/example-pyramid.html +119 -0
  76. package/skills/diagram-design/assets/example-quadrant-consultant.html +166 -0
  77. package/skills/diagram-design/assets/example-quadrant-dark.html +135 -0
  78. package/skills/diagram-design/assets/example-quadrant-full.html +138 -0
  79. package/skills/diagram-design/assets/example-quadrant.html +135 -0
  80. package/skills/diagram-design/assets/example-queue-animated.html +577 -0
  81. package/skills/diagram-design/assets/example-radar-dark.html +139 -0
  82. package/skills/diagram-design/assets/example-radar-full.html +135 -0
  83. package/skills/diagram-design/assets/example-radar.html +139 -0
  84. package/skills/diagram-design/assets/example-scatter-dark.html +141 -0
  85. package/skills/diagram-design/assets/example-scatter-full.html +116 -0
  86. package/skills/diagram-design/assets/example-scatter.html +141 -0
  87. package/skills/diagram-design/assets/example-sequence-dark.html +222 -0
  88. package/skills/diagram-design/assets/example-sequence-full.html +388 -0
  89. package/skills/diagram-design/assets/example-sequence-oauth-dark.html +188 -0
  90. package/skills/diagram-design/assets/example-sequence-oauth-full.html +350 -0
  91. package/skills/diagram-design/assets/example-sequence-oauth.html +227 -0
  92. package/skills/diagram-design/assets/example-sequence.html +222 -0
  93. package/skills/diagram-design/assets/example-state-dark.html +147 -0
  94. package/skills/diagram-design/assets/example-state-full.html +150 -0
  95. package/skills/diagram-design/assets/example-state.html +147 -0
  96. package/skills/diagram-design/assets/example-swimlane-dark.html +172 -0
  97. package/skills/diagram-design/assets/example-swimlane-full.html +175 -0
  98. package/skills/diagram-design/assets/example-swimlane.html +172 -0
  99. package/skills/diagram-design/assets/example-timeline-dark.html +135 -0
  100. package/skills/diagram-design/assets/example-timeline-full.html +138 -0
  101. package/skills/diagram-design/assets/example-timeline.html +135 -0
  102. package/skills/diagram-design/assets/example-tree-dark.html +173 -0
  103. package/skills/diagram-design/assets/example-tree-full.html +176 -0
  104. package/skills/diagram-design/assets/example-tree.html +173 -0
  105. package/skills/diagram-design/assets/example-venn-dark.html +132 -0
  106. package/skills/diagram-design/assets/example-venn-full.html +135 -0
  107. package/skills/diagram-design/assets/example-venn.html +110 -0
  108. package/skills/diagram-design/assets/icons.html +230 -0
  109. package/skills/diagram-design/assets/index.html +369 -0
  110. package/skills/diagram-design/assets/template-dark.html +85 -0
  111. package/skills/diagram-design/assets/template-full.html +413 -0
  112. package/skills/diagram-design/assets/template-motion.html +434 -0
  113. package/skills/diagram-design/assets/template-terminal.html +173 -0
  114. package/skills/diagram-design/assets/template.html +86 -0
  115. package/skills/diagram-design/references/animation.md +141 -0
  116. package/skills/diagram-design/references/export.md +136 -0
  117. package/skills/diagram-design/references/import-drawio.md +171 -0
  118. package/skills/diagram-design/references/import-mermaid.md +126 -0
  119. package/skills/diagram-design/references/onboarding.md +297 -0
  120. package/skills/diagram-design/references/output-spec.md +181 -0
  121. package/skills/diagram-design/references/primitive-annotation.md +36 -0
  122. package/skills/diagram-design/references/primitive-icons.md +827 -0
  123. package/skills/diagram-design/references/primitive-sketchy.md +43 -0
  124. package/skills/diagram-design/references/primitive-terminal.md +76 -0
  125. package/skills/diagram-design/references/semantic-patterns.md +122 -0
  126. package/skills/diagram-design/references/style-guide.md +139 -0
  127. package/skills/diagram-design/references/type-architecture.md +78 -0
  128. package/skills/diagram-design/references/type-bar.md +48 -0
  129. package/skills/diagram-design/references/type-data-flow.md +374 -0
  130. package/skills/diagram-design/references/type-dp-integration.md +410 -0
  131. package/skills/diagram-design/references/type-dp-security-matrix.md +379 -0
  132. package/skills/diagram-design/references/type-er.md +23 -0
  133. package/skills/diagram-design/references/type-flowchart.md +23 -0
  134. package/skills/diagram-design/references/type-gantt.md +45 -0
  135. package/skills/diagram-design/references/type-high-level.md +458 -0
  136. package/skills/diagram-design/references/type-it-state.md +470 -0
  137. package/skills/diagram-design/references/type-layers.md +26 -0
  138. package/skills/diagram-design/references/type-line.md +44 -0
  139. package/skills/diagram-design/references/type-loop.md +223 -0
  140. package/skills/diagram-design/references/type-medallion.md +356 -0
  141. package/skills/diagram-design/references/type-nested.md +22 -0
  142. package/skills/diagram-design/references/type-org-chart.md +44 -0
  143. package/skills/diagram-design/references/type-process.md +495 -0
  144. package/skills/diagram-design/references/type-pyramid.md +33 -0
  145. package/skills/diagram-design/references/type-quadrant.md +81 -0
  146. package/skills/diagram-design/references/type-radar.md +80 -0
  147. package/skills/diagram-design/references/type-scatter.md +39 -0
  148. package/skills/diagram-design/references/type-sequence.md +130 -0
  149. package/skills/diagram-design/references/type-state.md +21 -0
  150. package/skills/diagram-design/references/type-swimlane.md +20 -0
  151. package/skills/diagram-design/references/type-timeline.md +20 -0
  152. package/skills/diagram-design/references/type-tree.md +24 -0
  153. package/skills/diagram-design/references/type-venn.md +26 -0
  154. package/skills/diagram-design/scripts/drawio_extract.py +856 -0
  155. package/skills/diagram-design/scripts/mermaid_extract.py +1285 -0
  156. package/skills/diagram-design/scripts/self_check.py +389 -0
  157. package/skills/document/SKILL.md +63 -75
  158. package/skills/document/bin/deck-build.cjs +51 -1
  159. package/skills/document/bin/deck-qa.cjs +18745 -279
  160. package/skills/document/bin/doc-convert.cjs +9280 -76489
  161. package/skills/document/bin/doc-fill.cjs +0 -0
  162. package/skills/document/bin/doc-gen.cjs +3043 -46825
  163. package/skills/document/bin/doc-run.cjs +65095 -1967
  164. package/skills/document/bin/doc-scan.cjs +0 -0
  165. package/skills/document/bin/doc-text.cjs +0 -0
  166. package/skills/document/bin/doc-validate.cjs +18067 -226
  167. package/skills/document/bin/doc-xml.cjs +1 -1
  168. package/skills/document/bin/docx-annotate.cjs +0 -0
  169. package/skills/document/bin/html2pptx.cjs +32498 -145280
  170. package/skills/document/bin/ocr-worker.cjs +0 -0
  171. package/skills/document/bin/ocr.cjs +0 -0
  172. package/skills/document/bin/pdf-form.cjs +0 -0
  173. package/skills/document/bin/pdf-images.cjs +0 -0
  174. package/skills/document/bin/pdf-ops.cjs +0 -0
  175. package/skills/document/bin/pdf-render.cjs +11 -9
  176. package/skills/document/bin/pdf-tables.cjs +0 -0
  177. package/skills/document/bin/pptx-clone.cjs +21 -25
  178. package/skills/document/bin/pptx-embed-fonts.cjs +8 -6
  179. package/skills/document/bin/pptx-set-image.cjs +0 -0
  180. package/skills/document/bin/pptx-slide.cjs +22 -32
  181. package/skills/document/bin/pptx-theme.cjs +1 -20
  182. package/skills/document/bin/pptx-tokenize.cjs +1 -1
  183. package/skills/document/bin/xlsx-query.cjs +0 -0
  184. package/skills/document/bin/xlsx-recalc.cjs +0 -0
  185. package/skills/document/bin-reference.md +35 -0
  186. package/skills/document/content-pipeline.md +19 -18
  187. package/skills/document/deck-design.md +110 -211
  188. package/skills/document/layouts/README.md +4 -33
  189. package/skills/document/motion/README.md +4 -2
  190. package/skills/document/office.md +5 -1
  191. package/skills/document/rewrite.md +43 -99
  192. package/skills/document/styles/README.md +0 -7
  193. package/skills/document/theme-system.md +1 -0
  194. package/skills/document/themes/README.md +5 -5
  195. package/skills/document/themes/anthropic-clay.json +1 -7
  196. package/skills/document/themes/apple-keynote.json +1 -7
  197. package/skills/document/themes/black-gold.json +1 -2
  198. package/skills/document/themes/cinereel.json +1 -2
  199. package/skills/document/themes/cool-tech.json +1 -2
  200. package/skills/document/themes/hand-drawn.json +1 -2
  201. package/skills/document/themes/ivory-gold.json +1 -2
  202. package/skills/document/themes/magazine-ink.json +1 -2
  203. package/skills/document/themes/mckinsey-consulting.json +1 -7
  204. package/skills/document/themes/mono.json +1 -2
  205. package/skills/document/themes/swiss-grid.json +1 -2
  206. package/skills/document/themes/warm-editorial.json +1 -2
  207. package/skills/image-layout/SKILL.md +1 -1
  208. package/skills/image-layout/bin/html2img.cjs +0 -0
@@ -0,0 +1,434 @@
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>Motion diagram template</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; }
10
+ :root {
11
+ --color-paper: #f5f5f5;
12
+ --color-ink: #2d3142;
13
+ --color-muted: #4f5d75;
14
+ --color-soft: #7a8399;
15
+ --color-accent: #eb6c36;
16
+ --color-rule: rgba(45,49,66,0.12);
17
+ --font-sans: 'Geist', system-ui, sans-serif;
18
+ --font-serif: 'Instrument Serif', serif;
19
+ --font-mono: 'Geist Mono', ui-monospace, monospace;
20
+ --motion-fast: 160ms;
21
+ --motion-step: 480ms;
22
+ --motion-hold: 720ms;
23
+ --motion-total: 3600ms;
24
+ --motion-ease: cubic-bezier(.2,.8,.2,1);
25
+ }
26
+ body {
27
+ margin: 0;
28
+ min-height: 100vh;
29
+ display: grid;
30
+ place-items: center;
31
+ padding: 48px 32px;
32
+ color: var(--color-ink);
33
+ background: var(--color-paper);
34
+ font-family: var(--font-sans);
35
+ }
36
+ [data-motion-root] { width: min(100%, 1000px); }
37
+ .eyebrow {
38
+ margin: 0 0 8px;
39
+ color: var(--color-muted);
40
+ font: 500 12px/1.4 var(--font-mono);
41
+ letter-spacing: .18em;
42
+ text-transform: uppercase;
43
+ }
44
+ h1 { margin: 0 0 24px; font: 400 32px/1.15 var(--font-serif); }
45
+ svg { display: block; width: 100%; min-width: 720px; }
46
+
47
+ /* Static source is complete. Only an initialized enhancement hides items. */
48
+ .motion-ready [data-motion-item] {
49
+ opacity: .12;
50
+ transform: translateY(8px);
51
+ transform-box: fill-box;
52
+ transform-origin: center;
53
+ transition: opacity var(--motion-step) var(--motion-ease),
54
+ transform var(--motion-step) var(--motion-ease);
55
+ }
56
+ .motion-ready [data-motion-item].is-visible,
57
+ .motion-ready[data-frame="end"] [data-motion-item],
58
+ .motion-ready[data-frame="static"] [data-motion-item] {
59
+ opacity: 1;
60
+ transform: none;
61
+ }
62
+ .draw-path {
63
+ fill: none;
64
+ stroke: var(--color-accent);
65
+ stroke-width: 3;
66
+ stroke-dasharray: 1;
67
+ stroke-dashoffset: 1;
68
+ pointer-events: none;
69
+ }
70
+ .motion-ready .draw-path.is-visible {
71
+ animation: draw-path var(--motion-step) linear forwards;
72
+ }
73
+ .flow-token { opacity: 0; pointer-events: none; }
74
+ .motion-ready.is-playing .flow-token.is-visible {
75
+ opacity: 1;
76
+ animation: token-flow 3.2s linear 1 forwards;
77
+ }
78
+ .motion-ready[data-motion-mode="loop"].is-playing .flow-token.is-visible {
79
+ animation-iteration-count: infinite;
80
+ }
81
+ @keyframes draw-path { to { stroke-dashoffset: 0; } }
82
+ @keyframes token-flow {
83
+ 0% { transform: translateX(0); }
84
+ 100% { transform: translateX(240px); }
85
+ }
86
+
87
+ [data-motion-controls] {
88
+ display: none;
89
+ align-items: center;
90
+ flex-wrap: wrap;
91
+ gap: 8px;
92
+ margin-top: 16px;
93
+ padding-top: 16px;
94
+ border-top: 1px solid var(--color-rule);
95
+ }
96
+ .motion-ready [data-motion-controls] { display: flex; }
97
+ [data-motion-controls][hidden] { display: none !important; }
98
+ [data-motion-controls] button {
99
+ min-width: 44px;
100
+ min-height: 44px;
101
+ padding: 8px 12px;
102
+ border: 1px solid var(--color-muted);
103
+ border-radius: 4px;
104
+ color: var(--color-ink);
105
+ background: var(--color-paper);
106
+ font: 600 12px/1 var(--font-sans);
107
+ cursor: pointer;
108
+ }
109
+ [data-motion-controls] button:hover { border-color: var(--color-accent); }
110
+ [data-motion-controls] button:focus-visible {
111
+ outline: 3px solid var(--color-accent);
112
+ outline-offset: 2px;
113
+ }
114
+ [data-motion-controls] button:disabled { cursor: not-allowed; opacity: .45; }
115
+ [data-motion-status-visible] {
116
+ margin-left: auto;
117
+ color: var(--color-muted);
118
+ font: 500 12px/1.4 var(--font-mono);
119
+ }
120
+ .sr-only {
121
+ position: absolute;
122
+ width: 1px;
123
+ height: 1px;
124
+ padding: 0;
125
+ margin: -1px;
126
+ overflow: hidden;
127
+ clip: rect(0,0,0,0);
128
+ white-space: nowrap;
129
+ border: 0;
130
+ }
131
+ noscript p {
132
+ margin: 12px 0 0;
133
+ color: var(--color-muted);
134
+ font: 500 12px/1.4 var(--font-mono);
135
+ }
136
+
137
+ html[data-motion="static"] [data-motion-controls],
138
+ html[data-motion="static"] [data-motion-decorative] { display: none !important; }
139
+ html[data-motion="static"] [data-motion-item] {
140
+ opacity: 1 !important;
141
+ transform: none !important;
142
+ animation: none !important;
143
+ transition: none !important;
144
+ }
145
+ html[data-motion="step"] [data-motion-controls],
146
+ html[data-motion="step"] [data-motion-decorative] { display: none !important; }
147
+ html[data-motion="step"] [data-motion-item] {
148
+ animation: none !important;
149
+ transition: none !important;
150
+ }
151
+ @media (prefers-reduced-motion: reduce) {
152
+ *, *::before, *::after {
153
+ animation-duration: .001ms !important;
154
+ animation-iteration-count: 1 !important;
155
+ scroll-behavior: auto !important;
156
+ transition-duration: .001ms !important;
157
+ }
158
+ [data-motion-item] { opacity: 1 !important; transform: none !important; }
159
+ [data-motion-decorative] { display: none !important; }
160
+ [data-motion-controls] { display: none !important; }
161
+ }
162
+ @media print {
163
+ [data-motion-controls], [data-motion-decorative] { display: none !important; }
164
+ [data-motion-item] {
165
+ opacity: 1 !important;
166
+ transform: none !important;
167
+ animation: none !important;
168
+ transition: none !important;
169
+ }
170
+ }
171
+ </style>
172
+ </head>
173
+ <body>
174
+ <!-- Replace template-motion in IDs and prose when copying this file. -->
175
+ <main data-motion-root data-motion-mode="step" data-step-count="5" data-step-current="5" data-frame="static" data-static-frame="complete">
176
+ <p class="eyebrow">Process · Optional motion</p>
177
+ <h1>Request evaluation</h1>
178
+
179
+ <svg viewBox="0 0 960 480" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="template-motion-title template-motion-desc">
180
+ <title id="template-motion-title">Request evaluation</title>
181
+ <desc id="template-motion-desc">A request is validated, evaluated against a policy, queued, and appended to an audit log.</desc>
182
+ <defs>
183
+ <marker id="template-motion-arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
184
+ <polygon points="0 0, 8 3, 0 6" fill="#4f5d75"/>
185
+ </marker>
186
+ </defs>
187
+ <rect width="960" height="480" fill="#f5f5f5"/>
188
+
189
+ <!-- Persistent connectors carry the static meaning. -->
190
+ <path d="M248 180 H356" fill="none" stroke="#4f5d75" marker-end="url(#template-motion-arrow)"/>
191
+ <path d="M556 180 H664" fill="none" stroke="#4f5d75" marker-end="url(#template-motion-arrow)"/>
192
+ <path d="M764 232 V328" fill="none" stroke="#4f5d75" marker-end="url(#template-motion-arrow)"/>
193
+
194
+ <g data-motion-item data-step="1" aria-label="Step 1: Request received">
195
+ <rect x="48" y="128" width="200" height="104" rx="8" fill="#f5f5f5" stroke="#2d3142"/>
196
+ <text x="148" y="172" text-anchor="middle" fill="#2d3142" font-family="Geist, sans-serif" font-size="16" font-weight="600">Request</text>
197
+ <text x="148" y="196" text-anchor="middle" fill="#4f5d75" font-family="Geist Mono, monospace" font-size="12">fields complete</text>
198
+ </g>
199
+ <g data-motion-item data-step="2" aria-label="Step 2: Policy passed">
200
+ <rect x="356" y="128" width="200" height="104" rx="8" fill="rgba(235,108,54,0.08)" stroke="#eb6c36"/>
201
+ <text x="456" y="168" text-anchor="middle" fill="#2d3142" font-family="Geist, sans-serif" font-size="16" font-weight="600">Policy</text>
202
+ <text x="456" y="196" text-anchor="middle" fill="#4f5d75" font-family="Geist Mono, monospace" font-size="12">✓ PASS · rule 2</text>
203
+ </g>
204
+ <g data-motion-item data-step="3" aria-label="Step 3: Three items queued">
205
+ <rect x="664" y="128" width="200" height="104" rx="8" fill="#f5f5f5" stroke="#2d3142"/>
206
+ <text x="764" y="164" text-anchor="middle" fill="#2d3142" font-family="Geist, sans-serif" font-size="16" font-weight="600">Queue</text>
207
+ <rect x="700" y="184" width="16" height="16" fill="#4f5d75"/><rect x="724" y="184" width="16" height="16" fill="#4f5d75"/><rect x="748" y="184" width="16" height="16" fill="#4f5d75"/>
208
+ <text x="796" y="196" fill="#4f5d75" font-family="Geist Mono, monospace" font-size="12">3 queued</text>
209
+ </g>
210
+ <g data-motion-item data-step="4" aria-label="Step 4: Audit entry appended">
211
+ <rect x="664" y="328" width="200" height="88" rx="8" fill="#f5f5f5" stroke="#2d3142"/>
212
+ <text x="764" y="364" text-anchor="middle" fill="#2d3142" font-family="Geist, sans-serif" font-size="16" font-weight="600">Audit log</text>
213
+ <text x="764" y="388" text-anchor="middle" fill="#4f5d75" font-family="Geist Mono, monospace" font-size="12">0042 · appended</text>
214
+ </g>
215
+ <g data-motion-item data-step="5" aria-label="Step 5: Evaluation complete">
216
+ <text x="48" y="376" fill="#2d3142" font-family="Geist, sans-serif" font-size="16" font-weight="600">Outcome: accepted and recorded</text>
217
+ </g>
218
+
219
+ <!-- Decorative duplicate path and token never carry unique meaning. -->
220
+ <path data-motion-item data-step="2" data-motion-decorative aria-hidden="true" focusable="false" pathLength="1" class="draw-path" d="M248 180 H356"/>
221
+ <circle data-motion-item data-step="3" data-motion-decorative aria-hidden="true" focusable="false" class="flow-token" cx="556" cy="180" r="6" fill="#eb6c36"/>
222
+ </svg>
223
+
224
+ <div data-motion-controls role="group" aria-label="Diagram playback controls">
225
+ <button type="button" data-motion-action="prev">Previous</button>
226
+ <button type="button" data-motion-action="play" aria-pressed="false">Play</button>
227
+ <button type="button" data-motion-action="pause" aria-pressed="true">Pause</button>
228
+ <button type="button" data-motion-action="next">Next</button>
229
+ <button type="button" data-motion-action="replay">Replay</button>
230
+ <span class="keyboard-help">←/→ step · Space play/pause · R replay · Home/End jump</span>
231
+ <span data-motion-status-visible aria-hidden="true">Step <span data-motion-step-label>5</span> of 5</span>
232
+ </div>
233
+ <p class="sr-only" data-motion-status role="status" aria-live="polite" aria-atomic="true"></p>
234
+ <noscript><p>Animation controls require JavaScript. The complete final diagram is shown above.</p></noscript>
235
+ </main>
236
+
237
+ <script data-diagram-controls>
238
+ (() => {
239
+ const params = new URLSearchParams(location.search);
240
+ const staticOverride = params.get('motion') === 'static' || document.documentElement.dataset.motion === 'static';
241
+ const requestedStep = params.get('step');
242
+ const reduce = matchMedia('(prefers-reduced-motion: reduce)');
243
+ document.fonts.ready.then(() => { document.documentElement.dataset.fontsReady = 'true'; });
244
+
245
+ document.querySelectorAll('[data-motion-root]').forEach((root) => {
246
+ const count = Number(root.dataset.stepCount);
247
+ const hold = parseFloat(getComputedStyle(root).getPropertyValue('--motion-hold')) || 720;
248
+ const parsedStep = requestedStep !== null && /^\d+$/.test(requestedStep) ? Number(requestedStep) : null;
249
+ const exactStep = params.get('motion') === 'step' && Number.isSafeInteger(parsedStep) && parsedStep >= 0 && parsedStep <= count ? parsedStep : null;
250
+ const items = [...root.querySelectorAll('[data-motion-item]')];
251
+ const labels = Array.from({ length: count + 1 }, (_, index) => index === 0
252
+ ? 'Ready'
253
+ : items.filter((item) => !item.hasAttribute('data-motion-decorative') && Number(item.dataset.step) === index)
254
+ .map((item) => item.getAttribute('aria-label')).join('; '));
255
+ const controls = root.querySelector('[data-motion-controls]');
256
+ const status = root.querySelector('[data-motion-status]');
257
+ const visibleStep = root.querySelector('[data-motion-step-label]');
258
+ let step = count;
259
+ let timer = 0;
260
+ let playing = false;
261
+ let stepBeforeReduce = 0;
262
+ let resumeAfterReduce = root.dataset.motionMode === 'reveal';
263
+
264
+ const buttons = (action) => controls.querySelector(`[data-motion-action="${action}"]`);
265
+ const clearClock = () => { window.clearTimeout(timer); timer = 0; };
266
+ const announce = () => { status.textContent = `Step ${step} of ${count}: ${labels[step] || 'Complete'}`; };
267
+ const setControlsAvailable = (available) => {
268
+ controls.hidden = !available;
269
+ controls.setAttribute('aria-hidden', String(!available));
270
+ controls.dataset.playbackDisabled = String(!available);
271
+ controls.querySelectorAll('button').forEach((control) => { control.disabled = !available; });
272
+ };
273
+
274
+ function render(next, userInitiated = false) {
275
+ step = Math.max(0, Math.min(count, next));
276
+ root.dataset.stepCurrent = String(step);
277
+ root.dataset.frame = step === count ? 'end' : step === 0 ? 'start' : 'step';
278
+ items.forEach((item) => {
279
+ const itemStep = Number(item.dataset.step);
280
+ item.classList.toggle('is-visible', itemStep <= step);
281
+ item.classList.toggle('is-current', itemStep === step);
282
+ });
283
+ if (visibleStep) visibleStep.textContent = String(step);
284
+ const unavailable = controls.dataset.playbackDisabled === 'true';
285
+ buttons('prev').disabled = unavailable || step === 0;
286
+ buttons('next').disabled = unavailable || step === count;
287
+ if (userInitiated) announce();
288
+ }
289
+
290
+ function pause(userInitiated = false) {
291
+ clearClock();
292
+ playing = false;
293
+ root.classList.remove('is-playing');
294
+ buttons('play').setAttribute('aria-pressed', 'false');
295
+ buttons('pause').setAttribute('aria-pressed', 'true');
296
+ if (userInitiated) status.textContent = `Paused at step ${step} of ${count}`;
297
+ }
298
+
299
+ function finish() {
300
+ pause(false);
301
+ root.dataset.frame = 'end';
302
+ status.textContent = `Complete · step ${count} of ${count}`;
303
+ }
304
+
305
+ function tick() {
306
+ if (!playing) return;
307
+ if (step >= count) { finish(); return; }
308
+ render(step + 1, false);
309
+ if (step >= count) { finish(); return; }
310
+ timer = window.setTimeout(tick, hold);
311
+ }
312
+
313
+ function play(fromStart = false, userInitiated = false) {
314
+ clearClock();
315
+ if (fromStart || step >= count) render(0, userInitiated);
316
+ playing = true;
317
+ root.classList.add('is-playing');
318
+ buttons('play').setAttribute('aria-pressed', 'true');
319
+ buttons('pause').setAttribute('aria-pressed', 'false');
320
+ timer = window.setTimeout(tick, hold);
321
+ }
322
+
323
+ controls.addEventListener('click', (event) => {
324
+ const button = event.target.closest('[data-motion-action]');
325
+ if (!button) return;
326
+ const action = button.dataset.motionAction;
327
+ if (action === 'play') play(false, true);
328
+ if (action === 'pause') pause(true);
329
+ if (action === 'replay') play(true, true);
330
+ if (action === 'prev') { pause(false); render(step - 1, true); }
331
+ if (action === 'next') { pause(false); render(step + 1, true); }
332
+ });
333
+
334
+ root.addEventListener('keydown', (event) => {
335
+ if (event.target.matches('input, textarea, select, a[href]')) return;
336
+ const keys = { ArrowLeft: step - 1, ArrowRight: step + 1, Home: 0, End: count };
337
+ if (event.code === 'Space' && !event.target.closest('button')) {
338
+ event.preventDefault();
339
+ playing ? pause(true) : play(false, true);
340
+ return;
341
+ }
342
+ if (!event.ctrlKey && !event.metaKey && !event.altKey && event.key.toLowerCase() === 'r') {
343
+ event.preventDefault();
344
+ play(true, true);
345
+ return;
346
+ }
347
+ if (!(event.key in keys)) return;
348
+ event.preventDefault();
349
+ pause(false);
350
+ render(keys[event.key], true);
351
+ });
352
+
353
+ document.addEventListener('visibilitychange', () => {
354
+ if (document.visibilityState === 'hidden' && playing) pause(false);
355
+ });
356
+ reduce.addEventListener('change', (event) => {
357
+ if (event.matches && root.dataset.motionState !== 'reduced') {
358
+ stepBeforeReduce = step;
359
+ resumeAfterReduce = playing;
360
+ }
361
+ pause(false);
362
+ if (event.matches) {
363
+ setControlsAvailable(false);
364
+ render(count, false);
365
+ root.dataset.frame = 'static';
366
+ root.dataset.motionState = 'reduced';
367
+ status.textContent = 'Reduced motion · complete static frame · playback controls unavailable';
368
+ } else if (staticOverride || root.dataset.motionMode === 'none') {
369
+ setControlsAvailable(false);
370
+ render(count, false);
371
+ root.dataset.frame = 'static';
372
+ root.dataset.motionState = 'static';
373
+ status.textContent = 'Static frame · complete diagram · playback controls unavailable';
374
+ } else {
375
+ delete root.dataset.motionState;
376
+ if (exactStep !== null) {
377
+ setControlsAvailable(false);
378
+ render(exactStep, false);
379
+ root.dataset.frame = 'step';
380
+ root.dataset.motionState = 'test';
381
+ status.textContent = `Test frame · step ${step} of ${count} · playback controls unavailable`;
382
+ } else {
383
+ setControlsAvailable(true);
384
+ render(stepBeforeReduce, false);
385
+ status.textContent = `Ready · step ${step} of ${count}`;
386
+ if (resumeAfterReduce && root.dataset.motionMode === 'reveal') {
387
+ play(false, false);
388
+ }
389
+ }
390
+ resumeAfterReduce = false;
391
+ }
392
+ });
393
+
394
+ if (staticOverride) {
395
+ document.documentElement.dataset.motion = 'static';
396
+ pause(false);
397
+ setControlsAvailable(false);
398
+ render(count, false);
399
+ root.dataset.frame = 'static';
400
+ root.dataset.motionState = 'static';
401
+ status.textContent = 'Static frame · complete diagram · playback controls unavailable';
402
+ } else if (reduce.matches || root.dataset.motionMode === 'none') {
403
+ pause(false);
404
+ setControlsAvailable(false);
405
+ render(count, false);
406
+ root.dataset.frame = 'static';
407
+ root.dataset.motionState = reduce.matches ? 'reduced' : 'static';
408
+ status.textContent = reduce.matches
409
+ ? 'Reduced motion · complete static frame · playback controls unavailable'
410
+ : 'Static frame · complete diagram · playback controls unavailable';
411
+ } else if (exactStep !== null) {
412
+ document.documentElement.dataset.motion = 'step';
413
+ pause(false);
414
+ setControlsAvailable(false);
415
+ render(exactStep, false);
416
+ root.dataset.frame = 'step';
417
+ root.dataset.motionState = 'test';
418
+ status.textContent = `Test frame · step ${step} of ${count} · playback controls unavailable`;
419
+ } else if (root.dataset.motionMode === 'reveal') {
420
+ setControlsAvailable(true);
421
+ render(0, false);
422
+ play(false, false);
423
+ } else {
424
+ pause(false);
425
+ setControlsAvailable(true);
426
+ render(0, false);
427
+ status.textContent = `Ready · step 0 of ${count}`;
428
+ }
429
+ root.classList.add('motion-ready');
430
+ });
431
+ })();
432
+ </script>
433
+ </body>
434
+ </html>
@@ -0,0 +1,173 @@
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>Diagram</title>
7
+ <link
8
+ href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500;600;700&display=swap"
9
+ rel="stylesheet"
10
+ />
11
+ <style>
12
+ *,
13
+ *::before,
14
+ *::after {
15
+ box-sizing: border-box;
16
+ margin: 0;
17
+ padding: 0;
18
+ }
19
+ :root {
20
+ --color-page: #0a0a0a;
21
+ --color-paper: #141414;
22
+ --color-bar: #1b1b1b;
23
+ --color-border: #2b2b2b;
24
+ --color-ink: #f5f5f5;
25
+ --color-muted: #9a9a9a;
26
+ --color-soft: #5c5c5c;
27
+ --color-accent: #ff5a36;
28
+ --color-accent-tint: rgba(255, 90, 54, 0.12);
29
+ --font-mono: "Geist Mono", ui-monospace, monospace;
30
+ }
31
+
32
+ body {
33
+ font-family: var(--font-mono);
34
+ background: var(--color-page);
35
+ min-height: 100vh;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ padding: 3rem 2rem;
40
+ }
41
+
42
+ .terminal {
43
+ width: 100%;
44
+ max-width: 1200px;
45
+ background: var(--color-paper);
46
+ border: 1px solid var(--color-border);
47
+ border-radius: 12px;
48
+ overflow: hidden;
49
+ }
50
+
51
+ .titlebar {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 8px;
55
+ padding: 12px 16px;
56
+ background: var(--color-bar);
57
+ border-bottom: 1px solid var(--color-border);
58
+ }
59
+
60
+ .dot {
61
+ width: 10px;
62
+ height: 10px;
63
+ border-radius: 50%;
64
+ background: var(--color-soft);
65
+ }
66
+ .dot.accent {
67
+ background: var(--color-accent);
68
+ } /* exactly one of the three dots gets this */
69
+
70
+ .titlebar-name {
71
+ flex: 1;
72
+ text-align: center;
73
+ color: var(--color-muted);
74
+ font-size: 0.7rem;
75
+ font-weight: 500;
76
+ letter-spacing: 0.04em;
77
+ margin-right: 46px; /* offsets the three dots so the name optically centers */
78
+ }
79
+
80
+ .frame {
81
+ padding: 2.25rem 2.5rem 2.5rem;
82
+ }
83
+
84
+ .prompt {
85
+ display: flex;
86
+ gap: 0.6em;
87
+ margin-bottom: 0.9rem;
88
+ color: var(--color-muted);
89
+ font-size: 0.8rem;
90
+ font-weight: 500;
91
+ }
92
+ .prompt .sign {
93
+ color: var(--color-accent);
94
+ }
95
+
96
+ h1 {
97
+ font-family: var(--font-mono);
98
+ font-size: clamp(1.5rem, 2.2vw + 0.8rem, 2.05rem);
99
+ font-weight: 700;
100
+ letter-spacing: -0.01em;
101
+ line-height: 1.2;
102
+ color: var(--color-ink);
103
+ margin-bottom: 1.5rem;
104
+ }
105
+ h1::before {
106
+ content: "# ";
107
+ color: var(--color-soft);
108
+ }
109
+
110
+ svg {
111
+ width: 100%;
112
+ min-width: 900px;
113
+ display: block;
114
+ }
115
+ </style>
116
+ </head>
117
+ <body>
118
+ <div class="terminal">
119
+ <div class="titlebar">
120
+ <div class="dot accent"></div>
121
+ <div class="dot"></div>
122
+ <div class="dot"></div>
123
+ <div class="titlebar-name">[file.sh] — [diagram-slug]</div>
124
+ </div>
125
+ <main class="frame">
126
+ <p class="prompt">
127
+ <span class="sign">$</span> [command that "generated" this]
128
+ </p>
129
+ <h1>[Diagram title]</h1>
130
+
131
+ <!-- Replace [diagram-slug] with a unique slug for this diagram before export. -->
132
+ <svg viewBox="0 0 1000 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="[diagram-slug]-title [diagram-slug]-desc">
133
+ <title id="[diagram-slug]-title">[Diagram title]</title>
134
+ <desc id="[diagram-slug]-desc">[One sentence describing what the diagram shows]</desc>
135
+ <defs>
136
+ <marker
137
+ id="arrow"
138
+ markerWidth="8"
139
+ markerHeight="6"
140
+ refX="7"
141
+ refY="3"
142
+ orient="auto"
143
+ >
144
+ <polygon points="0 0, 8 3, 0 6" fill="#9a9a9a" />
145
+ </marker>
146
+ <marker
147
+ id="arrow-accent"
148
+ markerWidth="8"
149
+ markerHeight="6"
150
+ refX="7"
151
+ refY="3"
152
+ orient="auto"
153
+ >
154
+ <polygon points="0 0, 8 3, 0 6" fill="#ff5a36" />
155
+ </marker>
156
+
157
+ <!-- OPTIONAL: dot-pattern background. Uncomment and add <rect fill="url(#dots)"/> after the paper rect to enable. -->
158
+ <!--
159
+ <pattern id="dots" width="22" height="22" patternUnits="userSpaceOnUse">
160
+ <circle cx="1" cy="1" r="0.9" fill="rgba(255,255,255,0.08)"/>
161
+ </pattern>
162
+ --></defs>
163
+
164
+ <rect width="100%" height="100%" fill="#141414" />
165
+
166
+ <!-- Draw arrows first, then nodes. Replace with your content.
167
+ Text sizes run ~1-2px above the default scale: node-name 14px,
168
+ sublabel/arrow-label 9-10px, hub label 18px. See primitive-terminal.md. -->
169
+ </svg>
170
+ </main>
171
+ </div>
172
+ </body>
173
+ </html>