sheleg-design-skill 1.8.0 → 1.10.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 (148) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/README.md +39 -18
  3. package/bin/cli.js +17 -9
  4. package/cursor/rules/sheleg-design.mdc +43 -2
  5. package/kits/atrium/src/styles.css +1 -2
  6. package/kits/blueprint/.design-sync/config.json +14 -0
  7. package/kits/blueprint/.design-sync/conventions.md +52 -0
  8. package/kits/blueprint/README.md +14 -0
  9. package/kits/blueprint/package.json +29 -0
  10. package/kits/blueprint/src/Button.md +5 -0
  11. package/kits/blueprint/src/Button.tsx +33 -0
  12. package/kits/blueprint/src/Card.md +5 -0
  13. package/kits/blueprint/src/Card.tsx +24 -0
  14. package/kits/blueprint/src/Chip.md +5 -0
  15. package/kits/blueprint/src/Chip.tsx +25 -0
  16. package/kits/blueprint/src/CodeLine.md +14 -0
  17. package/kits/blueprint/src/CodeLine.tsx +28 -0
  18. package/kits/blueprint/src/GridField.md +14 -0
  19. package/kits/blueprint/src/GridField.tsx +23 -0
  20. package/kits/blueprint/src/Heading.md +5 -0
  21. package/kits/blueprint/src/Heading.tsx +19 -0
  22. package/kits/blueprint/src/RegistrationMarks.md +17 -0
  23. package/kits/blueprint/src/RegistrationMarks.tsx +34 -0
  24. package/kits/blueprint/src/Rule.md +5 -0
  25. package/kits/blueprint/src/Rule.tsx +18 -0
  26. package/kits/blueprint/src/RuledColumn.md +17 -0
  27. package/kits/blueprint/src/RuledColumn.tsx +25 -0
  28. package/kits/blueprint/src/Stat.md +5 -0
  29. package/kits/blueprint/src/Stat.tsx +17 -0
  30. package/kits/blueprint/src/index.ts +23 -0
  31. package/kits/blueprint/src/styles.css +233 -0
  32. package/kits/blueprint/tsconfig.json +15 -0
  33. package/kits/editorial-luxury/src/styles.css +5 -2
  34. package/kits/field-notes/src/styles.css +11 -2
  35. package/kits/instrument-console/src/styles.css +4 -1
  36. package/kits/maquette/.design-sync/config.json +14 -0
  37. package/kits/maquette/.design-sync/conventions.md +54 -0
  38. package/kits/maquette/README.md +14 -0
  39. package/kits/maquette/package.json +29 -0
  40. package/kits/maquette/src/AquaPill.md +15 -0
  41. package/kits/maquette/src/AquaPill.tsx +30 -0
  42. package/kits/maquette/src/Button.md +5 -0
  43. package/kits/maquette/src/Button.tsx +33 -0
  44. package/kits/maquette/src/Card.md +5 -0
  45. package/kits/maquette/src/Card.tsx +24 -0
  46. package/kits/maquette/src/Chip.md +5 -0
  47. package/kits/maquette/src/Chip.tsx +25 -0
  48. package/kits/maquette/src/CliLine.md +14 -0
  49. package/kits/maquette/src/CliLine.tsx +27 -0
  50. package/kits/maquette/src/Heading.md +5 -0
  51. package/kits/maquette/src/Heading.tsx +19 -0
  52. package/kits/maquette/src/LeaderLabel.md +17 -0
  53. package/kits/maquette/src/LeaderLabel.tsx +24 -0
  54. package/kits/maquette/src/ModelBlock.md +21 -0
  55. package/kits/maquette/src/ModelBlock.tsx +39 -0
  56. package/kits/maquette/src/Rule.md +5 -0
  57. package/kits/maquette/src/Rule.tsx +18 -0
  58. package/kits/maquette/src/Stat.md +5 -0
  59. package/kits/maquette/src/Stat.tsx +17 -0
  60. package/kits/maquette/src/index.ts +24 -0
  61. package/kits/maquette/src/styles.css +253 -0
  62. package/kits/maquette/tsconfig.json +15 -0
  63. package/kits/orchard/src/styles.css +6 -1
  64. package/kits/prism/.design-sync/config.json +14 -0
  65. package/kits/prism/.design-sync/conventions.md +50 -0
  66. package/kits/prism/README.md +14 -0
  67. package/kits/prism/package.json +29 -0
  68. package/kits/prism/src/BenchmarkRow.md +13 -0
  69. package/kits/prism/src/BenchmarkRow.tsx +25 -0
  70. package/kits/prism/src/Button.md +5 -0
  71. package/kits/prism/src/Button.tsx +33 -0
  72. package/kits/prism/src/Card.md +5 -0
  73. package/kits/prism/src/Card.tsx +24 -0
  74. package/kits/prism/src/Chip.md +5 -0
  75. package/kits/prism/src/Chip.tsx +25 -0
  76. package/kits/prism/src/Heading.md +5 -0
  77. package/kits/prism/src/Heading.tsx +19 -0
  78. package/kits/prism/src/InstallLine.md +16 -0
  79. package/kits/prism/src/InstallLine.tsx +29 -0
  80. package/kits/prism/src/RepoBadge.md +13 -0
  81. package/kits/prism/src/RepoBadge.tsx +25 -0
  82. package/kits/prism/src/Rule.md +5 -0
  83. package/kits/prism/src/Rule.tsx +18 -0
  84. package/kits/prism/src/Stat.md +5 -0
  85. package/kits/prism/src/Stat.tsx +17 -0
  86. package/kits/prism/src/Wash.md +17 -0
  87. package/kits/prism/src/Wash.tsx +23 -0
  88. package/kits/prism/src/index.ts +24 -0
  89. package/kits/prism/src/styles.css +223 -0
  90. package/kits/prism/tsconfig.json +15 -0
  91. package/kits/showroom/.design-sync/config.json +14 -0
  92. package/kits/showroom/.design-sync/conventions.md +50 -0
  93. package/kits/showroom/README.md +14 -0
  94. package/kits/showroom/package.json +29 -0
  95. package/kits/showroom/src/Button.md +5 -0
  96. package/kits/showroom/src/Button.tsx +33 -0
  97. package/kits/showroom/src/Card.md +5 -0
  98. package/kits/showroom/src/Card.tsx +24 -0
  99. package/kits/showroom/src/Chip.md +5 -0
  100. package/kits/showroom/src/Chip.tsx +25 -0
  101. package/kits/showroom/src/ColumnHeader.md +15 -0
  102. package/kits/showroom/src/ColumnHeader.tsx +33 -0
  103. package/kits/showroom/src/DataRow.md +14 -0
  104. package/kits/showroom/src/DataRow.tsx +31 -0
  105. package/kits/showroom/src/Heading.md +5 -0
  106. package/kits/showroom/src/Heading.tsx +19 -0
  107. package/kits/showroom/src/Rule.md +5 -0
  108. package/kits/showroom/src/Rule.tsx +18 -0
  109. package/kits/showroom/src/Specimen.md +26 -0
  110. package/kits/showroom/src/Specimen.tsx +44 -0
  111. package/kits/showroom/src/Stat.md +5 -0
  112. package/kits/showroom/src/Stat.tsx +17 -0
  113. package/kits/showroom/src/StatusChip.md +19 -0
  114. package/kits/showroom/src/StatusChip.tsx +26 -0
  115. package/kits/showroom/src/index.ts +23 -0
  116. package/kits/showroom/src/styles.css +249 -0
  117. package/kits/showroom/tsconfig.json +15 -0
  118. package/kits/workbench/src/styles.css +1 -1
  119. package/package.json +4 -4
  120. package/plugins/sheleg-design/.claude-plugin/plugin.json +2 -2
  121. package/plugins/sheleg-design/commands/sheleg-design.md +24 -8
  122. package/plugins/sheleg-design/skills/sheleg-design/DESIGN_SYNC_BRIDGE.md +4 -3
  123. package/plugins/sheleg-design/skills/sheleg-design/MOTION_DOCTRINE.md +10 -2
  124. package/plugins/sheleg-design/skills/sheleg-design/SHELEG_DESIGN.md +16 -7
  125. package/plugins/sheleg-design/skills/sheleg-design/SKILL.md +66 -21
  126. package/plugins/sheleg-design/skills/sheleg-design/styles/STYLE_PACK_TEMPLATE.md +5 -0
  127. package/plugins/sheleg-design/skills/sheleg-design/styles/atrium.md +36 -4
  128. package/plugins/sheleg-design/skills/sheleg-design/styles/blueprint.md +345 -0
  129. package/plugins/sheleg-design/skills/sheleg-design/styles/briefing-room.md +16 -6
  130. package/plugins/sheleg-design/skills/sheleg-design/styles/cyclorama.md +11 -0
  131. package/plugins/sheleg-design/skills/sheleg-design/styles/editorial-luxury.md +18 -7
  132. package/plugins/sheleg-design/skills/sheleg-design/styles/field-notes.md +35 -6
  133. package/plugins/sheleg-design/skills/sheleg-design/styles/instrument-console.md +22 -0
  134. package/plugins/sheleg-design/skills/sheleg-design/styles/maquette.md +325 -0
  135. package/plugins/sheleg-design/skills/sheleg-design/styles/orchard.md +20 -6
  136. package/plugins/sheleg-design/skills/sheleg-design/styles/prism.md +301 -0
  137. package/plugins/sheleg-design/skills/sheleg-design/styles/showroom.md +308 -0
  138. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/atrium.css +1 -1
  139. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/blueprint.css +143 -0
  140. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/editorial-luxury.css +5 -1
  141. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/field-notes.css +11 -1
  142. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/instrument-console.css +4 -0
  143. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/maquette.css +154 -0
  144. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/orchard.css +6 -0
  145. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/prism.css +138 -0
  146. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/showroom.css +160 -0
  147. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/workbench.css +1 -1
  148. package/plugins/sheleg-design/skills/sheleg-design/styles/workbench.md +37 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,177 @@ All notable changes to this project are documented in this file. The format
