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,605 +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">
6
- <title>Birchline — Card Variant Matrix</title>
7
- <style>
8
- :root {
9
- --ivory: #FAF9F5;
10
- --slate: #141413;
11
- --clay: #D97757;
12
- --oat: #E3DACC;
13
- --olive: #788C5D;
14
- --gray-100: #F0EEE6;
15
- --gray-300: #D1CFC5;
16
- --gray-500: #87867F;
17
- --gray-700: #3D3D3A;
18
- --white: #FFFFFF;
19
-
20
- --serif: ui-serif, Georgia, serif;
21
- --sans: system-ui, -apple-system, sans-serif;
22
- --mono: ui-monospace, 'SF Mono', Menlo, monospace;
23
-
24
- /* live-controlled tokens */
25
- --card-pad: 20px;
26
- --card-border: 1.5px solid var(--gray-300);
27
- --card-shadow: 0 4px 14px rgba(20, 20, 19, 0.08);
28
- }
29
-
30
- * { box-sizing: border-box; }
31
-
32
- body {
33
- margin: 0;
34
- background: var(--ivory);
35
- color: var(--slate);
36
- font-family: var(--sans);
37
- font-size: 15px;
38
- line-height: 1.5;
39
- -webkit-font-smoothing: antialiased;
40
- }
41
-
42
- .page {
43
- max-width: 1100px;
44
- margin: 0 auto;
45
- padding: 0 28px 80px;
46
- }
47
-
48
- header {
49
- padding: 48px 0 20px;
50
- }
51
- header h1 {
52
- font-family: var(--serif);
53
- font-weight: 500;
54
- font-size: 36px;
55
- letter-spacing: -0.01em;
56
- margin: 0 0 6px;
57
- }
58
- header p {
59
- color: var(--gray-500);
60
- font-size: 14px;
61
- margin: 0;
62
- max-width: 640px;
63
- }
64
-
65
- /* ---------- Toolbar ---------- */
66
- .toolbar {
67
- position: sticky;
68
- top: 0;
69
- z-index: 10;
70
- display: flex;
71
- flex-wrap: wrap;
72
- align-items: center;
73
- gap: 28px;
74
- padding: 16px 20px;
75
- margin: 24px 0 36px;
76
- background: var(--white);
77
- border: 1.5px solid var(--gray-300);
78
- border-radius: 12px;
79
- }
80
- .control {
81
- display: flex;
82
- align-items: center;
83
- gap: 10px;
84
- }
85
- .control-label {
86
- font-family: var(--mono);
87
- font-size: 12px;
88
- color: var(--gray-700);
89
- }
90
- .control-value {
91
- font-family: var(--mono);
92
- font-size: 12px;
93
- color: var(--gray-500);
94
- min-width: 36px;
95
- }
96
-
97
- input[type="range"] {
98
- appearance: none;
99
- width: 140px;
100
- height: 4px;
101
- background: var(--gray-300);
102
- border-radius: 2px;
103
- outline: none;
104
- }
105
- input[type="range"]::-webkit-slider-thumb {
106
- appearance: none;
107
- width: 16px; height: 16px;
108
- background: var(--clay);
109
- border-radius: 50%;
110
- cursor: pointer;
111
- }
112
- input[type="range"]::-moz-range-thumb {
113
- width: 16px; height: 16px;
114
- background: var(--clay);
115
- border: none;
116
- border-radius: 50%;
117
- cursor: pointer;
118
- }
119
-
120
- .radio-group {
121
- display: inline-flex;
122
- border: 1.5px solid var(--gray-300);
123
- border-radius: 8px;
124
- overflow: hidden;
125
- }
126
- .radio-group label {
127
- padding: 6px 12px;
128
- font-size: 13px;
129
- cursor: pointer;
130
- user-select: none;
131
- color: var(--gray-700);
132
- border-right: 1px solid var(--gray-300);
133
- }
134
- .radio-group label:last-child { border-right: none; }
135
- .radio-group input { display: none; }
136
- .radio-group input:checked + span {
137
- color: var(--slate);
138
- }
139
- .radio-group label:has(input:checked) {
140
- background: var(--gray-100);
141
- }
142
-
143
- .check {
144
- display: inline-flex;
145
- align-items: center;
146
- gap: 8px;
147
- font-size: 13px;
148
- cursor: pointer;
149
- user-select: none;
150
- }
151
- .check input {
152
- appearance: none;
153
- width: 16px; height: 16px;
154
- border: 1.5px solid var(--gray-300);
155
- border-radius: 4px;
156
- margin: 0;
157
- cursor: pointer;
158
- position: relative;
159
- }
160
- .check input:checked {
161
- background: var(--clay);
162
- border-color: var(--clay);
163
- }
164
- .check input:checked::after {
165
- content: "";
166
- position: absolute;
167
- left: 4px; top: 0;
168
- width: 4px; height: 9px;
169
- border: solid var(--white);
170
- border-width: 0 2px 2px 0;
171
- transform: rotate(45deg);
172
- }
173
-
174
- /* ---------- Grid ---------- */
175
- .grid {
176
- display: grid;
177
- grid-template-columns: repeat(3, 1fr);
178
- gap: 28px;
179
- }
180
- @media (max-width: 960px) {
181
- .grid { grid-template-columns: repeat(2, 1fr); }
182
- }
183
- @media (max-width: 640px) {
184
- .grid { grid-template-columns: 1fr; }
185
- }
186
-
187
- .cell {}
188
- .variant-label {
189
- display: inline-flex;
190
- align-items: center;
191
- height: 22px;
192
- padding: 0 9px;
193
- font-family: var(--mono);
194
- font-size: 11px;
195
- font-weight: 500;
196
- color: var(--gray-700);
197
- background: var(--gray-100);
198
- border-radius: 999px;
199
- margin-bottom: 10px;
200
- }
201
- .variant-note {
202
- font-size: 12px;
203
- color: var(--gray-500);
204
- margin-top: 10px;
205
- }
206
-
207
- /* ---------- Card base ---------- */
208
- .card {
209
- border-radius: 12px;
210
- padding: var(--card-pad);
211
- transition: padding 0.15s ease, box-shadow 0.15s ease, border 0.15s ease;
212
- cursor: pointer;
213
- }
214
- .card:hover { outline: 2px solid var(--clay); outline-offset: 2px; }
215
-
216
- .card-head {
217
- display: flex;
218
- align-items: center;
219
- gap: 12px;
220
- margin-bottom: 12px;
221
- }
222
- .avatar {
223
- width: 36px; height: 36px;
224
- border-radius: 50%;
225
- background: var(--oat);
226
- flex-shrink: 0;
227
- display: flex;
228
- align-items: center;
229
- justify-content: center;
230
- font-size: 13px;
231
- font-weight: 600;
232
- color: var(--gray-700);
233
- }
234
- .card-titles { min-width: 0; }
235
- .card-title {
236
- font-family: var(--serif);
237
- font-size: 17px;
238
- font-weight: 500;
239
- margin: 0 0 2px;
240
- line-height: 1.3;
241
- }
242
- .card-sub {
243
- font-size: 13px;
244
- color: var(--gray-500);
245
- margin: 0;
246
- white-space: nowrap;
247
- overflow: hidden;
248
- text-overflow: ellipsis;
249
- }
250
- .chips {
251
- display: flex;
252
- gap: 6px;
253
- margin-bottom: 14px;
254
- }
255
- .chip {
256
- display: inline-flex;
257
- align-items: center;
258
- height: 20px;
259
- padding: 0 8px;
260
- font-size: 11px;
261
- font-weight: 500;
262
- border-radius: 999px;
263
- background: var(--gray-100);
264
- color: var(--gray-700);
265
- }
266
- .chip.olive { background: rgba(120,140,93,0.16); color: var(--olive); }
267
- .ghost-btn {
268
- display: inline-flex;
269
- align-items: center;
270
- height: 30px;
271
- padding: 0 12px;
272
- font-size: 13px;
273
- font-weight: 500;
274
- color: var(--gray-700);
275
- background: transparent;
276
- border: 1.5px solid var(--gray-300);
277
- border-radius: 8px;
278
- cursor: pointer;
279
- }
280
- .ghost-btn:hover { background: var(--gray-100); }
281
-
282
- /* ---------- Variant treatments ---------- */
283
- .v-flat {
284
- background: var(--white);
285
- border: none;
286
- box-shadow: none;
287
- }
288
- .v-outlined {
289
- background: var(--white);
290
- border: var(--card-border);
291
- box-shadow: none;
292
- }
293
- .v-elevated {
294
- background: var(--white);
295
- border: none;
296
- box-shadow: var(--card-shadow);
297
- }
298
- .v-stripe {
299
- background: var(--white);
300
- border: var(--card-border);
301
- box-shadow: none;
302
- position: relative;
303
- overflow: hidden;
304
- }
305
- .v-stripe::before {
306
- content: "";
307
- position: absolute;
308
- left: 0; right: 0; top: 0;
309
- height: 4px;
310
- background: var(--clay);
311
- }
312
- .v-inset {
313
- background: var(--oat);
314
- border: none;
315
- box-shadow: none;
316
- }
317
- .v-inset .chip { background: rgba(255,255,255,0.6); }
318
- .v-inset .ghost-btn { border-color: rgba(20,20,19,0.15); }
319
- .v-inset .avatar { background: var(--white); }
320
-
321
- .v-horizontal {
322
- background: var(--white);
323
- border: var(--card-border);
324
- box-shadow: none;
325
- display: flex;
326
- align-items: center;
327
- gap: 14px;
328
- }
329
- .v-horizontal .card-head { margin: 0; flex: 1; min-width: 0; }
330
- .v-horizontal .chips { margin: 0; }
331
- .v-horizontal .card-sub { display: none; }
332
- .v-horizontal .ghost-btn { flex-shrink: 0; }
333
-
334
- /* ---------- Snippet panel ---------- */
335
- .snippet-panel {
336
- margin-top: 40px;
337
- border: 1.5px solid var(--gray-300);
338
- border-radius: 12px;
339
- overflow: hidden;
340
- }
341
- .snippet-head {
342
- padding: 10px 16px;
343
- font-family: var(--mono);
344
- font-size: 12px;
345
- color: var(--gray-500);
346
- background: var(--gray-100);
347
- border-bottom: 1px solid var(--gray-300);
348
- }
349
- pre#snippet {
350
- margin: 0;
351
- padding: 20px;
352
- background: var(--slate);
353
- color: var(--ivory);
354
- font-family: var(--mono);
355
- font-size: 13px;
356
- line-height: 1.6;
357
- overflow-x: auto;
358
- min-height: 120px;
359
- }
360
- </style>
361
- </head>
362
- <body>
363
- <div class="page">
364
-
365
- <header>
366
- <h1>Card variant matrix</h1>
367
- <p>Six structural treatments of the Birchline <code style="font-family:var(--mono);font-size:13px">&lt;Card /&gt;</code> component. Adjust density and emphasis with the controls, hover a variant to see its prop combo.</p>
368
- </header>
369
-
370
- <!-- ---------- Toolbar ---------- -->
371
- <div class="toolbar">
372
- <div class="control">
373
- <span class="control-label">Padding</span>
374
- <input id="ctl-pad" type="range" min="12" max="32" value="20" step="2">
375
- <span class="control-value" id="pad-out">20px</span>
376
- </div>
377
-
378
- <div class="control">
379
- <span class="control-label">Border</span>
380
- <div class="radio-group">
381
- <label><input type="radio" name="border" value="none"><span>none</span></label>
382
- <label><input type="radio" name="border" value="hairline" checked><span>hairline</span></label>
383
- <label><input type="radio" name="border" value="solid"><span>solid</span></label>
384
- </div>
385
- </div>
386
-
387
- <div class="control">
388
- <label class="check">
389
- <input id="ctl-shadow" type="checkbox" checked>
390
- Show shadow
391
- </label>
392
- </div>
393
- </div>
394
-
395
- <!-- ---------- Grid ---------- -->
396
- <div class="grid" id="grid">
397
-
398
- <!-- A: Flat -->
399
- <div class="cell">
400
- <span class="variant-label">A &middot; Flat</span>
401
- <div class="card v-flat"
402
- data-snippet='<Card variant="flat" padding={PAD}>
403
- <Card.Header avatar title="Weekly planning" subtitle="12 tasks &middot; due Friday" />
404
- <Card.Meta tags={["Q2", "Roadmap"]} />
405
- <Button variant="ghost">Open</Button>
406
- </Card>'>
407
- <div class="card-head">
408
- <div class="avatar">WP</div>
409
- <div class="card-titles">
410
- <p class="card-title">Weekly planning</p>
411
- <p class="card-sub">12 tasks &middot; due Friday</p>
412
- </div>
413
- </div>
414
- <div class="chips">
415
- <span class="chip">Q2</span>
416
- <span class="chip olive">Roadmap</span>
417
- </div>
418
- <button class="ghost-btn">Open</button>
419
- </div>
420
- <p class="variant-note">best for: dense lists on tinted backgrounds</p>
421
- </div>
422
-
423
- <!-- B: Outlined -->
424
- <div class="cell">
425
- <span class="variant-label">B &middot; Outlined</span>
426
- <div class="card v-outlined"
427
- data-snippet='<Card variant="outlined" padding={PAD} border="BORDER">
428
- <Card.Header avatar title="Weekly planning" subtitle="12 tasks &middot; due Friday" />
429
- <Card.Meta tags={["Q2", "Roadmap"]} />
430
- <Button variant="ghost">Open</Button>
431
- </Card>'>
432
- <div class="card-head">
433
- <div class="avatar">WP</div>
434
- <div class="card-titles">
435
- <p class="card-title">Weekly planning</p>
436
- <p class="card-sub">12 tasks &middot; due Friday</p>
437
- </div>
438
- </div>
439
- <div class="chips">
440
- <span class="chip">Q2</span>
441
- <span class="chip olive">Roadmap</span>
442
- </div>
443
- <button class="ghost-btn">Open</button>
444
- </div>
445
- <p class="variant-note">best for: default content cards on ivory</p>
446
- </div>
447
-
448
- <!-- C: Elevated -->
449
- <div class="cell">
450
- <span class="variant-label">C &middot; Elevated</span>
451
- <div class="card v-elevated"
452
- data-snippet='<Card variant="elevated" padding={PAD} shadow="md">
453
- <Card.Header avatar title="Weekly planning" subtitle="12 tasks &middot; due Friday" />
454
- <Card.Meta tags={["Q2", "Roadmap"]} />
455
- <Button variant="ghost">Open</Button>
456
- </Card>'>
457
- <div class="card-head">
458
- <div class="avatar">WP</div>
459
- <div class="card-titles">
460
- <p class="card-title">Weekly planning</p>
461
- <p class="card-sub">12 tasks &middot; due Friday</p>
462
- </div>
463
- </div>
464
- <div class="chips">
465
- <span class="chip">Q2</span>
466
- <span class="chip olive">Roadmap</span>
467
- </div>
468
- <button class="ghost-btn">Open</button>
469
- </div>
470
- <p class="variant-note">best for: draggable items, popovers</p>
471
- </div>
472
-
473
- <!-- D: Accent stripe -->
474
- <div class="cell">
475
- <span class="variant-label">D &middot; Accent stripe</span>
476
- <div class="card v-stripe"
477
- data-snippet='<Card variant="outlined" accent="clay" padding={PAD} border="BORDER">
478
- <Card.Header avatar title="Weekly planning" subtitle="12 tasks &middot; due Friday" />
479
- <Card.Meta tags={["Q2", "Roadmap"]} />
480
- <Button variant="ghost">Open</Button>
481
- </Card>'>
482
- <div class="card-head">
483
- <div class="avatar">WP</div>
484
- <div class="card-titles">
485
- <p class="card-title">Weekly planning</p>
486
- <p class="card-sub">12 tasks &middot; due Friday</p>
487
- </div>
488
- </div>
489
- <div class="chips">
490
- <span class="chip">Q2</span>
491
- <span class="chip olive">Roadmap</span>
492
- </div>
493
- <button class="ghost-btn">Open</button>
494
- </div>
495
- <p class="variant-note">best for: pinned or priority items</p>
496
- </div>
497
-
498
- <!-- E: Inset / filled -->
499
- <div class="cell">
500
- <span class="variant-label">E &middot; Inset</span>
501
- <div class="card v-inset"
502
- data-snippet='<Card variant="filled" tone="oat" padding={PAD}>
503
- <Card.Header avatar title="Weekly planning" subtitle="12 tasks &middot; due Friday" />
504
- <Card.Meta tags={["Q2", "Roadmap"]} />
505
- <Button variant="ghost">Open</Button>
506
- </Card>'>
507
- <div class="card-head">
508
- <div class="avatar">WP</div>
509
- <div class="card-titles">
510
- <p class="card-title">Weekly planning</p>
511
- <p class="card-sub">12 tasks &middot; due Friday</p>
512
- </div>
513
- </div>
514
- <div class="chips">
515
- <span class="chip">Q2</span>
516
- <span class="chip olive">Roadmap</span>
517
- </div>
518
- <button class="ghost-btn">Open</button>
519
- </div>
520
- <p class="variant-note">best for: nested cards inside white panels</p>
521
- </div>
522
-
523
- <!-- F: Horizontal / compact -->
524
- <div class="cell">
525
- <span class="variant-label">F &middot; Horizontal</span>
526
- <div class="card v-horizontal"
527
- data-snippet='<Card variant="outlined" layout="row" padding={PAD} border="BORDER">
528
- <Card.Header avatar title="Weekly planning" />
529
- <Card.Meta tags={["Q2", "Roadmap"]} />
530
- <Button variant="ghost">Open</Button>
531
- </Card>'>
532
- <div class="card-head">
533
- <div class="avatar">WP</div>
534
- <div class="card-titles">
535
- <p class="card-title">Weekly planning</p>
536
- <p class="card-sub">12 tasks &middot; due Friday</p>
537
- </div>
538
- </div>
539
- <div class="chips">
540
- <span class="chip">Q2</span>
541
- <span class="chip olive">Roadmap</span>
542
- </div>
543
- <button class="ghost-btn">Open</button>
544
- </div>
545
- <p class="variant-note">best for: compact row lists, sidebars</p>
546
- </div>
547
-
548
- </div>
549
-
550
- <!-- ---------- Snippet ---------- -->
551
- <div class="snippet-panel">
552
- <div class="snippet-head">JSX &mdash; hover a variant above</div>
553
- <pre id="snippet">// hover a card to preview its props</pre>
554
- </div>
555
-
556
- </div>
557
-
558
- <script>
559
- (function () {
560
- var root = document.documentElement;
561
- var pad = document.getElementById('ctl-pad');
562
- var padOut = document.getElementById('pad-out');
563
- var shadow = document.getElementById('ctl-shadow');
564
- var snippet = document.getElementById('snippet');
565
- var currentBorder = 'hairline';
566
-
567
- var borderMap = {
568
- none: 'none',
569
- hairline: '1px solid var(--gray-300)',
570
- solid: '1.5px solid var(--gray-300)'
571
- };
572
-
573
- function applyPad() {
574
- root.style.setProperty('--card-pad', pad.value + 'px');
575
- padOut.textContent = pad.value + 'px';
576
- }
577
- function applyBorder(v) {
578
- currentBorder = v;
579
- root.style.setProperty('--card-border', borderMap[v]);
580
- }
581
- function applyShadow() {
582
- root.style.setProperty('--card-shadow',
583
- shadow.checked ? '0 4px 14px rgba(20,20,19,0.08)' : 'none');
584
- }
585
-
586
- pad.addEventListener('input', applyPad);
587
- shadow.addEventListener('change', applyShadow);
588
- document.querySelectorAll('input[name="border"]').forEach(function (r) {
589
- r.addEventListener('change', function () { applyBorder(r.value); });
590
- });
591
-
592
- document.querySelectorAll('.card').forEach(function (card) {
593
- card.addEventListener('mouseenter', function () {
594
- var raw = card.getAttribute('data-snippet') || '';
595
- snippet.textContent = raw
596
- .replace(/PAD/g, pad.value)
597
- .replace(/BORDER/g, currentBorder);
598
- });
599
- });
600
-
601
- applyPad(); applyBorder('hairline'); applyShadow();
602
- })();
603
- </script>
604
- </body>
605
- </html>