claude-dev-env 1.83.0 → 1.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/_shared/pr-loop/audit-contract.md +24 -12
  2. package/_shared/pr-loop/scripts/_claude_permissions_common.py +16 -5
  3. package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
  4. package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -1
  5. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +8 -0
  6. package/_shared/pr-loop/scripts/reviews_disabled.py +2 -0
  7. package/_shared/pr-loop/scripts/terminology_sweep.py +85 -39
  8. package/_shared/pr-loop/scripts/tests/test__claude_permissions_common.py +212 -0
  9. package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +18 -0
  10. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +18 -0
  11. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +37 -0
  12. package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +14 -0
  13. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +94 -4
  14. package/agents/clean-coder.md +3 -0
  15. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
  16. package/bin/install.mjs +16 -8
  17. package/bin/install.test.mjs +17 -6
  18. package/commands/CLAUDE.md +0 -1
  19. package/docs/CODE_RULES.md +1 -1
  20. package/hooks/blocking/CLAUDE.md +0 -4
  21. package/hooks/blocking/claude_md_orphan_file_blocker.py +1 -1
  22. package/hooks/blocking/code_rules_constants_config.py +5 -0
  23. package/hooks/blocking/code_rules_docstrings.py +133 -19
  24. package/hooks/blocking/code_rules_enforcer.py +4 -0
  25. package/hooks/blocking/code_rules_imports_logging.py +10 -6
  26. package/hooks/blocking/code_rules_magic_values.py +5 -0
  27. package/hooks/blocking/code_rules_naming_collection.py +15 -8
  28. package/hooks/blocking/code_rules_paired_test.py +3 -2
  29. package/hooks/blocking/code_rules_shared.py +34 -0
  30. package/hooks/blocking/code_rules_string_magic.py +1 -1
  31. package/hooks/blocking/code_rules_unused_imports.py +2 -2
  32. package/hooks/blocking/duplicate_rmtree_helper_blocker.py +4 -4
  33. package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +29 -0
  34. package/hooks/blocking/test_code_rules_enforcer_docstring_prose_wall_illustration.py +197 -0
  35. package/hooks/blocking/test_code_rules_enforcer_docstring_runon_sentence.py +27 -0
  36. package/hooks/blocking/test_code_rules_enforcer_naive_datetime.py +24 -0
  37. package/hooks/blocking/test_code_rules_enforcer_split_constants_config.py +33 -0
  38. package/hooks/blocking/test_code_rules_enforcer_split_shared.py +23 -0
  39. package/hooks/blocking/test_code_rules_magic_values.py +54 -0
  40. package/hooks/blocking/test_duplicate_rmtree_helper_blocker.py +0 -6
  41. package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +184 -0
  42. package/hooks/blocking/test_shared_stdin_adoption.py +5 -30
  43. package/hooks/hooks_constants/CLAUDE.md +0 -3
  44. package/hooks/hooks_constants/blocking_check_limits.py +4 -0
  45. package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -1
  46. package/hooks/hooks_constants/duplicate_rmtree_helper_blocker_constants.py +0 -1
  47. package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -5
  48. package/hooks/validation/post_tool_use_dispatcher.py +1 -1
  49. package/hooks/validation/test_post_tool_use_dispatcher.py +51 -35
  50. package/hooks/workflow/CLAUDE.md +2 -8
  51. package/package.json +1 -1
  52. package/rules/CLAUDE.md +1 -1
  53. package/rules/docstring-prose-matches-implementation.md +1 -1
  54. package/rules/env-var-table-code-drift.md +1 -1
  55. package/rules/package-inventory-stale-entry.md +1 -1
  56. package/rules/paired-test-coverage.md +1 -1
  57. package/rules/plain-illustrative-docstrings.md +35 -1
  58. package/skills/CLAUDE.md +6 -1
  59. package/skills/_shared/pr-loop/CLAUDE.md +1 -0
  60. package/skills/_shared/pr-loop/scripts/CLAUDE.md +1 -0
  61. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -0
  62. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +45 -0
  63. package/skills/_shared/pr-loop/scripts/test_write_handoff.py +201 -0
  64. package/skills/_shared/pr-loop/scripts/write_handoff.py +309 -0
  65. package/skills/autoconverge/SKILL.md +82 -58
  66. package/skills/autoconverge/reference/closing-report.md +6 -6
  67. package/skills/autoconverge/reference/convergence.md +17 -15
  68. package/skills/autoconverge/reference/gotchas.md +6 -3
  69. package/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +2 -9
  70. package/skills/autoconverge/workflow/converge.contract.test.mjs +87 -13
  71. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +1 -1
  72. package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +16 -9
  73. package/skills/autoconverge/workflow/converge.mjs +71 -74
  74. package/skills/autoconverge/workflow/render_report.py +7 -11
  75. package/skills/bugteam/CLAUDE.md +1 -1
  76. package/skills/bugteam/PROMPTS.md +7 -6
  77. package/skills/bugteam/SKILL.md +25 -72
  78. package/skills/bugteam/reference/CLAUDE.md +1 -3
  79. package/skills/bugteam/reference/README.md +1 -1
  80. package/skills/bugteam/reference/audit-and-teammates.md +1 -1
  81. package/skills/bugteam/reference/obstacles/fix-publish-summary.md +1 -1
  82. package/skills/bugteam/reference/team-setup.md +8 -7
  83. package/skills/bugteam/scripts/CLAUDE.md +0 -6
  84. package/skills/bugteam/scripts/README.md +0 -4
  85. package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +0 -1
  86. package/skills/code/SKILL.md +2 -0
  87. package/skills/copilot-review/CLAUDE.md +1 -1
  88. package/skills/copilot-review/SKILL.md +25 -23
  89. package/skills/findbugs/CLAUDE.md +2 -2
  90. package/skills/findbugs/SKILL.md +22 -83
  91. package/skills/fixbugs/SKILL.md +2 -4
  92. package/skills/log-audit/CLAUDE.md +20 -0
  93. package/skills/log-audit/SKILL.md +68 -0
  94. package/skills/log-audit/reference/CLAUDE.md +9 -0
  95. package/skills/log-audit/reference/charter.md +52 -0
  96. package/skills/log-audit/scripts/CLAUDE.md +27 -0
  97. package/skills/log-audit/scripts/cluster_recurrences.py +261 -0
  98. package/skills/log-audit/scripts/collect_log_window.py +199 -0
  99. package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +12 -0
  100. package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +23 -0
  101. package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +24 -0
  102. package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +49 -0
  103. package/skills/log-audit/scripts/mine_copilot_findings.py +302 -0
  104. package/skills/log-audit/scripts/test_cluster_recurrences.py +160 -0
  105. package/skills/log-audit/scripts/test_collect_log_window.py +111 -0
  106. package/skills/log-audit/scripts/test_mine_copilot_findings.py +126 -0
  107. package/skills/monitor-open-prs/SKILL.md +2 -2
  108. package/skills/post-audit-findings/SKILL.md +84 -0
  109. package/skills/pr-converge/CLAUDE.md +2 -0
  110. package/skills/pr-converge/SKILL.md +99 -60
  111. package/skills/pr-converge/reference/CLAUDE.md +1 -1
  112. package/skills/pr-converge/reference/convergence-gates.md +16 -19
  113. package/skills/pr-converge/reference/examples.md +5 -5
  114. package/skills/pr-converge/reference/fix-protocol.md +16 -43
  115. package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +1 -1
  116. package/skills/pr-converge/reference/per-tick.md +24 -45
  117. package/skills/pr-converge/reference/state-schema.md +27 -0
  118. package/skills/pr-converge/scripts/README.md +3 -5
  119. package/skills/pr-fix-protocol/SKILL.md +70 -0
  120. package/skills/pr-loop-lifecycle/SKILL.md +73 -0
  121. package/skills/{bugteam → pr-loop-lifecycle}/reference/teardown-publish-permissions.md +22 -24
  122. package/skills/pr-scope-resolve/SKILL.md +48 -0
  123. package/skills/qbug/CLAUDE.md +4 -4
  124. package/skills/qbug/SKILL.md +46 -144
  125. package/skills/qbug/test_qbug_skill_audit_schema.py +2 -2
  126. package/skills/qbug/test_qbug_skill_post_fix_audit.py +1 -1
  127. package/skills/reviewer-gates/SKILL.md +96 -0
  128. package/skills/session-log/CLAUDE.md +7 -7
  129. package/skills/session-log/SKILL.md +27 -44
  130. package/skills/test_markdown_link_integrity.py +103 -0
  131. package/commands/doc-gist.md +0 -16
  132. package/hooks/blocking/_md_to_html_blocker_test_support.py +0 -65
  133. package/hooks/blocking/conftest.py +0 -30
  134. package/hooks/blocking/md_path_exemptions.py +0 -224
  135. package/hooks/blocking/md_to_html_blocker.py +0 -155
  136. package/hooks/blocking/test_md_to_html_blocker_exemptions.py +0 -434
  137. package/hooks/blocking/test_md_to_html_blocker_extensions.py +0 -157
  138. package/hooks/blocking/test_md_to_html_blocker_path_resolution.py +0 -336
  139. package/hooks/hooks_constants/doc_gist_auto_publish_constants.py +0 -18
  140. package/hooks/hooks_constants/html_companion_constants.py +0 -20
  141. package/hooks/hooks_constants/md_to_html_blocker_constants.py +0 -76
  142. package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +0 -125
  143. package/hooks/workflow/doc_gist_auto_publish.py +0 -144
  144. package/hooks/workflow/md_to_html_companion.py +0 -358
  145. package/hooks/workflow/test_doc_gist_auto_publish.py +0 -117
  146. package/hooks/workflow/test_md_to_html_companion.py +0 -613
  147. package/skills/bugteam/reference/audit-contract.md +0 -163
  148. package/skills/bugteam/scripts/_bugteam_permissions_common.py +0 -455
  149. package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py +0 -69
  150. package/skills/bugteam/scripts/grant_project_claude_permissions.py +0 -280
  151. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +0 -266
  152. package/skills/bugteam/scripts/test__bugteam_permissions_common.py +0 -160
  153. package/skills/bugteam/scripts/test_agent_config_carveout.py +0 -356
  154. package/skills/bugteam/scripts/test_bugteam_permissions_common.py +0 -140
  155. package/skills/doc-gist/CLAUDE.md +0 -25
  156. package/skills/doc-gist/SKILL.md +0 -97
  157. package/skills/doc-gist/references/CLAUDE.md +0 -9
  158. package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +0 -453
  159. package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +0 -515
  160. package/skills/doc-gist/references/examples/03-code-review-pr.html +0 -638
  161. package/skills/doc-gist/references/examples/04-code-understanding.html +0 -491
  162. package/skills/doc-gist/references/examples/05-design-system.html +0 -629
  163. package/skills/doc-gist/references/examples/06-component-variants.html +0 -605
  164. package/skills/doc-gist/references/examples/07-prototype-animation.html +0 -455
  165. package/skills/doc-gist/references/examples/08-prototype-interaction.html +0 -396
  166. package/skills/doc-gist/references/examples/09-slide-deck.html +0 -592
  167. package/skills/doc-gist/references/examples/10-svg-illustrations.html +0 -492
  168. package/skills/doc-gist/references/examples/11-status-report.html +0 -528
  169. package/skills/doc-gist/references/examples/12-incident-report.html +0 -596
  170. package/skills/doc-gist/references/examples/13-flowchart-diagram.html +0 -395
  171. package/skills/doc-gist/references/examples/14-research-feature-explainer.html +0 -381
  172. package/skills/doc-gist/references/examples/15-research-concept-explainer.html +0 -368
  173. package/skills/doc-gist/references/examples/16-implementation-plan.html +0 -702
  174. package/skills/doc-gist/references/examples/17-pr-writeup.html +0 -595
  175. package/skills/doc-gist/references/examples/18-editor-triage-board.html +0 -573
  176. package/skills/doc-gist/references/examples/19-editor-feature-flags.html +0 -663
  177. package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +0 -722
  178. package/skills/doc-gist/references/examples/21-decision-signoff.html +0 -546
  179. package/skills/doc-gist/references/examples/CLAUDE.md +0 -25
  180. package/skills/doc-gist/references/examples/README.md +0 -5
  181. package/skills/doc-gist/scripts/CLAUDE.md +0 -27
  182. package/skills/doc-gist/scripts/doc_gist_scripts_constants/CLAUDE.md +0 -10
  183. package/skills/doc-gist/scripts/doc_gist_scripts_constants/gist_upload_constants.py +0 -16
  184. package/skills/doc-gist/scripts/gist_upload.py +0 -177
  185. package/skills/doc-gist/scripts/test_gist_upload.py +0 -51
  186. /package/skills/{doc-gist/scripts/doc_gist_scripts_constants → log-audit/scripts/log_audit_constants}/__init__.py +0 -0