4
4
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions
5
5
  follow [SemVer](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.10.0] - 2026-08-10
8
+
9
+ A fresh-eyes audit of the whole skill, and the finding is the green: at 1.9.0 all
10
+ three gates passed — 1270 / 412 / 224 — while the skill told a reading agent
11
+ there were six style packs, handed the chart layer a token ramp no pack defines,
12
+ and stated thirteen contrast ratios that are wrong.
13
+
14
+ Full report with every `file:line`, and the reproductions:
15
+ [`docs/audit/2026-08-10-skill-audit.md`](./docs/audit/2026-08-10-skill-audit.md).
16
+
17
+ ### Fixed — what an agent was told that was not true
18
+
19
+ - **The `dataviz` handoff named tokens no pack defines.** `SKILL.md` promised a
20
+ ramp `--accent-tint … --accent-deep`: `--accent-tint` exists in **one** pack of
21
+ twelve, `--accent-deep` in three, and **no pack has both**. It promised a
22
+ status set of `--good` / `--warning` / `--danger` that seven packs lack and
23
+ two have no version of at all. An undefined custom property does not error —
24
+ the declaration goes invalid at computed-value time and the property silently
25
+ inherits — so the agent follows the instruction exactly and the page is wrong.
26
+ The table is now written by role, and the non-uniform mappings are named.
27
+ - **Thirteen stated contrast ratios, recomputed and corrected.** `blueprint`'s
28
+ ratio column is headed ``On `--bg` `` and every number in it was computed
29
+ against pure white (`--ink` 17.74 → **17.15**, `--accent` 7.53 → **7.28**,
30
+ pure black 21 → **20.31**). `prism` claimed ink "≥18:1 over all four stops"
31
+ three times; it is **15.85–16.82** — 18.95 is ink on plain white, carried onto
32
+ the wash. Also `showroom` 15.9 → **15.35** and 7.7 → **7.08**, `maquette` 5.0 →
33
+ **5.62** and 13.9 → **13.57**, `editorial-luxury` 6.1 → **6.93**, `workbench`
34
+ 5.0 → **4.57**. None crossed a floor; all were presented as measured.
35
+ - **Two packs justified one accent by a "symmetry" that is a mathematical
36
+ identity.** WCAG contrast is symmetric for every pair by definition. In
37
+ `showroom`, whose field is white, the sentence stated one measurement twice; in
38
+ `blueprint`, whose field is not, the two directions genuinely differ and the
39
+ pack asserted one number for both.
40
+ - **`atrium` prescribed `transition: padding-top .2s` on a sticky header** — a
41
+ layout property, transitioned, on scroll: the exact form `MOTION_DOCTRINE.md`
42
+ forbids, shipped inside the bundle that ships the ban.
43
+ - **`field-notes`' radius rule, its worked example and its token layer were three
44
+ different systems.** "Subtract the padding … `12 - 12 ≈ 7.2`" — subtraction
45
+ gives 0; the token layer uses `calc(var(--radius) * 0.6)`.
46
+ - **`blueprint`'s Components and Hero instructed the violation its own Signature
47
+ element section names** (registration marks on both CTAs). `test/scenarios.md`
48
+ recorded this as "fixed in the same run"; only half of it had landed.
49
+ - **`atrium` said three shadows exist**; its token layer defines four.
50
+ - **The colour-blindness ban was copy-pasted into six packs**, asserting a
51
+ measurement across "several pairs" in packs owning one status colour or none —
52
+ and naming four states as if the pack supplied them, which is an invitation to
53
+ invent a hue. Rewritten for `orchard`, `editorial-luxury` and `briefing-room`.
54
+ - **`MOTION_DOCTRINE.md` §5 over-banned**, forbidding everything outside four
55
+ properties while §2 prescribes an ease for colour changes. The ban is on
56
+ layout, which is what its own rationale says.
57
+ - **ADR-0001 named a pack that never existed** (`lecture-hall`; the pack that
58
+ shipped from graphify.com is `field-notes`). The decision stands; the example
59
+ was written on a branch that never merged.
60
+
61
+ ### Added — the half-library nobody declared
62
+
63
+ Six of twelve packs carry `## Components`, `## Hero`, `## Responsive` and
64
+ `## Signature element`; six do not, and nothing said which. Every pack now
65
+ declares **`Contract: core` or `Contract: widened`** above its Register, a core
66
+ pack states what it leaves the reader to decide, the `SKILL.md` routing table
67
+ marks it, and a check enforces the declaration against the headings present.
68
+
69
+ ### Added — six checks, each watched failing on a planted defect
70
+
71
+ Counted claims (whitespace-normalised: the README's "six locked style packs" was
72
+ split across a line break) · exhaustive pack enumerations in both manifests, the
73
+ slash command, the CLI, the README and the Cursor rule · one name for the pack
74
+ contract · the `Contract:` declaration · the core role vocabulary (`--bg`,
75
+ `--ink`, and an accent role every pack resolves) · and **every stated contrast
76
+ ratio, recomputed from the token layer**.
77
+
78
+ The ratio check is scoped to claims whose base the document declares — a column
79
+ headed ``On `--bg` ``, an `on/over --token` phrase, or an `--on-X` name. A first
80
+ draft that inferred the partner produced 22 false positives out of 40.
81
+
82
+ ### Fixed — three gates that could not fail
83
+
84
+ - **Deleting requirements made two gates quieter, and green.** Stripping a pack's
85
+ four widened headings took `validate.py` 1270 → 1269 and `sloplint.py` 224 →
86
+ 223, both exit 0. **Ratchet floors** now live in `test/floors.json` and are
87
+ enforced by all three.
88
+ - **One decoy comment disabled a slop-lint ban for a whole file, permanently.**
89
+ The check took the first match only and `continue`d past a nearby negation
90
+ word, so the counter fell and later occurrences went unexamined. Suppression is
91
+ now per occurrence, and ban-quoting sections are exempted by heading.
92
+ - **`validate.py --self-test` printed OK for a self-test that did not exist** —
93
+ the same defect the 2026-08-05 retrospective recorded in `validate_palette.py`.
94
+ All three scripts now exit 2 on an unknown argument, and `validate.py` has a
95
+ real self-test: six planted defects, run against a copy of the tree.
96
+ - **The slop lint read only fenced code blocks**, and no style pack contains one —
97
+ so all twelve packs, `SKILL.md`, both bridges and the AI patterns were never
98
+ linted. It now reads the inline CSS the packs prescribe in prose.
99
+ - **`npm test` and both workflows now run every gate and every self-test.** The
100
+ release path was gated on one of three.
101
+
102
+ ### Fixed — stale counts and reach
103
+
104
+ "six locked style packs" and "all six kits" (twelve), "T1–T7" (T1–T19), "Three
105
+ packs extracted" (eight), the pack contract called nine / ten / thirteen in five
106
+ places at once — one of which told an author to ship nine headings, which the
107
+ gate then passed. `plugin.json`, `marketplace.json` and the `/sheleg-design`
108
+ command named three packs of twelve, so nine could not be asked for by name.
109
+ `MOTION_DOCTRINE.md`, marked REQUIRED, appeared on no install surface: it is now
110
+ in the README table, the CLI help and banner, the slash command, and the Cursor
111
+ rule — which gains the whole doctrine in condensed form.
112
+
113
+ Gates: **1364 / 469 / 320**, from 1270 / 412 / 224.
114
+
115
+ ## [1.9.0] - 2026-08-09
116
+
117
+ Four style packs, taking the library from eight to twelve — and a fix to the
118
+ thing that would have made twelve worse than eight.
119
+
120
+ Extracted from four live references on 2026-08-09. Three of them sell vector
121
+ databases and none of them collapse into each other; two are the same company's
122
+ project page and product page, and they share a type stack and nothing else.
123
+
124
+ ### Added
125
+
126
+ - **`showroom`** — from [attio.com](https://attio.com/). A white gallery where
127
+ one real product surface is the exhibit, under a **seven-layer shadow**. The
128
+ reference declares its palette in **CIE Lab**, which this repo's palette gate
129
+ cannot parse; every value was converted by painting it into a canvas and
130
+ reading the sRGB bytes back — the browser's conversion, not ours.
131
+ - **`blueprint`** — from [pinecone.io](https://www.pinecone.io/). A drawing
132
+ sheet: a 32px grid, ruled column boundaries, corner registration marks, one
133
+ electric blue that works as ink *and* as fill at 7.53:1 both ways, and **no
134
+ radius anywhere**.
135
+ - **`prism`** — from [milvus.io](https://milvus.io/). One static iridescent wash
136
+ with a hard bottom edge, a heavy grotesque display over **mono body copy** —
137
+ the inversion that makes a page read as a project rather than a company.
138
+ - **`maquette`** — from [zilliz.com](https://zilliz.com/). A near-black table
139
+ with a cream axonometric model on it, mono block labels, and the only accent in
140
+ this library's four new packs that works as text (15.49:1).
141
+ - Four reference kits, each with the six-component spine plus four signature
142
+ parts, and four routing scenario pairs (**T16–T19**), every one with its
143
+ negative branch.
144
+
145
+ ### Fixed — the routing table, which was a list
146
+
147
+ **Five of the eight shipped packs named no other pack at all.** Forks existed
148
+ only in `field-notes`, `cyclorama` and `atrium`, and every one pointed backwards
149
+ at packs that never pointed back — so an agent entering at `instrument-console`,
150
+ which is where any infrastructure brief lands first, never learned that a
151
+ distinction existed. Four more one-way forks would have made twelve packs with
152
+ eight dead ends.
153
+
154
+ - `instrument-console`, `workbench`, `field-notes` and `cyclorama` each gain the
155
+ mirror clause for the new pack that forks against them.
156
+ - **A new `validate.py` check enforces it:** a markdown link from one pack to
157
+ another must be reciprocated. Watched failing against a planted defect before
158
+ it landed.
159
+
160
+ ### Fixed — in the packs, not in the references
161
+
162
+ - **`blueprint`'s reference sets pure black as body ink**, on 316 elements, which
163
+ the doctrine bans. The pack ships the reference's *own* second ink `#111827`
164
+ (136 elements) and does not pretend it is the same colour: the two sit **21.2
165
+ apart** in OKLab.
166
+ - **`showroom`'s reference names `#A4ADBA` "caption-foreground"** and it measures
167
+ **2.27:1** on its own white field. Kept, renamed `--disabled`, and captions
168
+ routed to an ink that passes.
169
+ - **`prism`'s reference sets 72px display type in `#00B3FF`** — **2.36:1**, which
170
+ fails even the relaxed large-text floor. The cyan is a fill in this pack.
171
+ - **Neither `blueprint` nor `prism` ships a `prefers-reduced-motion` branch** —
172
+ zero blocks each, against live marquee, ping, pulse and scroll. Both packs
173
+ require the branch their references omit.
174
+ - **`maquette`'s status palette is derived, not extracted**, and the token layer
175
+ says so at the declaration. The reference exposes none; the first set this run
176
+ reached for was a framework default, and the palette gate caught it colliding.
177
+
7
178
  ## [1.8.0] - 2026-08-08
8
179
 
9
180
  An eighth style pack, and the first one whose reference already implements this
package/README.md CHANGED
@@ -10,7 +10,8 @@ nothing. Ask it for a dashboard and you get a different flavor of the same
10
10
  problem — invented colors, six accent hues, dark mode retrofitted later.
11
11
 
12
12
  This skill is the taste layer. It gives a coding agent **one motion
13
- methodology** for cinematic, scroll-driven pages and **six locked style
13
+ methodology** for cinematic, scroll-driven pages, **a motion doctrine** that
14
+ decides whether to animate before it decides how, and **twelve locked style
14
15
  packs** with ready-made design tokens, so what it builds reads as one system
15
16
  instead of a pile of effects.
16
17
 
@@ -34,11 +35,13 @@ and collectively cinematic. One scroll "clock" feeds a WebGL particle field, a
34
35
  rail — each an independent, degrade-to-calm layer. Nothing crossfades; things
35
36
  *redeploy*.
36
37
 
37
- **Style packs** — the visual identity, pluggable per project. Two of them are
38
- meant to be used **standalone**, with none of the motion layer: `workbench`
39
- (quiet light/dark product UI for dashboards, admin panels, internal and dev
40
- tools) and `briefing-room` (a dark 16:9 presentation deck, where the presenter's
41
- voice is the timeline and slides therefore never animate).
38
+ **Style packs** — the visual identity, pluggable per project. Three of them are
39
+ meant to be used **standalone**: `workbench` (quiet light/dark product UI for
40
+ dashboards, admin panels, internal and dev tools) and `briefing-room` (a dark
41
+ 16:9 presentation deck, where the presenter's voice is the timeline and slides
42
+ therefore never animate) take none of the motion layer at all; `field-notes` is
43
+ standalone by default — its reference carries no motion library — but may opt
44
+ into the cinematic layer, and says so in its own *Motion flavor* section.
42
45
 
43
46
  | Pack | Look | Choose for |
44
47
  |---|---|---|
@@ -49,6 +52,10 @@ voice is the timeline and slides therefore never animate).
49
52
  | `atrium` | warm cream daylight field with no dark bands, one terracotta accent, light serif with italic asides, fluted-glass hero over photography | consumer health, longevity & diagnostics, wellness, premium care, high-trust DTC |
50
53
  | `orchard` | warm oat field of rounded slabs, sage brand + one candy-orange action, rounded geometric display, soft-3D pills built from inset light | friendly consumer biotech, DTC wellness, testing kits & supplements |
51
54
  | `field-notes` | warm green-cast paper ruled by hairlines, one rust accent, a hero that dissolves into the page instead of ending, numbered mono eyebrows, crop marks, colour that encodes how a claim is known | open-source & developer tools sold on auditability — code intelligence, provenance, evals, agent memory |
55
+ | `showroom` | white gallery, near-black ink, one blue that works as link and as fill, Inter Display + Inter + JetBrains Mono, a seven-layer shadow framing one real product surface | product-led companies whose best argument is the application on screen |
56
+ | `blueprint` | white drawing stock, 32px grid, ruled column edges, corner registration marks, one electric blue, zero radius anywhere | infrastructure sold on precision — vector databases, search, storage and query engines |
57
+ | `prism` | one static iridescent wash with a hard bottom edge, heavy grotesque display over mono body copy, cyan as a fill only | an open-source project's front door, where the first action is a command |
58
+ | `maquette` | near-black table, cream ink and cream axonometric models, mono block labels, pale aqua that works as text, one offset shadow | enterprise data infrastructure sold to an architecture buyer |
52
59
  | `cyclorama` | a pale field cycling through six pastel stops on a 32s loop under near-black ink that never moves with it, a monospaced typewriter serif over mono, one orange used only as a fill, a particle organ that holds then redeploys, no shadows anywhere | enterprise AI transformation, applied-AI services, technical consultancies — where what is sold is a change of state and there is no screenshot worth showing |
53
60
 
54
61
  Each pack locks palette, type, texture, motion tokens, signature motifs and
@@ -119,11 +126,12 @@ skills.
119
126
  |---|---|
120
127
  | `SKILL.md` | The agent-facing skill: discovery triggers, the principles, how to apply them, quick-reference rules, common mistakes |
121
128
  | `SHELEG_DESIGN.md` | The full reference: architecture, layer-by-layer mechanics with code, the exact morph math, the DOM↔WebGL projection bridge, a build-from-scratch recipe, and why each piece works |
129
+ | `MOTION_DOCTRINE.md` | Whether to animate at all, before how: the frequency table that kills motion on high-repetition paths, the easing tree and the `ease-in` ban, the duration ceiling, the forbidden forms, and the reduced-motion contract. `SKILL.md` marks it required before any animation |
122
130
  | `DESIGN_SYNC_BRIDGE.md` | The Claude Design contract: what a pack sends to claude.ai/design and in what shape, the rule for each of the four reference types, and the border motion does not cross |
123
131
  | `FIGMA_BRIDGE.md` | The design↔code contract: how a pack's tokens map onto Figma variable collections and modes, how to implement a design without importing raw values, and what cannot cross the border |
124
132
  | `AI_PRODUCT_PATTERNS.md` | The surfaces a model drives: the five states of a call, streaming instead of spinners, latency, provenance and uncertainty, agent confirmations, and the bans that keep it honest |
125
- | `styles/*.md` | The eight style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
126
- | `styles/tokens/*.css` | The ready-made token layer per pack, copied verbatim instead of transcribed (workbench ships a light `:root` plus a `data-theme="dark"` twin) |
133
+ | `styles/*.md` | The twelve style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
134
+ | `styles/tokens/*.css` | The ready-made token layer per pack, copied verbatim instead of transcribed (`workbench` and `field-notes` each ship a light `:root` plus a `data-theme="dark"` twin) |
127
135
  | `styles/STYLE_PACK_TEMPLATE.md` | The pack contract as a skeleton, so a new style is authored against the same headings rather than improvised |
128
136
 
129
137
  ## What you get out of it
@@ -193,7 +201,7 @@ cd ./ds-workbench && npm install && npm run build
193
201
  then `/design-sync` in that directory, from Claude Code. Three layers cross: the
194
202
  pack's **bans** as the design system's own README, `styles.css` built from
195
203
  `tokens/<pack>.css` verbatim, and the components — a six-name spine that is
196
- identical in all six kits, so switching packs swaps identity rather than API,
204
+ identical in all twelve kits, so switching packs swaps identity rather than API,
197
205
  plus each pack's signature parts. **Motion does not cross**, exactly as it does
198
206
  not cross into Figma: a kit is the static half of a pack, and saying so is what
199
207
  stops an agent inventing motion to fill the silence.
@@ -220,16 +228,29 @@ repo. Entirely optional; without it the skill works from the pack alone.
220
228
  python3 test/validate.py # or: npm test
221
229
  ```
222
230
 
223
- The validator is the repo's contract, not a formality — it checks manifests and
224
- four-way version sync, skill/command/rule front-matter and description canon,
225
- the full style-pack section contract, pack ↔ `SKILL.md` ↔ CLI-help agreement,
226
- the bundled template against `templates/`, both installers' file lists, the
227
- entire `.cursor/` mirror against the plugin copy, and every relative link. CI
228
- runs it on each push and PR alongside a negative self-test (the validator must
229
- fail on a corrupted version) and installs the bundle through **both** installers,
230
- diffing the result against the source.
231
+ `npm test` is **four gates**, not one, and `validate.py` alone is about a third
232
+ of the contract:
231
233
 
232
- `test/scenarios.md` (T1–T7) is the behavioral harness: fresh subagents given a
234
+ | Gate | What it decides |
235
+ |---|---|
236
+ | `test/validate.py` | manifests and four-way version sync · skill/command/rule front-matter and the description canon · the pack section contract (nine always, the widened four all-or-nothing) and each pack's `Contract:` declaration · the core role vocabulary (`--bg`, `--ink`, and a resolvable accent) in every token layer · every counted claim (packs, kits, scenarios, headings) · exhaustive pack enumerations in the manifests, the command, the CLI, the README and the rule · one name for the pack contract · fork reciprocity · the eleven kit checks · `install.sh`'s file list, both directions · the whole `.cursor/` mirror · every relative link |
237
+ | `test/validate_palette.py` | contrast floors and semantic separation per theme, including three simulated dichromacies · AI-default-cluster provenance · **every contrast ratio the docs state, recomputed from the token layer** |
238
+ | `test/sloplint.py` | the bundle obeying its own bans, in token layers, fenced examples **and the inline CSS the packs prescribe in prose** · doctrine completeness · pack origin addressability |
239
+ | `node --check bin/cli.js` | the installer parses |
240
+
241
+ Each gate ships a `--self-test` that plants a defect it must catch (`npm run
242
+ selftest`), rejects an unknown argument instead of silently running the normal
243
+ pass, and enforces a **ratchet floor** from `test/floors.json` — a check count
244
+ that falls means a requirement stopped being required, which is how stripping
245
+ a pack's four widened sections used to make two gates *quieter* and still green.
246
+
247
+ One honest limit: the npx installer is checked by asserting its runtime bundle
248
+ walker exists, not by reading a file list — it has none by design. What proves
249
+ it ships the right files is CI, which installs the bundle through **both**
250
+ installers and `diff -r`s the result against the source, then builds all twelve
251
+ kits.
252
+
253
+ `test/scenarios.md` (T1–T19) is the behavioral harness: fresh subagents given a
233
254
  task, checking that the skill is discovered, applied and quoted correctly.
234
255
  Re-run the affected scenarios after any edit to `SKILL.md`, a pack or the
235
256
  reference.
package/bin/cli.js CHANGED
@@ -228,16 +228,23 @@ ${c("bold", "Default")}
228
228
  ${c("bold", "What it installs")}
229
229
  SKILL.md the agent-facing skill (discovery + principles)
230
230
  SHELEG_DESIGN.md the full reference (architecture, recipes, why it works)
231
+ MOTION_DOCTRINE.md whether to animate at all — frequency, easing, duration,
232
+ forbidden forms, the reduced-motion contract
231
233
  FIGMA_BRIDGE.md the design↔code contract (tokens ⇄ Figma variables)
234
+ DESIGN_SYNC_BRIDGE.md the Claude Design contract (what a pack sends, and
235
+ what does not cross)
232
236
  AI_PRODUCT_PATTERNS.md chat / agent / streaming surfaces (honest state)
233
- styles/ eight style packs — instrument-console (dark console),
237
+ styles/ twelve style packs — instrument-console (dark console),
234
238
  editorial-luxury (warm editorial), workbench (light/dark
235
239
  product UI), briefing-room (dark 16:9 presentation deck),
236
240
  atrium (warm cream consumer health), orchard (friendly
237
241
  consumer biotech), field-notes (warm paper dev tools),
238
- cyclorama (a pastel field on a 32s cycle, for enterprise
239
- AI transformation) — plus a ready-made token CSS per pack
240
- and STYLE_PACK_TEMPLATE.md for authoring more
242
+ cyclorama (a pastel field on a 32s cycle), showroom
243
+ (the product as the exhibit), blueprint (a drawing sheet,
244
+ zero radius), prism (one iridescent wash over mono body),
245
+ maquette (cream axonometric models on a dark table) —
246
+ plus a ready-made token CSS per pack and
247
+ STYLE_PACK_TEMPLATE.md for authoring more
241
248
  `);
242
249
  }
243
250
 
@@ -314,12 +321,13 @@ function main() {
314
321
  const rel = path.relative(cwd, targetDir) || ".";
315
322
  console.log(
316
323
  `\n${c("green", "✓")} ${c("bold", "SHELEG Design")} installed to ${c("blue", rel + "/")}\n` +
317
- ` ${c("dim", "SKILL.md")} the agent skill\n` +
318
- ` ${c("dim", "SHELEG_DESIGN.md")} the full reference\n` +
319
- ` ${c("dim", "styles/")} style packs + token CSS (instrument-console / editorial-luxury / workbench / briefing-room / atrium / orchard / field-notes / cyclorama)\n\n` +
324
+ ` ${c("dim", "SKILL.md")} the agent skill\n` +
325
+ ` ${c("dim", "SHELEG_DESIGN.md")} the full reference\n` +
326
+ ` ${c("dim", "MOTION_DOCTRINE.md")} whether to animate at all — read before any animation\n` +
327
+ ` ${c("dim", "styles/")} style packs + token CSS (instrument-console / editorial-luxury / workbench / briefing-room / atrium / orchard / field-notes / cyclorama / showroom / blueprint / prism / maquette)\n\n` +
320
328
  `Your Cursor / Claude agent can now discover the skill and build\n` +
321
- `cinematic, scroll-driven pages — or style product UI (dashboards,\n` +
322
- `admin, internal tools) from the workbench pack — on its principles.\n\n` +
329
+ `cinematic, scroll-driven pages — or style product UI (dashboards, admin,\n` +
330
+ `internal tools) from a standalone pack — on its principles.\n\n` +
323
331
  `${c("dim", "Docs: " + pkg.homepage)}\n`,
324
332
  );
325
333
  }
@@ -9,7 +9,8 @@ A page feels cinematic from a **single source of truth** (measured scroll
9
9
  position) driving **many cheap, layered, independently-degradable responses** —
10
10
  not from many animations. If the project has the full skill installed
11
11
  (`.cursor/skills/sheleg-design/`), read its `SKILL.md`, `SHELEG_DESIGN.md`,
12
- and the chosen style pack in `styles/` first (instrument-console — dark
12
+ `MOTION_DOCTRINE.md` (before any animation) and the chosen style pack in
13
+ `styles/` first (instrument-console — dark
13
14
  console; editorial-luxury — warm editorial; workbench — quiet light/dark
14
15
  product UI for dashboards and tools, used standalone without the cinematic
15
16
  motion layer; briefing-room — dark 16:9 presentation deck, standalone, slides
@@ -20,9 +21,49 @@ tools on warm green-cast paper ruled by hairlines, one rust accent, a hero
20
21
  that dissolves into the page, and colour that encodes how a claim is known;
21
22
  cyclorama — enterprise AI transformation on a pale field that cycles through
22
23
  six pastel stops on a 32s loop under fixed near-black ink, a monospaced
23
- typewriter serif, one orange used only as a fill, and no shadows at all);
24
+ typewriter serif, one orange used only as a fill, and no shadows at all;
25
+ showroom — a white gallery where one real product surface is the exhibit,
26
+ under a seven-layer shadow; blueprint — a drawing sheet for infrastructure
27
+ sold on precision: grid, ruled columns, registration marks, one electric
28
+ blue and zero radius; prism — an open-source project's front door, one
29
+ static iridescent wash over mono body copy; maquette — enterprise data
30
+ infrastructure as a cream axonometric model on a near-black table);
24
31
  otherwise follow the contract below (self-contained on purpose).
25
32
 
33
+ ## Whether to animate at all — before how
34
+
35
+ Frequency decides before taste gets a vote. (Full doctrine:
36
+ `MOTION_DOCTRINE.md` in the installed skill.)
37
+
38
+ - Seen 100+ times a day — command palette, keyboard shortcut, tab switch:
39
+ **no animation, ever.** Never animate a keyboard-initiated action; it turns
40
+ instant into laggy and disconnects the result from the keypress.
41
+ - Tens of times a day — hover, list navigation, inline toggles: remove it or
42
+ cut it to the floor. Occasional (modals, drawers, toasts): standard. Rare or
43
+ first-time (onboarding, empty-to-filled): delight is allowed.
44
+ - Every animation answers "why does this move?" in one sentence — spatial
45
+ consistency, state indication, feedback, explanation, or preventing a jarring
46
+ cut. "It looked cool" is not an answer; if you cannot write the sentence,
47
+ delete the animation.
48
+ - **`ease-in` is banned in UI.** It starts slow, in the exact moment the user is
49
+ watching hardest. Entering or leaving → `ease-out`; moving or morphing on
50
+ screen → `ease-in-out`; hover or colour change → `ease`; constant motion →
51
+ `linear`. Curves: `--ease-out: cubic-bezier(.23,1,.32,1)`,
52
+ `--ease-in-out: cubic-bezier(.77,0,.175,1)`,
53
+ `--ease-drawer: cubic-bezier(.32,.72,0,1)`.
54
+ - **UI motion stays under 300 ms.** Button press 100–160ms · tooltip 125–200ms ·
55
+ dropdown 150–250ms · modal/drawer 200–500ms. Marketing and scrollytelling are
56
+ deliberately longer.
57
+ - Never animate a property that triggers layout (`width`, `height`, `top`,
58
+ `left`, `padding`, `margin`, `gap`, `font-size`). Never a bare scroll
59
+ listener, never `requestAnimationFrame` writing component state, never
60
+ `backdrop-filter` or grain on a scrolling container, never a left-behind
61
+ `will-change`, never two marquees.
62
+ - **Reduced motion is a contract, not a feature.** Anything beyond a colour
63
+ change honours `prefers-reduced-motion: reduce`; loops, parallax and springs
64
+ collapse to static or instant, never to "slower". Shipping an animation
65
+ without that branch is a bug, not a polish item.
66
+
26
67
  ## Five principles, in order
27
68
 
28
69
  1. **One clock.** All motion derives from one measured scroll state in one
@@ -119,7 +119,7 @@
119
119
  --track-mono: 0.1em;
120
120
  --track-mono-sm: 0.07em;
121
121
 
122
- /* ---- Elevation: three shadows, one job each -------------------------- */
122
+ /* ---- Elevation: four shadows, one job each --------------------------- */
123
123
  --shadow-panel: 12px 32px 80px 0 rgba(42, 43, 47, 0.1); /* the hero panel */
124
124
  --shadow-lift: 0 4px 30px 0 rgba(0, 0, 0, 0.1); /* a card pulled forward */
125
125
  --shadow-cta: 0 2px 12px 0 rgba(0, 0, 0, 0.1); /* a button on photography */
@@ -175,7 +175,6 @@
175
175
  --marquee-cycle: 0s;
176
176
  }
