sheleg-design-skill 1.7.0 → 1.9.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 (157) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/README.md +6 -1
  3. package/bin/cli.js +7 -3
  4. package/cursor/rules/sheleg-design.mdc +10 -1
  5. package/kits/blueprint/.design-sync/config.json +14 -0
  6. package/kits/blueprint/.design-sync/conventions.md +52 -0
  7. package/kits/blueprint/README.md +14 -0
  8. package/kits/blueprint/package.json +29 -0
  9. package/kits/blueprint/src/Button.md +5 -0
  10. package/kits/blueprint/src/Button.tsx +33 -0
  11. package/kits/blueprint/src/Card.md +5 -0
  12. package/kits/blueprint/src/Card.tsx +24 -0
  13. package/kits/blueprint/src/Chip.md +5 -0
  14. package/kits/blueprint/src/Chip.tsx +25 -0
  15. package/kits/blueprint/src/CodeLine.md +14 -0
  16. package/kits/blueprint/src/CodeLine.tsx +28 -0
  17. package/kits/blueprint/src/GridField.md +14 -0
  18. package/kits/blueprint/src/GridField.tsx +23 -0
  19. package/kits/blueprint/src/Heading.md +5 -0
  20. package/kits/blueprint/src/Heading.tsx +19 -0
  21. package/kits/blueprint/src/RegistrationMarks.md +17 -0
  22. package/kits/blueprint/src/RegistrationMarks.tsx +34 -0
  23. package/kits/blueprint/src/Rule.md +5 -0
  24. package/kits/blueprint/src/Rule.tsx +18 -0
  25. package/kits/blueprint/src/RuledColumn.md +17 -0
  26. package/kits/blueprint/src/RuledColumn.tsx +25 -0
  27. package/kits/blueprint/src/Stat.md +5 -0
  28. package/kits/blueprint/src/Stat.tsx +17 -0
  29. package/kits/blueprint/src/index.ts +23 -0
  30. package/kits/blueprint/src/styles.css +233 -0
  31. package/kits/blueprint/tsconfig.json +15 -0
  32. package/kits/cyclorama/.design-sync/config.json +12 -0
  33. package/kits/cyclorama/.design-sync/conventions.md +69 -0
  34. package/kits/cyclorama/README.md +23 -0
  35. package/kits/cyclorama/package.json +14 -0
  36. package/kits/cyclorama/src/AppWindow.md +27 -0
  37. package/kits/cyclorama/src/AppWindow.tsx +46 -0
  38. package/kits/cyclorama/src/Button.md +26 -0
  39. package/kits/cyclorama/src/Button.tsx +43 -0
  40. package/kits/cyclorama/src/Card.md +19 -0
  41. package/kits/cyclorama/src/Card.tsx +33 -0
  42. package/kits/cyclorama/src/Chip.md +19 -0
  43. package/kits/cyclorama/src/Chip.tsx +34 -0
  44. package/kits/cyclorama/src/ComparePanel.md +27 -0
  45. package/kits/cyclorama/src/ComparePanel.tsx +61 -0
  46. package/kits/cyclorama/src/FieldStop.md +29 -0
  47. package/kits/cyclorama/src/FieldStop.tsx +33 -0
  48. package/kits/cyclorama/src/Heading.md +20 -0
  49. package/kits/cyclorama/src/Heading.tsx +27 -0
  50. package/kits/cyclorama/src/Rule.md +18 -0
  51. package/kits/cyclorama/src/Rule.tsx +27 -0
  52. package/kits/cyclorama/src/Stat.md +19 -0
  53. package/kits/cyclorama/src/Stat.tsx +25 -0
  54. package/kits/cyclorama/src/StatusPill.md +31 -0
  55. package/kits/cyclorama/src/StatusPill.tsx +37 -0
  56. package/kits/cyclorama/src/index.ts +25 -0
  57. package/kits/cyclorama/src/styles.css +569 -0
  58. package/kits/cyclorama/tsconfig.json +15 -0
  59. package/kits/field-notes/src/styles.css +5 -2
  60. package/kits/maquette/.design-sync/config.json +14 -0
  61. package/kits/maquette/.design-sync/conventions.md +54 -0
  62. package/kits/maquette/README.md +14 -0
  63. package/kits/maquette/package.json +29 -0
  64. package/kits/maquette/src/AquaPill.md +15 -0
  65. package/kits/maquette/src/AquaPill.tsx +30 -0
  66. package/kits/maquette/src/Button.md +5 -0
  67. package/kits/maquette/src/Button.tsx +33 -0
  68. package/kits/maquette/src/Card.md +5 -0
  69. package/kits/maquette/src/Card.tsx +24 -0
  70. package/kits/maquette/src/Chip.md +5 -0
  71. package/kits/maquette/src/Chip.tsx +25 -0
  72. package/kits/maquette/src/CliLine.md +14 -0
  73. package/kits/maquette/src/CliLine.tsx +27 -0
  74. package/kits/maquette/src/Heading.md +5 -0
  75. package/kits/maquette/src/Heading.tsx +19 -0
  76. package/kits/maquette/src/LeaderLabel.md +17 -0
  77. package/kits/maquette/src/LeaderLabel.tsx +24 -0
  78. package/kits/maquette/src/ModelBlock.md +21 -0
  79. package/kits/maquette/src/ModelBlock.tsx +39 -0
  80. package/kits/maquette/src/Rule.md +5 -0
  81. package/kits/maquette/src/Rule.tsx +18 -0
  82. package/kits/maquette/src/Stat.md +5 -0
  83. package/kits/maquette/src/Stat.tsx +17 -0
  84. package/kits/maquette/src/index.ts +24 -0
  85. package/kits/maquette/src/styles.css +253 -0
  86. package/kits/maquette/tsconfig.json +15 -0
  87. package/kits/prism/.design-sync/config.json +14 -0
  88. package/kits/prism/.design-sync/conventions.md +50 -0
  89. package/kits/prism/README.md +14 -0
  90. package/kits/prism/package.json +29 -0
  91. package/kits/prism/src/BenchmarkRow.md +13 -0
  92. package/kits/prism/src/BenchmarkRow.tsx +25 -0
  93. package/kits/prism/src/Button.md +5 -0
  94. package/kits/prism/src/Button.tsx +33 -0
  95. package/kits/prism/src/Card.md +5 -0
  96. package/kits/prism/src/Card.tsx +24 -0
  97. package/kits/prism/src/Chip.md +5 -0
  98. package/kits/prism/src/Chip.tsx +25 -0
  99. package/kits/prism/src/Heading.md +5 -0
  100. package/kits/prism/src/Heading.tsx +19 -0
  101. package/kits/prism/src/InstallLine.md +16 -0
  102. package/kits/prism/src/InstallLine.tsx +29 -0
  103. package/kits/prism/src/RepoBadge.md +13 -0
  104. package/kits/prism/src/RepoBadge.tsx +25 -0
  105. package/kits/prism/src/Rule.md +5 -0
  106. package/kits/prism/src/Rule.tsx +18 -0
  107. package/kits/prism/src/Stat.md +5 -0
  108. package/kits/prism/src/Stat.tsx +17 -0
  109. package/kits/prism/src/Wash.md +17 -0
  110. package/kits/prism/src/Wash.tsx +23 -0
  111. package/kits/prism/src/index.ts +24 -0
  112. package/kits/prism/src/styles.css +223 -0
  113. package/kits/prism/tsconfig.json +15 -0
  114. package/kits/showroom/.design-sync/config.json +14 -0
  115. package/kits/showroom/.design-sync/conventions.md +50 -0
  116. package/kits/showroom/README.md +14 -0
  117. package/kits/showroom/package.json +29 -0
  118. package/kits/showroom/src/Button.md +5 -0
  119. package/kits/showroom/src/Button.tsx +33 -0
  120. package/kits/showroom/src/Card.md +5 -0
  121. package/kits/showroom/src/Card.tsx +24 -0
  122. package/kits/showroom/src/Chip.md +5 -0
  123. package/kits/showroom/src/Chip.tsx +25 -0
  124. package/kits/showroom/src/ColumnHeader.md +15 -0
  125. package/kits/showroom/src/ColumnHeader.tsx +33 -0
  126. package/kits/showroom/src/DataRow.md +14 -0
  127. package/kits/showroom/src/DataRow.tsx +31 -0
  128. package/kits/showroom/src/Heading.md +5 -0
  129. package/kits/showroom/src/Heading.tsx +19 -0
  130. package/kits/showroom/src/Rule.md +5 -0
  131. package/kits/showroom/src/Rule.tsx +18 -0
  132. package/kits/showroom/src/Specimen.md +26 -0
  133. package/kits/showroom/src/Specimen.tsx +44 -0
  134. package/kits/showroom/src/Stat.md +5 -0
  135. package/kits/showroom/src/Stat.tsx +17 -0
  136. package/kits/showroom/src/StatusChip.md +19 -0
  137. package/kits/showroom/src/StatusChip.tsx +26 -0
  138. package/kits/showroom/src/index.ts +23 -0
  139. package/kits/showroom/src/styles.css +249 -0
  140. package/kits/showroom/tsconfig.json +15 -0
  141. package/package.json +2 -2
  142. package/plugins/sheleg-design/.claude-plugin/plugin.json +2 -2
  143. package/plugins/sheleg-design/skills/sheleg-design/SKILL.md +5 -0
  144. package/plugins/sheleg-design/skills/sheleg-design/styles/blueprint.md +336 -0
  145. package/plugins/sheleg-design/skills/sheleg-design/styles/cyclorama.md +417 -0
  146. package/plugins/sheleg-design/skills/sheleg-design/styles/field-notes.md +22 -1
  147. package/plugins/sheleg-design/skills/sheleg-design/styles/instrument-console.md +12 -0
  148. package/plugins/sheleg-design/skills/sheleg-design/styles/maquette.md +323 -0
  149. package/plugins/sheleg-design/skills/sheleg-design/styles/prism.md +297 -0
  150. package/plugins/sheleg-design/skills/sheleg-design/styles/showroom.md +303 -0
  151. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/blueprint.css +143 -0
  152. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/cyclorama.css +201 -0
  153. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/field-notes.css +5 -1
  154. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/maquette.css +154 -0
  155. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/prism.css +138 -0
  156. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/showroom.css +160 -0
  157. package/plugins/sheleg-design/skills/sheleg-design/styles/workbench.md +9 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,122 @@ 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.9.0] - 2026-08-09
