claude-dev-env 1.82.0 → 1.84.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 (217) hide show
  1. package/CLAUDE.md +16 -13
  2. package/_shared/pr-loop/audit-contract.md +24 -12
  3. package/_shared/pr-loop/scripts/CLAUDE.md +1 -0
  4. package/_shared/pr-loop/scripts/README.md +1 -0
  5. package/_shared/pr-loop/scripts/_claude_permissions_common.py +16 -5
  6. package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
  7. package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -0
  8. package/_shared/pr-loop/scripts/pr_loop_shared_constants/reviewer_availability_constants.py +12 -0
  9. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +0 -2
  10. package/_shared/pr-loop/scripts/reviewer_availability.py +182 -0
  11. package/_shared/pr-loop/scripts/reviews_disabled.py +2 -0
  12. package/_shared/pr-loop/scripts/terminology_sweep.py +9 -33
  13. package/_shared/pr-loop/scripts/tests/CLAUDE.md +2 -0
  14. package/_shared/pr-loop/scripts/tests/test__claude_permissions_common.py +212 -0
  15. package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +18 -0
  16. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +18 -0
  17. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +37 -0
  18. package/_shared/pr-loop/scripts/tests/test_reviewer_availability.py +159 -0
  19. package/_shared/pr-loop/scripts/tests/test_reviewer_availability_constants.py +36 -0
  20. package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +14 -0
  21. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +14 -4
  22. package/agents/clean-coder.md +3 -0
  23. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
  24. package/bin/install.mjs +16 -8
  25. package/bin/install.test.mjs +17 -6
  26. package/commands/CLAUDE.md +0 -1
  27. package/docs/CODE_RULES.md +1 -1
  28. package/hooks/blocking/CLAUDE.md +2 -4
  29. package/hooks/blocking/code_rules_constants_config.py +164 -1
  30. package/hooks/blocking/code_rules_docstrings.py +428 -15
  31. package/hooks/blocking/code_rules_enforcer.py +33 -0
  32. package/hooks/blocking/code_rules_imports_logging.py +867 -1
  33. package/hooks/blocking/code_rules_magic_values.py +5 -0
  34. package/hooks/blocking/code_rules_naming_collection.py +152 -6
  35. package/hooks/blocking/code_rules_shared.py +34 -0
  36. package/hooks/blocking/code_rules_string_magic.py +68 -0
  37. package/hooks/blocking/duplicate_rmtree_helper_blocker.py +4 -4
  38. package/hooks/blocking/pre_tool_use_dispatcher.py +3 -3
  39. package/hooks/blocking/reviewer_spawn_gate.py +182 -0
  40. package/hooks/blocking/stale_comment_reference_blocker.py +267 -0
  41. package/hooks/blocking/state_description_blocker.py +96 -5
  42. package/hooks/blocking/test_code_rules_config_duplicate_path_anchor.py +132 -0
  43. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +2 -0
  44. package/hooks/blocking/test_code_rules_enforcer_docstring_delegation_summary.py +385 -0
  45. package/hooks/blocking/test_code_rules_enforcer_docstring_prose_wall_illustration.py +197 -0
  46. package/hooks/blocking/test_code_rules_enforcer_docstring_runon_sentence.py +27 -0
  47. package/hooks/blocking/test_code_rules_enforcer_join_separator_magic.py +67 -0
  48. package/hooks/blocking/test_code_rules_enforcer_module_docstring_roster.py +40 -0
  49. package/hooks/blocking/test_code_rules_enforcer_naive_datetime.py +213 -0
  50. package/hooks/blocking/test_code_rules_enforcer_referenced_underscore_loop.py +169 -0
  51. package/hooks/blocking/test_code_rules_enforcer_split_constants_config.py +33 -0
  52. package/hooks/blocking/test_code_rules_enforcer_split_shared.py +23 -0
  53. package/hooks/blocking/test_code_rules_js_bare_flag_return_directive.py +266 -0
  54. package/hooks/blocking/test_code_rules_js_sibling_return_object_key_drift.py +490 -0
  55. package/hooks/blocking/test_code_rules_logging_adjacent_literals.py +171 -0
  56. package/hooks/blocking/test_code_rules_magic_values.py +54 -0
  57. package/hooks/blocking/test_duplicate_rmtree_helper_blocker.py +0 -6
  58. package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +184 -0
  59. package/hooks/blocking/test_pre_tool_use_dispatcher.py +9 -3
  60. package/hooks/blocking/test_reviewer_spawn_gate.py +230 -0
  61. package/hooks/blocking/test_shared_stdin_adoption.py +5 -30
  62. package/hooks/blocking/test_stale_comment_reference_blocker.py +236 -0
  63. package/hooks/blocking/test_state_description_blocker.py +135 -0
  64. package/hooks/hooks.json +5 -0
  65. package/hooks/hooks_constants/CLAUDE.md +3 -4
  66. package/hooks/hooks_constants/blocking_check_limits.py +46 -0
  67. package/hooks/hooks_constants/code_rules_enforcer_constants.py +41 -0
  68. package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -1
  69. package/hooks/hooks_constants/duplicate_rmtree_helper_blocker_constants.py +0 -1
  70. package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -5
  71. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +4 -0
  72. package/hooks/hooks_constants/reviewer_spawn_gate_constants.py +41 -0
  73. package/hooks/hooks_constants/stale_comment_reference_blocker_constants.py +76 -0
  74. package/hooks/hooks_constants/state_description_blocker_constants.py +8 -0
  75. package/hooks/validation/post_tool_use_dispatcher.py +1 -1
  76. package/hooks/validation/test_post_tool_use_dispatcher.py +51 -35
  77. package/hooks/workflow/CLAUDE.md +2 -8
  78. package/package.json +1 -1
  79. package/rules/CLAUDE.md +5 -2
  80. package/rules/claude-md-orphan-file.md +5 -0
  81. package/rules/docstring-prose-matches-implementation.md +10 -1
  82. package/rules/env-var-table-code-drift.md +5 -0
  83. package/rules/es-exe-file-search.md +17 -0
  84. package/rules/no-historical-clutter.md +12 -1
  85. package/rules/orphan-css-class.md +5 -0
  86. package/rules/package-inventory-stale-entry.md +10 -0
  87. package/rules/paired-test-coverage.md +5 -0
  88. package/rules/plain-illustrative-docstrings.md +40 -1
  89. package/rules/verify-before-asking.md +7 -0
  90. package/rules/verify-runtime-state.md +40 -0
  91. package/rules/windows-filesystem-safe.md +8 -0
  92. package/rules/workers-done-before-complete.md +33 -0
  93. package/rules/workflow-substitution-slots.md +5 -0
  94. package/skills/CLAUDE.md +7 -2
  95. package/skills/autoconverge/SKILL.md +48 -61
  96. package/skills/autoconverge/reference/closing-report.md +6 -6
  97. package/skills/autoconverge/reference/convergence.md +17 -15
  98. package/skills/autoconverge/reference/gotchas.md +6 -3
  99. package/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +2 -9
  100. package/skills/autoconverge/workflow/converge.contract.test.mjs +153 -10
  101. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +55 -19
  102. package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +16 -9
  103. package/skills/autoconverge/workflow/converge.mjs +167 -106
  104. package/skills/autoconverge/workflow/render_report.py +7 -11
  105. package/skills/bugteam/CLAUDE.md +1 -1
  106. package/skills/bugteam/PROMPTS.md +7 -6
  107. package/skills/bugteam/SKILL.md +25 -72
  108. package/skills/bugteam/reference/CLAUDE.md +1 -3
  109. package/skills/bugteam/reference/README.md +1 -1
  110. package/skills/bugteam/reference/audit-and-teammates.md +1 -1
  111. package/skills/bugteam/reference/obstacles/fix-publish-summary.md +1 -1
  112. package/skills/bugteam/reference/team-setup.md +8 -7
  113. package/skills/bugteam/scripts/CLAUDE.md +0 -6
  114. package/skills/bugteam/scripts/README.md +0 -4
  115. package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +0 -1
  116. package/skills/code/SKILL.md +2 -0
  117. package/skills/copilot-review/CLAUDE.md +1 -1
  118. package/skills/copilot-review/SKILL.md +25 -23
  119. package/skills/everything-search/SKILL.md +5 -0
  120. package/skills/findbugs/CLAUDE.md +2 -2
  121. package/skills/findbugs/SKILL.md +22 -83
  122. package/skills/fixbugs/SKILL.md +2 -4
  123. package/skills/log-audit/CLAUDE.md +20 -0
  124. package/skills/log-audit/SKILL.md +68 -0
  125. package/skills/log-audit/reference/CLAUDE.md +9 -0
  126. package/skills/log-audit/reference/charter.md +52 -0
  127. package/skills/log-audit/scripts/CLAUDE.md +27 -0
  128. package/skills/log-audit/scripts/cluster_recurrences.py +261 -0
  129. package/skills/log-audit/scripts/collect_log_window.py +199 -0
  130. package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +12 -0
  131. package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +23 -0
  132. package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +24 -0
  133. package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +49 -0
  134. package/skills/log-audit/scripts/mine_copilot_findings.py +302 -0
  135. package/skills/log-audit/scripts/test_cluster_recurrences.py +160 -0
  136. package/skills/log-audit/scripts/test_collect_log_window.py +111 -0
  137. package/skills/log-audit/scripts/test_mine_copilot_findings.py +126 -0
  138. package/skills/monitor-open-prs/SKILL.md +2 -2
  139. package/skills/post-audit-findings/SKILL.md +84 -0
  140. package/skills/pr-converge/CLAUDE.md +2 -0
  141. package/skills/pr-converge/SKILL.md +72 -59
  142. package/skills/pr-converge/reference/CLAUDE.md +1 -1
  143. package/skills/pr-converge/reference/convergence-gates.md +16 -19
  144. package/skills/pr-converge/reference/examples.md +5 -5
  145. package/skills/pr-converge/reference/fix-protocol.md +16 -43
  146. package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +1 -1
  147. package/skills/pr-converge/reference/per-tick.md +24 -45
  148. package/skills/pr-converge/reference/state-schema.md +15 -0
  149. package/skills/pr-converge/scripts/README.md +3 -5
  150. package/skills/pr-fix-protocol/SKILL.md +70 -0
  151. package/skills/pr-loop-lifecycle/SKILL.md +73 -0
  152. package/skills/{bugteam → pr-loop-lifecycle}/reference/teardown-publish-permissions.md +22 -24
  153. package/skills/pr-scope-resolve/SKILL.md +48 -0
  154. package/skills/qbug/CLAUDE.md +4 -4
  155. package/skills/qbug/SKILL.md +46 -144
  156. package/skills/qbug/test_qbug_skill_audit_schema.py +2 -2
  157. package/skills/qbug/test_qbug_skill_post_fix_audit.py +1 -1
  158. package/skills/reviewer-gates/SKILL.md +96 -0
  159. package/skills/session-log/CLAUDE.md +7 -7
  160. package/skills/session-log/SKILL.md +27 -44
  161. package/skills/test_markdown_link_integrity.py +103 -0
  162. package/commands/doc-gist.md +0 -16
  163. package/hooks/blocking/_md_to_html_blocker_test_support.py +0 -65
  164. package/hooks/blocking/conftest.py +0 -30
  165. package/hooks/blocking/md_path_exemptions.py +0 -224
  166. package/hooks/blocking/md_to_html_blocker.py +0 -155
  167. package/hooks/blocking/test_md_to_html_blocker_exemptions.py +0 -434
  168. package/hooks/blocking/test_md_to_html_blocker_extensions.py +0 -157
  169. package/hooks/blocking/test_md_to_html_blocker_path_resolution.py +0 -336
  170. package/hooks/hooks_constants/doc_gist_auto_publish_constants.py +0 -18
  171. package/hooks/hooks_constants/html_companion_constants.py +0 -20
  172. package/hooks/hooks_constants/md_to_html_blocker_constants.py +0 -76
  173. package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +0 -125
  174. package/hooks/workflow/doc_gist_auto_publish.py +0 -144
  175. package/hooks/workflow/md_to_html_companion.py +0 -358
  176. package/hooks/workflow/test_doc_gist_auto_publish.py +0 -117
  177. package/hooks/workflow/test_md_to_html_companion.py +0 -613
  178. package/skills/bugteam/reference/audit-contract.md +0 -163
  179. package/skills/bugteam/scripts/_bugteam_permissions_common.py +0 -455
  180. package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py +0 -69
  181. package/skills/bugteam/scripts/grant_project_claude_permissions.py +0 -280
  182. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +0 -266
  183. package/skills/bugteam/scripts/test__bugteam_permissions_common.py +0 -160
  184. package/skills/bugteam/scripts/test_agent_config_carveout.py +0 -356
  185. package/skills/bugteam/scripts/test_bugteam_permissions_common.py +0 -140
  186. package/skills/doc-gist/CLAUDE.md +0 -25
  187. package/skills/doc-gist/SKILL.md +0 -97
  188. package/skills/doc-gist/references/CLAUDE.md +0 -9
  189. package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +0 -453
  190. package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +0 -515
  191. package/skills/doc-gist/references/examples/03-code-review-pr.html +0 -638
  192. package/skills/doc-gist/references/examples/04-code-understanding.html +0 -491
  193. package/skills/doc-gist/references/examples/05-design-system.html +0 -629
  194. package/skills/doc-gist/references/examples/06-component-variants.html +0 -605
  195. package/skills/doc-gist/references/examples/07-prototype-animation.html +0 -455
  196. package/skills/doc-gist/references/examples/08-prototype-interaction.html +0 -396
  197. package/skills/doc-gist/references/examples/09-slide-deck.html +0 -592
  198. package/skills/doc-gist/references/examples/10-svg-illustrations.html +0 -492
  199. package/skills/doc-gist/references/examples/11-status-report.html +0 -528
  200. package/skills/doc-gist/references/examples/12-incident-report.html +0 -596
  201. package/skills/doc-gist/references/examples/13-flowchart-diagram.html +0 -395
  202. package/skills/doc-gist/references/examples/14-research-feature-explainer.html +0 -381
  203. package/skills/doc-gist/references/examples/15-research-concept-explainer.html +0 -368
  204. package/skills/doc-gist/references/examples/16-implementation-plan.html +0 -702
  205. package/skills/doc-gist/references/examples/17-pr-writeup.html +0 -595
  206. package/skills/doc-gist/references/examples/18-editor-triage-board.html +0 -573
  207. package/skills/doc-gist/references/examples/19-editor-feature-flags.html +0 -663
  208. package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +0 -722
  209. package/skills/doc-gist/references/examples/21-decision-signoff.html +0 -546
  210. package/skills/doc-gist/references/examples/CLAUDE.md +0 -25
  211. package/skills/doc-gist/references/examples/README.md +0 -5
  212. package/skills/doc-gist/scripts/CLAUDE.md +0 -27
  213. package/skills/doc-gist/scripts/doc_gist_scripts_constants/CLAUDE.md +0 -10
  214. package/skills/doc-gist/scripts/doc_gist_scripts_constants/gist_upload_constants.py +0 -16
  215. package/skills/doc-gist/scripts/gist_upload.py +0 -177
  216. package/skills/doc-gist/scripts/test_gist_upload.py +0 -51
  217. /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>