177
177
  }
178
-
179
178
  /* ── components ── */
180
179
 
181
180
  /* Everything below consumes var(--…) only. Colour never appears as a literal:
@@ -0,0 +1,14 @@
1
+ {
2
+ "pkg": "@sheleg-design/blueprint",
3
+ "globalName": "ShelegBlueprint",
4
+ "shape": "package",
5
+ "buildCmd": "npm run build",
6
+ "srcDir": "src",
7
+ "tsconfig": "tsconfig.json",
8
+ "cssEntry": "src/styles.css",
9
+ "docsDir": "src",
10
+ "readmeHeader": ".design-sync/conventions.md",
11
+ "guidelinesGlob": [
12
+ "guidelines/*.md"
13
+ ]
14
+ }
@@ -0,0 +1,52 @@
1
+ # Blueprint — the contract this design system ships under
2
+
3
+ **Register.** Choose Blueprint for **infrastructure sold on precision**: vector
4
+ databases, search and retrieval, storage and query engines. Its vocabulary is
5
+ technical drafting — a white sheet, a 32px grid, ruled column edges, registration
6
+ marks, one saturated blue used the way a draftsman uses ink. The fork people get
7
+ wrong is against `field-notes`: that pack is **warm paper** arguing from
8
+ provenance (*how do you know*), this one is **cold stock** arguing from precision
9
+ (*how is it built*). Against `instrument-console`: that pack's subject is a
10
+ running system with a changing value; this one's is a mechanism drawn to scale.
11
+ Build every screen against `var(--…)` and never a literal.
12
+
13
+ **There is no radius.** `--radius: 0`, everywhere, and the token exists so the
14
+ ban is greppable. The single exception is `--radius-round: 50%` for a dot or an
15
+ avatar. Most component libraries ship a default radius — zero it globally rather
16
+ than per component, or the page ends up with three rounded inputs nobody notices
17
+ until it looks cheap and nobody can say why.
18
+
19
+ **One blue does everything.** `--accent` `#002BFF` measures 7.53:1 as text on the
20
+ stock *and* 7.53:1 under white. It sets a heading word, draws a 1.5px rule, fills
21
+ a button and rings a focused input, with no second token. It is unusually
22
+ saturated and vibrates against `--ink` at small sizes — never set body copy in
23
+ it.
24
+
25
+ **The ink is not the reference's ink, and the pack says so.** The reference sets
26
+ pure black on 316 elements; the doctrine bans pure black as ink. This system
27
+ ships `#111827` — the reference's own second ink, on 136 of its elements. The two
28
+ sit 21.2 apart in OKLab: it is a visible substitution, not a rounding.
29
+
30
+ **Category marks are squares, not circles.** A circle is a status; a square is a
31
+ kind. Every pair clears both separation floors under all three dichromacies —
32
+ label them anyway, because a legend of four coloured squares is a legend nobody
33
+ reads.
34
+
35
+ **Bans** (verbatim from the pack):
36
+
37
+ - A radius. Any radius, on anything, except `50%` for a dot or an avatar.
38
+ - A shadow used for elevation.
39
+ - `--ink-faint` as text; `--accent` as a large field fill.
40
+ - A circle used as a category mark; a category colour used to mean health.
41
+ - The annotation size without its tracking; caps annotations set at 0.
42
+ - A geometric or humanist substitute for the display face.
43
+ - Fluid `clamp()` type; `transition: all`; `100vh`; a scroll listener.
44
+ - Animating the grid, or parallaxing it.
45
+ - A screenshot as the hero's figure. Draw it, or use `showroom`.
46
+
47
+ **The reference ships no `prefers-reduced-motion` branch at all**, against live
48
+ marquee, ping, pulse and scroll animations. This system requires the branch its
49
+ reference omits.
50
+
51
+ Motion is not part of this design system and must not be invented: a kit is the
52
+ static half of a pack, and anything that moves stays behind in the pack.
@@ -0,0 +1,14 @@
1
+ # @sheleg-design/blueprint
2
+
3
+ The React reference kit for the SHELEG **Blueprint** style pack — a drawing sheet: grid, ruled columns, registration marks, one electric blue, and zero radius anywhere.
4
+
5
+ It is generated from the pack, not authored beside it: `src/styles.css` opens
6
+ with `styles/tokens/blueprint.css` byte for byte, and the rules the design agent
7
+ must obey are in [`.design-sync/conventions.md`](./.design-sync/conventions.md).
8
+
9
+ ```bash
10
+ npm install && npm run build
11
+ ```
12
+
13
+ Then run `/design-sync` in Claude Code from this directory to push it to
14
+ claude.ai/design.
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@sheleg-design/blueprint",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "src"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.json"
21
+ },
22
+ "peerDependencies": {
23
+ "react": ">=18"
24
+ },
25
+ "devDependencies": {
26
+ "typescript": "^5.6.0",
27
+ "@types/react": "^18.3.0"
28
+ }
29
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ category: Actions
3
+ ---
4
+
5
+ **Zero radius**, like everything in this pack. The primary carries registration marks at its four corners — that is the pack's signature and it belongs on the one action the page wants, not on every button.
@@ -0,0 +1,33 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface ButtonProps {
4
+ /** `primary` is the pack's default fill — at most one accent action per view. */
5
+ variant?: 'primary' | 'secondary' | 'ghost';
6
+ size?: 'sm' | 'md' | 'lg';
7
+ disabled?: boolean;
8
+ onClick?: () => void;
9
+ children: ReactNode;
10
+ className?: string;
11
+ }
12
+
13
+ export function Button({
14
+ variant = 'primary',
15
+ size = 'md',
16
+ disabled = false,
17
+ onClick,
18
+ children,
19
+ className,
20
+ }: ButtonProps) {
21
+ return (
22
+ <button
23
+ type="button"
24
+ className={['bp-btn', `bp-btn--${variant}`, `bp-btn--${size}`, className]
25
+ .filter(Boolean)
26
+ .join(' ')}
27
+ disabled={disabled}
28
+ onClick={onClick}
29
+ >
30
+ {children}
31
+ </button>
32
+ );
33
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ category: Surfaces
3
+ ---
4
+
5
+ A panel: `--surface` on a 1px `--line`, **0 radius**, no shadow. Elevation here is a hairline; `--shadow-panel` exists only for a genuinely floating popover.
@@ -0,0 +1,24 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface CardProps {
4
+ title?: string;
5
+ /** Right-aligned metadata on the title row: a count, an id, a timestamp. */
6
+ meta?: string;
7
+ children: ReactNode;
8
+ className?: string;
9
+ }
10
+
11
+ export function Card({ title, meta, children, className }: CardProps) {
12
+ const head = title !== undefined || meta !== undefined;
13
+ return (
14
+ <section className={['bp-card', className].filter(Boolean).join(' ')}>
15
+ {head && (
16
+ <div className="bp-card__head">
17
+ {title !== undefined && <h3 className="bp-card__title">{title}</h3>}
18
+ {meta !== undefined && <span className="bp-card__meta">{meta}</span>}
19
+ </div>
20
+ )}
21
+ <div className="bp-card__body">{children}</div>
22
+ </section>
23
+ );
24
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ category: Data
3
+ ---
4
+
5
+ A category mark — a **square**, never a circle. A circle is a status; a square is a kind. Every pair of category colours clears both separation floors, but label them anyway.
@@ -0,0 +1,25 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface ChipProps {
4
+ children: ReactNode;
5
+ selected?: boolean;
6
+ tone?: 'neutral' | 'accent';
7
+ className?: string;
8
+ }
9
+
10
+ export function Chip({ children, selected = false, tone = 'neutral', className }: ChipProps) {
11
+ return (
12
+ <span
13
+ className={[
14
+ 'bp-chip',
15
+ `bp-chip--${tone}`,
16
+ selected ? 'bp-chip--selected' : undefined,
17
+ className,
18
+ ]
19
+ .filter(Boolean)
20
+ .join(' ')}
21
+ >
22
+ {children}
23
+ </span>
24
+ );
25
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ category: Data
3
+ ---
4
+
5
+ JetBrains Mono on `--surface-2`, **zero radius**, a `$` prompt in `--ink-faint`,
6
+ a copy control at the right.
7
+
8
+ The control changes its **label**, not only its colour. A colour-only
9
+ confirmation is invisible to a meaningful share of the readers this page is for,
10
+ and it is the same rule the pack applies to its category marks.
11
+
12
+ ```tsx
13
+ <CodeLine command="pip install pinecone" copied={done} onCopy={copy} />
14
+ ```