8
+
9
+ Four style packs, taking the library from eight to twelve — and a fix to the
10
+ thing that would have made twelve worse than eight.
11
+
12
+ Extracted from four live references on 2026-08-09. Three of them sell vector
13
+ databases and none of them collapse into each other; two are the same company's
14
+ project page and product page, and they share a type stack and nothing else.
15
+
16
+ ### Added
17
+
18
+ - **`showroom`** — from [attio.com](https://attio.com/). A white gallery where
19
+ one real product surface is the exhibit, under a **seven-layer shadow**. The
20
+ reference declares its palette in **CIE Lab**, which this repo's palette gate
21
+ cannot parse; every value was converted by painting it into a canvas and
22
+ reading the sRGB bytes back — the browser's conversion, not ours.
23
+ - **`blueprint`** — from [pinecone.io](https://www.pinecone.io/). A drawing
24
+ sheet: a 32px grid, ruled column boundaries, corner registration marks, one
25
+ electric blue that works as ink *and* as fill at 7.53:1 both ways, and **no
26
+ radius anywhere**.
27
+ - **`prism`** — from [milvus.io](https://milvus.io/). One static iridescent wash
28
+ with a hard bottom edge, a heavy grotesque display over **mono body copy** —
29
+ the inversion that makes a page read as a project rather than a company.
30
+ - **`maquette`** — from [zilliz.com](https://zilliz.com/). A near-black table
31
+ with a cream axonometric model on it, mono block labels, and the only accent in
32
+ this library's four new packs that works as text (15.49:1).
33
+ - Four reference kits, each with the six-component spine plus four signature
34
+ parts, and four routing scenario pairs (**T16–T19**), every one with its
35
+ negative branch.
36
+
37
+ ### Fixed — the routing table, which was a list
38
+
39
+ **Five of the eight shipped packs named no other pack at all.** Forks existed
40
+ only in `field-notes`, `cyclorama` and `atrium`, and every one pointed backwards
41
+ at packs that never pointed back — so an agent entering at `instrument-console`,
42
+ which is where any infrastructure brief lands first, never learned that a
43
+ distinction existed. Four more one-way forks would have made twelve packs with
44
+ eight dead ends.
45
+
46
+ - `instrument-console`, `workbench`, `field-notes` and `cyclorama` each gain the
47
+ mirror clause for the new pack that forks against them.
48
+ - **A new `validate.py` check enforces it:** a markdown link from one pack to
49
+ another must be reciprocated. Watched failing against a planted defect before
50
+ it landed.
51
+
52
+ ### Fixed — in the packs, not in the references
53
+
54
+ - **`blueprint`'s reference sets pure black as body ink**, on 316 elements, which
55
+ the doctrine bans. The pack ships the reference's *own* second ink `#111827`
56
+ (136 elements) and does not pretend it is the same colour: the two sit **21.2
57
+ apart** in OKLab.
58
+ - **`showroom`'s reference names `#A4ADBA` "caption-foreground"** and it measures
59
+ **2.27:1** on its own white field. Kept, renamed `--disabled`, and captions
60
+ routed to an ink that passes.
61
+ - **`prism`'s reference sets 72px display type in `#00B3FF`** — **2.36:1**, which
62
+ fails even the relaxed large-text floor. The cyan is a fill in this pack.
63
+ - **Neither `blueprint` nor `prism` ships a `prefers-reduced-motion` branch** —
64
+ zero blocks each, against live marquee, ping, pulse and scroll. Both packs
65
+ require the branch their references omit.
66
+ - **`maquette`'s status palette is derived, not extracted**, and the token layer
67
+ says so at the declaration. The reference exposes none; the first set this run
68
+ reached for was a framework default, and the palette gate caught it colliding.
69
+
70
+ ## [1.8.0] - 2026-08-08
71
+
72
+ An eighth style pack, and the first one whose reference already implements this
73
+ skill's own core pattern.
74
+
75
+ `cyclorama` is extracted from [codos.ai](https://www.codos.ai/): a pale field
76
+ that breathes through **six pastel stops on a 32-second loop** under near-black
77
+ ink that never moves with it, a **monospaced typewriter serif** over a
78
+ monospaced sans, one orange used only as a fill, and no shadows anywhere. Its
79
+ reference ships GSAP ScrollTrigger with real pinning and two WebGL canvases
80
+ whose formation holds and then redeploys — principle 3 in production rather than
81
+ in a doc.
82
+
83
+ ### Added
84
+
85
+ - **`styles/cyclorama.md`** on the thirteen-heading widened contract plus
86
+ `## Motion flavor`, with an addressable origin and every ratio computed by
87
+ importing `test/validate_palette.py` rather than by a second implementation.
88
+ - **`styles/tokens/cyclorama.css`** — the six cycle stops as named tokens, one
89
+ ease, three durations plus the 32s loop, a five-step radius ramp whose nesting
90
+ is arithmetic, and an inline accent-dot cursor.
91
+ - **`kits/cyclorama/`** — the six-component spine plus four signature parts:
92
+ `FieldStop` (the six stops as six static surfaces — the cycle itself does not
93
+ cross the border), `AppWindow` (a hairline frame with **no fill**, so the
94
+ field shows through it), `StatusPill` and `ComparePanel`.
95
+ - **`docs/adr/0001-style-pack-naming.md`** — restored to `main`. It was written
96
+ on a branch that held at its stage-0 gate and never merged, so the decision
97
+ register began at `0002` for four days while the rule it records was already
98
+ binding. It is why this pack is `cyclorama` and not `codos`.
99
+ - **T15** in `test/scenarios.md` — a routing pair with its negative branch, so
100
+ "is `cyclorama` distinguishable from `field-notes`?" can fail in the
101
+ interesting direction.
102
+
103
+ ### Fixed — in the pack, not in the reference
104
+
105
+ - The reference paints its section eyebrows in the accent on the field, which
106
+ measures **1.71–1.97:1** across the six stops. This pack does not propagate
107
+ it: the accent is a fill, eyebrows take `--ink-soft` at 8.36:1. The three
108
+ darkened-orange candidates are recorded in `## Gotchas` **with their numbers**,
109
+ because each one trades a WCAG failure for a colour-blindness collision with
110
+ `--danger` or `--warning` — there is no text-safe orange in this palette, and
111
+ the next reader should not have to rediscover that.
112
+ - The pack states that `--accent` and `--signal` sit 6.8 apart under protanopia
113
+ and that **the palette gate cannot see it**, because `--signal` is not one of
114
+ the names it treats as semantic. Written down rather than renamed around: a
115
+ token renamed to satisfy a checker is worse than an unchecked token that says
116
+ so out loud.
117
+ - The reference's own display fallback is `Fraunces`, which is **proportional**,
118
+ while the face it replaces is monospaced — so a reader without the licensed
119
+ font gets a hero that reflows rather than merely restyles. The pack ships
120
+ measured substitutes instead (Courier Prime 0.600, Cutive Mono 0.605 against
121
+ the original's 0.590).
122
+
7
123
  ## [1.7.0] - 2026-08-05
8
124
 
9
125
  The Claude Design border, and the first code this skill has ever shipped.
package/README.md CHANGED
@@ -49,6 +49,11 @@ voice is the timeline and slides therefore never animate).
49
49
  | `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
50
  | `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
51
  | `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 |
52
+ | `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 |
53
+ | `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 |
54
+ | `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 |
55
+ | `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 |
56
+ | `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 |
52
57
 
53
58
  Each pack locks palette, type, texture, motion tokens, signature motifs and
54
59
  bans — and ships a `tokens/<pack>.css` to copy verbatim, so the agent never
@@ -121,7 +126,7 @@ skills.
121
126
  | `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 |
122
127
  | `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 |
123
128
  | `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 |
124
- | `styles/*.md` | The seven style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
129
+ | `styles/*.md` | The twelve style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
125
130
  | `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) |
126
131
  | `styles/STYLE_PACK_TEMPLATE.md` | The pack contract as a skeleton, so a new style is authored against the same headings rather than improvised |
127
132
 
package/bin/cli.js CHANGED
@@ -230,11 +230,15 @@ ${c("bold", "What it installs")}
230
230
  SHELEG_DESIGN.md the full reference (architecture, recipes, why it works)
231
231
  FIGMA_BRIDGE.md the design↔code contract (tokens ⇄ Figma variables)
232
232
  AI_PRODUCT_PATTERNS.md chat / agent / streaming surfaces (honest state)
233
- styles/ seven style packs — instrument-console (dark console),
233
+ styles/ twelve style packs — instrument-console (dark console),
234
234
  editorial-luxury (warm editorial), workbench (light/dark
235
235
  product UI), briefing-room (dark 16:9 presentation deck),
236
236
  atrium (warm cream consumer health), orchard (friendly
237
- consumer biotech), field-notes (warm paper dev tools)
237
+ consumer biotech), field-notes (warm paper dev tools),
238
+ cyclorama (a pastel field on a 32s cycle), showroom
239
+ (the product as the exhibit), blueprint (a drawing sheet,
240
+ zero radius), prism (one iridescent wash over mono body),
241
+ maquette (cream axonometric models on a dark table) —
238
242
  plus a ready-made token CSS per pack and
239
243
  STYLE_PACK_TEMPLATE.md for authoring more
240
244
  `);
@@ -315,7 +319,7 @@ function main() {
315
319
  `\n${c("green", "✓")} ${c("bold", "SHELEG Design")} installed to ${c("blue", rel + "/")}\n` +
316
320
  ` ${c("dim", "SKILL.md")} the agent skill\n` +
317
321
  ` ${c("dim", "SHELEG_DESIGN.md")} the full reference\n` +
318
- ` ${c("dim", "styles/")} style packs + token CSS (instrument-console / editorial-luxury / workbench / briefing-room / atrium / orchard / field-notes)\n\n` +
322
+ ` ${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` +
319
323
  `Your Cursor / Claude agent can now discover the skill and build\n` +
320
324
  `cinematic, scroll-driven pages — or style product UI (dashboards,\n` +
321
325
  `admin, internal tools) from the workbench pack — on its principles.\n\n` +
@@ -17,7 +17,16 @@ never animate; atrium — warm cream consumer-health field, one terracotta
17
17
  accent, fluted-glass hero; orchard — friendly consumer biotech, oat slabs,
18
18
  sage brand and one candy-orange action; field-notes — open-source developer
19
19
  tools on warm green-cast paper ruled by hairlines, one rust accent, a hero
20
- that dissolves into the page, and colour that encodes how a claim is known);
20
+ that dissolves into the page, and colour that encodes how a claim is known;
21
+ cyclorama — enterprise AI transformation on a pale field that cycles through
22
+ 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
+ showroom — a white gallery where one real product surface is the exhibit,
25
+ under a seven-layer shadow; blueprint — a drawing sheet for infrastructure
26
+ sold on precision: grid, ruled columns, registration marks, one electric
27
+ blue and zero radius; prism — an open-source project's front door, one
28
+ static iridescent wash over mono body copy; maquette — enterprise data
29
+ infrastructure as a cream axonometric model on a near-black table);
21
30
  otherwise follow the contract below (self-contained on purpose).
22
31
 
23
32
  ## Five principles, in order
@@ -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
+ ```
@@ -0,0 +1,28 @@
1
+ export interface CodeLineProps {
2
+ command: string;
3
+ /** Shown before the command, in --ink-faint. Defaults to a shell prompt. */
4
+ prompt?: string;
5
+ onCopy?: () => void;
6
+ /** Flipped by the caller after a copy. Changes the LABEL, not just a colour. */
7
+ copied?: boolean;
8
+ className?: string;
9
+ }
10
+
11
+ /**
12
+ * A command in JetBrains Mono on `--surface-2`, zero radius, with a copy
13
+ * control at the right.
14
+ *
15
+ * The copy control changes its **label** to `copied`, not only its colour — the
16
+ * same rule the pack applies to category marks, and for the same readers.
17
+ */
18
+ export function CodeLine({ command, prompt = '$', onCopy, copied = false, className }: CodeLineProps) {
19
+ return (
20
+ <div className={['bp-code', className].filter(Boolean).join(' ')}>
21
+ <span className="bp-code__prompt" aria-hidden="true">{prompt}</span>
22
+ <code className="bp-code__cmd">{command}</code>
23
+ <button type="button" className="bp-code__copy" onClick={onCopy}>
24
+ {copied ? 'copied' : 'copy'}
25
+ </button>
26
+ </div>
27
+ );
28
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ category: Foundations
3
+ ---
4
+
5
+ 1px dots in `--line-grid` at `--grid-step` 32px, halving to 16px below 768px so
6
+ the density stays visually constant as the viewport narrows.
7
+
8
+ Depth layer 1: `pointer-events: none`, `aria-hidden`, never on a scroller, and
9
+ **never animated**. The grid is the sheet. A sheet that drifts, parallaxes or
10
+ fades in turns a drawing into a screensaver.
11
+
12
+ ```tsx
13
+ <GridField />
14
+ ```
@@ -0,0 +1,23 @@
1
+ export interface GridFieldProps {
2
+ /** Dot spacing in px. Halves below 768px so density stays visually constant. */
3
+ step?: number;
4
+ className?: string;
5
+ }
6
+
7
+ /**
8
+ * The drawing grid: 1px dots in `--line-grid` at `--grid-step`.
9
+ *
10
+ * It sits at depth layer 1 — `pointer-events: none`, `aria-hidden`, behind
11
+ * everything, never on a scroller. **It never animates**: not on load, not on
12
+ * scroll, not on hover. It is the sheet the page is drawn on, and a sheet that
13
+ * moves is a different kind of page.
14
+ */
15
+ export function GridField({ step, className }: GridFieldProps) {
16
+ return (
17
+ <div
18
+ className={['bp-grid', className].filter(Boolean).join(' ')}
19
+ style={step !== undefined ? ({ ['--grid-step' as string]: `${step}px` } as object) : undefined}
20
+ aria-hidden="true"
21
+ />
22
+ );
23
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ category: Foundations
3
+ ---
4
+
5
+ GT Planar at 700, tracking −0.02em. Substitutes are Inter or Geist — never a geometric, which rounds the page off in a way that fights the zero-radius rule.
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface HeadingProps {
4
+ /** 1 = page title, 2 = section, 3 = sub-head. */
5
+ level?: 1 | 2 | 3;
6
+ children: ReactNode;
7
+ className?: string;
8
+ }
9
+
10
+ export function Heading({ level = 2, children, className }: HeadingProps) {
11
+ const Tag = `h${level}` as 'h1' | 'h2' | 'h3';
12
+ return (
13
+ <Tag
14
+ className={['bp-heading', `bp-heading--${level}`, className].filter(Boolean).join(' ')}
15
+ >
16
+ {children}
17
+ </Tag>
18
+ );
19
+ }
@@ -0,0 +1,17 @@
1
+ ---
2
+ category: Signature
3
+ ---
4
+
5
+ Four L-shaped brackets — `--tick-len` 8px arms at `--tick-w` 1px, offset
6
+ `--tick-gap` 6px — around the thing the page is registering.
7
+
8
+ **Spend them on one thing per viewport.** The primary action, or the figure the
9
+ section argues from. Marks on every card is a texture; marks on the one thing
10
+ that matters is an argument, and it is the argument this pack is making.
11
+
12
+ Desktop only: below 768px they come off buttons, where 8px brackets become
13
+ touch-target confetti, and stay on framed figures.
14
+
15
+ ```tsx
16
+ <RegistrationMarks tone="accent"><Button>Start Building</Button></RegistrationMarks>
17
+ ```
@@ -0,0 +1,34 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface RegistrationMarksProps {
4
+ /** `accent` puts the marks in the pack's blue; `grid` keeps them faint. */
5
+ tone?: 'grid' | 'accent';
6
+ children: ReactNode;
7
+ className?: string;
8
+ }
9
+
10
+ /**
11
+ * Four L-shaped brackets at the corners of whatever it wraps: 8px arms at 1px,
12
+ * offset 6px from the object they register.
13
+ *
14
+ * They are the pack's signature and they must stay rare. A registration mark
15
+ * exists so two plates line up in a press — it is a mark about *accuracy*, made
16
+ * by someone who assumed you would recognise it. Put them on **one** thing per
17
+ * viewport: the action the page wants, or the figure it is arguing from. Marks
18
+ * on every card is a texture; marks on the one thing that matters is an
19
+ * argument.
20
+ *
21
+ * Desktop only. At 8px they become touch-target confetti on a phone, so they
22
+ * come off buttons below 768px and stay only on framed figures.
23
+ */
24
+ export function RegistrationMarks({ tone = 'grid', children, className }: RegistrationMarksProps) {
25
+ return (
26
+ <span className={['bp-reg', `bp-reg--${tone}`, className].filter(Boolean).join(' ')}>
27
+ {children}
28
+ <i className="bp-reg__tick bp-reg__tick--tl" aria-hidden="true" />
29
+ <i className="bp-reg__tick bp-reg__tick--tr" aria-hidden="true" />
30
+ <i className="bp-reg__tick bp-reg__tick--bl" aria-hidden="true" />
31
+ <i className="bp-reg__tick bp-reg__tick--br" aria-hidden="true" />
32
+ </span>
33
+ );
34
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ category: Foundations
3
+ ---
4
+
5
+ 1px in `--line`, 0 radius. The vertical column rules are a layout element, not this component; use `RuledColumn` for those.
@@ -0,0 +1,18 @@
1
+ export interface RuleProps {
2
+ tone?: 'hairline' | 'strong';
3
+ className?: string;
4
+ }
5
+
6
+ export function Rule({ tone = 'hairline', className }: RuleProps) {
7
+ return (
8
+ <hr
9
+ className={[
10
+ 'bp-rule',
11
+ tone === 'strong' ? 'bp-rule--strong' : undefined,
12
+ className,
13
+ ]
14
+ .filter(Boolean)
15
+ .join(' ')}
16
+ />
17
+ );
18
+ }
@@ -0,0 +1,17 @@
1
+ ---
2
+ category: Foundations
3
+ ---
4
+
5
+ Two 1px verticals in `--line-strong` at `--column-max` 1280px, running the full
6
+ height of the section.
7
+
8
+ This is the layout made visible. A max-width container with no rules is a
9
+ website; the same container with its boundaries drawn is a sheet, and that
10
+ difference is most of what separates this pack from a plain white page.
11
+
12
+ Below 1024px the rules move to the viewport edges; below 768px they are removed
13
+ entirely.
14
+
15
+ ```tsx
16
+ <RuledColumn><Heading level={1}>Give agents knowledge</Heading></RuledColumn>
17
+ ```
@@ -0,0 +1,25 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface RuledColumnProps {
4
+ children: ReactNode;
5
+ className?: string;
6
+ }
7
+
8
+ /**
9
+ * The content column with its two 1px vertical rules, in `--line-strong`,
10
+ * running the section's full height at `--column-max`.
11
+ *
12
+ * They are the layout made visible, and they are why the page reads as a sheet
13
+ * rather than as a container with a max-width. Below 1024px they collapse to
14
+ * the viewport edges; below 768px they are removed entirely, because two rules
15
+ * 16px in from the screen edge read as a rendering error.
16
+ */
17
+ export function RuledColumn({ children, className }: RuledColumnProps) {
18
+ return (
19
+ <div className={['bp-column', className].filter(Boolean).join(' ')}>
20
+ <span className="bp-column__rule bp-column__rule--l" aria-hidden="true" />
21
+ <div className="bp-column__inner">{children}</div>
22
+ <span className="bp-column__rule bp-column__rule--r" aria-hidden="true" />
23
+ </div>
24
+ );
25
+ }