@@ -1,515 +0,0 @@
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>Empty state — four visual directions</title>
7
- <style>
8
- :root {
9
- --ivory: #FAF9F5;
10
- --slate: #141413;
11
- --clay: #D97757;
12
- --oat: #E3DACC;
13
- --olive: #788C5D;
14
- --gray-150: #F0EEE6;
15
- --gray-300: #D1CFC5;
16
- --gray-500: #87867F;
17
- --gray-700: #3D3D3A;
18
- --white: #FFFFFF;
19
-
20
- --serif: ui-serif, Georgia, 'Times New Roman', serif;
21
- --sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
22
- --mono: ui-monospace, 'SF Mono', Menlo, Monaco, monospace;
23
- }
24
-
25
- * { margin: 0; padding: 0; box-sizing: border-box; }
26
-
27
- body {
28
- font-family: var(--sans);
29
- background: var(--ivory);
30
- color: var(--gray-700);
31
- line-height: 1.55;
32
- -webkit-font-smoothing: antialiased;
33
- padding-bottom: 96px;
34
- }
35
-
36
- /* ---------- sticky toolbar ---------- */
37
-
38
- .toolbar {
39
- position: sticky;
40
- top: 0;
41
- z-index: 10;
42
- background: var(--ivory);
43
- border-bottom: 1.5px solid var(--gray-300);
44
- padding: 14px 32px;
45
- display: flex;
46
- align-items: center;
47
- gap: 18px;
48
- font-size: 13px;
49
- }
50
-
51
- .toolbar .title {
52
- font-family: var(--mono);
53
- font-size: 12px;
54
- letter-spacing: 0.04em;
55
- color: var(--gray-500);
56
- margin-right: auto;
57
- }
58
-
59
- .toolbar .field {
60
- display: flex;
61
- align-items: center;
62
- gap: 10px;
63
- }
64
-
65
- .toolbar .field > span {
66
- color: var(--gray-700);
67
- font-weight: 500;
68
- }
69
-
70
- .seg {
71
- display: inline-flex;
72
- border: 1.5px solid var(--gray-300);
73
- border-radius: 8px;
74
- overflow: hidden;
75
- background: var(--white);
76
- }
77
-
78
- .seg label {
79
- padding: 6px 14px;
80
- cursor: pointer;
81
- font-size: 13px;
82
- color: var(--gray-700);
83
- user-select: none;
84
- }
85
-
86
- .seg label + label {
87
- border-left: 1.5px solid var(--gray-300);
88
- }
89
-
90
- .seg input { display: none; }
91
-
92
- .seg input:checked + span {
93
- color: var(--slate);
94
- font-weight: 600;
95
- }
96
-
97
- .seg label:has(input:checked) {
98
- background: var(--oat);
99
- }
100
-
101
- /* ---------- page header ---------- */
102
-
103
- .page {
104
- max-width: 1240px;
105
- margin: 0 auto;
106
- padding: 48px 32px 0;
107
- }
108
-
109
- header.page-head {
110
- max-width: 720px;
111
- margin-bottom: 40px;
112
- }
113
-
114
- .eyebrow {
115
- font-size: 12px;
116
- letter-spacing: 0.08em;
117
- text-transform: uppercase;
118
- color: var(--gray-500);
119
- margin-bottom: 12px;
120
- }
121
-
122
- h1 {
123
- font-family: var(--serif);
124
- font-weight: 500;
125
- font-size: 38px;
126
- line-height: 1.15;
127
- color: var(--slate);
128
- margin-bottom: 18px;
129
- letter-spacing: -0.01em;
130
- }
131
-
132
- .prompt-box {
133
- background: var(--gray-150);
134
- border: 1.5px solid var(--gray-300);
135
- border-radius: 12px;
136
- padding: 16px 20px;
137
- font-size: 14.5px;
138
- }
139
-
140
- .prompt-box .label {
141
- font-family: var(--mono);
142
- font-size: 11px;
143
- text-transform: uppercase;
144
- letter-spacing: 0.06em;
145
- color: var(--gray-500);
146
- display: block;
147
- margin-bottom: 6px;
148
- }
149
-
150
- /* ---------- artboard grid ---------- */
151
-
152
- .board {
153
- display: grid;
154
- grid-template-columns: 1fr 1fr;
155
- gap: 32px;
156
- }
157
-
158
- @media (max-width: 960px) {
159
- .board { grid-template-columns: 1fr; }
160
- }
161
-
162
- .artboard {
163
- background: var(--white);
164
- border: 1.5px solid var(--gray-300);
165
- border-radius: 12px;
166
- padding: 20px;
167
- position: relative;
168
- }
169
-
170
- .tag {
171
- position: absolute;
172
- top: 14px;
173
- left: 14px;
174
- font-family: var(--mono);
175
- font-size: 11px;
176
- letter-spacing: 0.02em;
177
- background: var(--oat);
178
- color: var(--slate);
179
- padding: 4px 10px;
180
- border-radius: 8px;
181
- z-index: 2;
182
- }
183
-
184
- .stage {
185
- height: 280px;
186
- border-radius: 8px;
187
- border: 1.5px solid var(--gray-300);
188
- background: var(--ivory);
189
- display: flex;
190
- align-items: center;
191
- justify-content: center;
192
- padding: 24px;
193
- transition: background 0.15s, border-color 0.15s;
194
- overflow: hidden;
195
- }
196
-
197
- .stage.dark {
198
- background: var(--slate);
199
- border-color: var(--slate);
200
- }
201
-
202
- .rationale {
203
- margin-top: 16px;
204
- font-size: 13px;
205
- color: var(--gray-500);
206
- line-height: 1.5;
207
- }
208
-
209
- /* =========================================================
210
- Empty-state variants — each scoped under .es-*
211
- Theme tokens flip when .stage.dark is present.
212
- ========================================================= */
213
-
214
- .stage { --fg: var(--slate); --muted: var(--gray-500); --line: var(--gray-300); --panel: var(--white); }
215
- .stage.dark { --fg: #F0EEE6; --muted: #9C9A93; --line: #3D3D3A; --panel: #1F1E1B; }
216
-
217
- /* ---- A · Minimal ---- */
218
-
219
- .es-a {
220
- text-align: center;
221
- max-width: 300px;
222
- }
223
- .es-a h3 {
224
- font-family: var(--serif);
225
- font-weight: 500;
226
- font-size: 19px;
227
- color: var(--fg);
228
- margin-bottom: 6px;
229
- }
230
- .es-a p {
231
- font-size: 13px;
232
- color: var(--muted);
233
- margin-bottom: 18px;
234
- }
235
- .es-a .btn {
236
- display: inline-block;
237
- font-size: 13px;
238
- color: var(--fg);
239
- border: 1.5px solid var(--line);
240
- border-radius: 8px;
241
- padding: 8px 16px;
242
- background: transparent;
243
- }
244
-
245
- /* ---- B · Illustrated ---- */
246
-
247
- .es-b {
248
- text-align: center;
249
- max-width: 320px;
250
- }
251
- .es-b svg {
252
- display: block;
253
- margin: 0 auto 18px;
254
- }
255
- .es-b h3 {
256
- font-family: var(--serif);
257
- font-weight: 500;
258
- font-size: 19px;
259
- color: var(--fg);
260
- margin-bottom: 6px;
261
- }
262
- .es-b p {
263
- font-size: 13px;
264
- color: var(--muted);
265
- margin-bottom: 16px;
266
- }
267
- .es-b .btn {
268
- display: inline-block;
269
- font-size: 13px;
270
- font-weight: 500;
271
- color: var(--white);
272
- background: var(--clay);
273
- border-radius: 8px;
274
- padding: 8px 16px;
275
- }
276
- .stage.dark .es-b .btn { color: var(--slate); background: var(--oat); }
277
-
278
- /* ---- C · Playful ---- */
279
-
280
- .es-c {
281
- text-align: center;
282
- max-width: 300px;
283
- }
284
- .es-c .float {
285
- width: 56px;
286
- height: 56px;
287
- margin: 0 auto 20px;
288
- position: relative;
289
- animation: bob 3.2s ease-in-out infinite;
290
- }
291
- .es-c .float .card {
292
- position: absolute;
293
- inset: 0;
294
- border-radius: 10px;
295
- background: var(--panel);
296
- border: 1.5px solid var(--line);
297
- }
298
- .es-c .float .card:nth-child(1) { transform: rotate(-8deg) translate(-6px, 4px); opacity: 0.5; }
299
- .es-c .float .card:nth-child(2) { transform: rotate( 6deg) translate( 6px, 2px); opacity: 0.75; }
300
- .es-c .float .card:nth-child(3) { background: var(--oat); border-color: var(--oat); }
301
- .stage.dark .es-c .float .card:nth-child(3) { background: var(--clay); border-color: var(--clay); }
302
- .es-c .shadow {
303
- width: 44px;
304
- height: 8px;
305
- margin: -8px auto 22px;
306
- border-radius: 50%;
307
- background: rgba(0,0,0,0.12);
308
- filter: blur(2px);
309
- animation: shadow 3.2s ease-in-out infinite;
310
- }
311
- .stage.dark .es-c .shadow { background: rgba(0,0,0,0.5); }
312
- .es-c h3 {
313
- font-family: var(--serif);
314
- font-weight: 500;
315
- font-size: 19px;
316
- color: var(--fg);
317
- margin-bottom: 6px;
318
- }
319
- .es-c p {
320
- font-size: 13px;
321
- color: var(--muted);
322
- }
323
-
324
- @keyframes bob {
325
- 0%, 100% { transform: translateY(0); }
326
- 50% { transform: translateY(-10px); }
327
- }
328
- @keyframes shadow {
329
- 0%, 100% { transform: scaleX(1); opacity: 0.9; }
330
- 50% { transform: scaleX(0.8); opacity: 0.5; }
331
- }
332
-
333
- /* ---- D · Instructional ---- */
334
-
335
- .es-d {
336
- width: 100%;
337
- max-width: 360px;
338
- }
339
- .es-d h3 {
340
- font-family: var(--serif);
341
- font-weight: 500;
342
- font-size: 18px;
343
- color: var(--fg);
344
- margin-bottom: 14px;
345
- }
346
- .es-d ol {
347
- list-style: none;
348
- counter-reset: step;
349
- display: flex;
350
- flex-direction: column;
351
- gap: 10px;
352
- }
353
- .es-d li {
354
- counter-increment: step;
355
- display: flex;
356
- align-items: flex-start;
357
- gap: 12px;
358
- background: var(--panel);
359
- border: 1.5px solid var(--line);
360
- border-radius: 8px;
361
- padding: 10px 14px;
362
- font-size: 13px;
363
- color: var(--fg);
364
- }
365
- .es-d li::before {
366
- content: counter(step);
367
- font-family: var(--mono);
368
- font-size: 11px;
369
- flex: 0 0 20px;
370
- height: 20px;
371
- border-radius: 50%;
372
- background: var(--oat);
373
- color: var(--slate);
374
- display: inline-flex;
375
- align-items: center;
376
- justify-content: center;
377
- margin-top: 1px;
378
- }
379
- .es-d li span { color: var(--muted); display: block; font-size: 12px; margin-top: 2px; }
380
- </style>
381
- </head>
382
- <body>
383
-
384
- <div class="toolbar">
385
- <div class="title">Birchline · design exploration</div>
386
- <div class="field">
387
- <span>Background:</span>
388
- <div class="seg" id="bg-seg">
389
- <label><input type="radio" name="bg" value="light" checked><span>Light</span></label>
390
- <label><input type="radio" name="bg" value="dark"><span>Dark</span></label>
391
- </div>
392
- </div>
393
- </div>
394
-
395
- <div class="page">
396
-
397
- <header class="page-head">
398
- <div class="eyebrow">Exploration · Empty states</div>
399
- <h1>Four visual directions for the “no tasks yet” state</h1>
400
- <div class="prompt-box">
401
- <span class="label">Prompt</span>
402
- Explore four visual directions for our empty-state component. Render each
403
- live so we can compare tone, density, and how well they hold up on light
404
- and dark surfaces.
405
- </div>
406
- </header>
407
-
408
- <section class="board">
409
-
410
- <!-- ================= A — Minimal ================= -->
411
- <article class="artboard">
412
- <span class="tag">A — Minimal</span>
413
- <div class="stage">
414
- <div class="es-a">
415
- <h3>No tasks yet</h3>
416
- <p>When you create a task it will show up here.</p>
417
- <span class="btn">New task</span>
418
- </div>
419
- </div>
420
- <p class="rationale">
421
- Pure typography, single quiet action. Reads as calm and confident;
422
- assumes the surrounding UI already carries enough personality.
423
- </p>
424
- </article>
425
-
426
- <!-- ================= B — Illustrated ================= -->
427
- <article class="artboard">
428
- <span class="tag">B — Illustrated</span>
429
- <div class="stage">
430
- <div class="es-b">
431
- <svg width="120" height="90" viewBox="0 0 120 90" aria-hidden="true">
432
- <rect x="14" y="20" width="72" height="54" rx="8"
433
- fill="var(--panel)" stroke="var(--line)" stroke-width="1.5"/>
434
- <rect x="34" y="10" width="72" height="54" rx="8"
435
- fill="var(--oat)"/>
436
- <line x1="46" y1="26" x2="92" y2="26"
437
- stroke="var(--slate)" stroke-width="2" stroke-linecap="round"/>
438
- <line x1="46" y1="38" x2="80" y2="38"
439
- stroke="var(--slate)" stroke-width="2" stroke-linecap="round" opacity="0.5"/>
440
- <circle cx="98" cy="60" r="12" fill="var(--clay)"/>
441
- <path d="M98 55 v10 M93 60 h10"
442
- stroke="white" stroke-width="2" stroke-linecap="round"/>
443
- </svg>
444
- <h3>Start your first list</h3>
445
- <p>Group related work and watch progress roll up automatically.</p>
446
- <span class="btn">Create a task</span>
447
- </div>
448
- </div>
449
- <p class="rationale">
450
- A small geometric spot illustration anchors the eye and explains the
451
- object model (lists contain tasks) without a wall of copy.
452
- </p>
453
- </article>
454
-
455
- <!-- ================= C — Playful ================= -->
456
- <article class="artboard">
457
- <span class="tag">C — Playful</span>
458
- <div class="stage">
459
- <div class="es-c">
460
- <div class="float">
461
- <div class="card"></div>
462
- <div class="card"></div>
463
- <div class="card"></div>
464
- </div>
465
- <div class="shadow"></div>
466
- <h3>Nothing on your plate</h3>
467
- <p>Enjoy the quiet, or add something to get moving.</p>
468
- </div>
469
- </div>
470
- <p class="rationale">
471
- A gently bobbing stack adds life to an otherwise static screen. Motion
472
- is subtle enough to loop indefinitely without drawing complaints.
473
- </p>
474
- </article>
475
-
476
- <!-- ================= D — Instructional ================= -->
477
- <article class="artboard">
478
- <span class="tag">D — Instructional</span>
479
- <div class="stage">
480
- <div class="es-d">
481
- <h3>Set up this project</h3>
482
- <ol>
483
- <li>
484
- Create your first task
485
- <span>Give it a name and an owner.</span>
486
- </li>
487
- <li>
488
- Add a due date
489
- <span>Birchline will surface it on the timeline.</span>
490
- </li>
491
- <li>
492
- Invite a teammate
493
- <span>Shared projects stay in sync automatically.</span>
494
- </li>
495
- </ol>
496
- </div>
497
- </div>
498
- <p class="rationale">
499
- Treats the empty state as onboarding. Higher density, but every line is
500
- actionable — best when the user is new to the product, not just the view.
501
- </p>
502
- </article>
503
-
504
- </section>
505
- </div>
506
-
507
- <script>
508
- const stages = document.querySelectorAll('.stage');
509
- document.getElementById('bg-seg').addEventListener('change', (e) => {
510
- const dark = e.target.value === 'dark';
511
- stages.forEach((s) => s.classList.toggle('dark', dark));
512
- });
513
- </script>
514
- </body>
515
- </html>