sheleg-design-skill 1.29.0 → 1.32.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 (53) hide show
  1. package/CHANGELOG.md +224 -0
  2. package/README.md +5 -4
  3. package/bin/cli.js +5 -2
  4. package/cursor/rules/sheleg-design.mdc +5 -1
  5. package/kits/paperclip/.design-sync/config.json +14 -0
  6. package/kits/paperclip/.design-sync/conventions.md +62 -0
  7. package/kits/paperclip/README.md +46 -0
  8. package/kits/paperclip/package.json +29 -0
  9. package/kits/paperclip/src/Button.md +23 -0
  10. package/kits/paperclip/src/Button.tsx +33 -0
  11. package/kits/paperclip/src/CapsuleCurtain.md +32 -0
  12. package/kits/paperclip/src/CapsuleCurtain.tsx +109 -0
  13. package/kits/paperclip/src/Card.md +22 -0
  14. package/kits/paperclip/src/Card.tsx +24 -0
  15. package/kits/paperclip/src/Chip.md +21 -0
  16. package/kits/paperclip/src/Chip.tsx +25 -0
  17. package/kits/paperclip/src/HairlineGrid.md +34 -0
  18. package/kits/paperclip/src/HairlineGrid.tsx +23 -0
  19. package/kits/paperclip/src/Heading.md +21 -0
  20. package/kits/paperclip/src/Heading.tsx +19 -0
  21. package/kits/paperclip/src/LedgerRow.md +31 -0
  22. package/kits/paperclip/src/LedgerRow.tsx +54 -0
  23. package/kits/paperclip/src/OrgNode.md +27 -0
  24. package/kits/paperclip/src/OrgNode.tsx +42 -0
  25. package/kits/paperclip/src/Rule.md +20 -0
  26. package/kits/paperclip/src/Rule.tsx +18 -0
  27. package/kits/paperclip/src/ScheduleLane.md +31 -0
  28. package/kits/paperclip/src/ScheduleLane.tsx +58 -0
  29. package/kits/paperclip/src/SectionBadge.md +23 -0
  30. package/kits/paperclip/src/SectionBadge.tsx +21 -0
  31. package/kits/paperclip/src/Stat.md +18 -0
  32. package/kits/paperclip/src/Stat.tsx +17 -0
  33. package/kits/paperclip/src/Terminal.md +34 -0
  34. package/kits/paperclip/src/Terminal.tsx +67 -0
  35. package/kits/paperclip/src/index.ts +29 -0
  36. package/kits/paperclip/src/styles.css +962 -0
  37. package/kits/paperclip/tsconfig.json +15 -0
  38. package/kits/tenor/src/styles.css +61 -9
  39. package/package.json +2 -2
  40. package/plugins/sheleg-design/.claude-plugin/plugin.json +2 -2
  41. package/plugins/sheleg-design/commands/sheleg-design.md +2 -2
  42. package/plugins/sheleg-design/skills/sheleg-design/DESIGN_SYNC_BRIDGE.md +1 -1
  43. package/plugins/sheleg-design/skills/sheleg-design/MOBILE_SURFACES.md +1 -1
  44. package/plugins/sheleg-design/skills/sheleg-design/SKILL.md +12 -8
  45. package/plugins/sheleg-design/skills/sheleg-design/SURFACE_COMPOSITION.md +4 -4
  46. package/plugins/sheleg-design/skills/sheleg-design/styles/instrument-console.md +10 -0
  47. package/plugins/sheleg-design/skills/sheleg-design/styles/ora.md +13 -0
  48. package/plugins/sheleg-design/skills/sheleg-design/styles/orchard.md +9 -0
  49. package/plugins/sheleg-design/skills/sheleg-design/styles/paperclip.md +775 -0
  50. package/plugins/sheleg-design/skills/sheleg-design/styles/tenor.md +115 -23
  51. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/paperclip.css +294 -0
  52. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/tenor.css +61 -9
  53. package/plugins/sheleg-design/skills/sheleg-design/styles/workbench.md +10 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,230 @@ 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.32.0] - 2026-08-15
8
+
9
+ **The pack met a product surface, and three of its own measurements did not survive
10
+ the meeting.** `tenor` was mounted on a populated twenty-route dashboard behind a
11
+ `?pack=` switch — the "mount them, don't imagine them" procedure `SKILL.md` prescribes
12
+ — and every finding below came from a screen with real data on it rather than from a
13
+ re-read. Each is reproduced by a number the token layer now carries and
14
+ `validate_stated_ratios` now checks.
15
+
16
+ ### Fixed — in `tenor`
17
+
18
+ - **The reference puts the wrong label on its own accent, and the pack copied the
19
+ workaround instead of the fix.** Gotcha 3 measured `--paper` on the orange at 3.02:1,
20
+ correctly, and concluded that a control whose label is its only statement must keep
21
+ its ink fill and move its *border* to the accent. It never measured the other
22
+ direction: `--coal` on the same orange is **5.84:1**. `--accent-ink` is the coal now,
23
+ declared once and deliberately not overridden on the dark band — the orange does not
24
+ change between fields, so neither does the only label readable on it. The hover fill,
25
+ which is this pack's most recognisable interaction, is legal after all.
26
+ - **Gotcha 1's remedy was short on the pack's own second field.** It said to darken
27
+ `--ink-soft` "to at least `#6f6f6b`", which clears 4.67:1 on `--bg` and only **4.27:1**
28
+ on `--bg-deep` — a field the pack spends on a whole section. A remedy nobody
29
+ re-measures is a defect with a citation attached. **New `--ink-soft-aa` `#6b6b67`**:
30
+ 4.95:1 and 4.53:1, the smallest step that holds on both. `--ink-soft` keeps the
31
+ reference's value and is now marked for the tracked mono labels, not for prose.
32
+ - **`--warn` is the accent, and a product surface sets warn as a word.** At 3.02:1 the
33
+ orange cannot carry one. **New `--warn-ink` `#94400f`** — the same hue on the value
34
+ axis, 6.47:1 on `--bg` and 5.93:1 on `--bg-deep`. `--warn` stays the mark (the dot,
35
+ the edge rule, the fill); the two are one severity in two roles, which is the split
36
+ `--sev-ask`/`--sev-limit`/`--sev-never` already models. On the dark band the orange
37
+ clears AA unaided, so `--warn-ink` remaps back to the accent there.
38
+ - **The dark band's `--bg-deep` resolved to the field it sits on.** Correct for a band,
39
+ which has no hover and no resting chip; a rule that silently does nothing on a product
40
+ surface, which has both. Derived to `#222221` — paper at 8% over the coal, 1.20:1
41
+ against `--bg`, and `--ink` 14.73:1 / `--ink-soft` 6.31:1 / `--good` 7.07:1 on it.
42
+
43
+ ### Added — in `tenor`
44
+
45
+ - **`--coal`**, beside `--paper`. The pack has two materials and named only one, which is
46
+ why the dark band restated `#f7f6f2` as a literal that then had to agree with the light
47
+ block by hand. `--ink` is `var(--coal)` on the paper and `var(--paper)` on the band.
48
+ - **`### On a product surface`**, inside `## Components`. Five things a marketing page
49
+ never exercises, each derived and each found on the dashboard: no dark theme exists and
50
+ a product with a toggle has to pick one of three answers; ranking by value costs the
51
+ link its affordance, and the pack's own flipped-origin rule is the fix (static
52
+ underline in a table — fifty animated rules is the marquee ban in another costume); a
53
+ rail's selected row is the lattice cell's inversion held open; **a column of chips is
54
+ where the single hairline stops separating**, which makes the Register's "not for dense
55
+ operator chrome" specific rather than a blanket refusal; and prose sits on two fields
56
+ at once. What does not change: the spacing scale and the type ramp, which are page
57
+ values.
58
+
59
+ ### Note
60
+
61
+ `--bg-deep` on the dark band was written into this changelog's draft as 1.41:1 against
62
+ `--bg` and is **1.20:1**. The number was asserted rather than computed, and
63
+ `validate_stated_ratios` caught it before the commit — the check earning its keep on the
64
+ run that extended it.
65
+
66
+ ## [1.31.0] - 2026-08-14
67
+
68
+ **T29 ran, and the pack it was written for did not survive it intact.** Both branches
69
+ green — the routing worked — and the pair returned forty-one findings, twenty-six of them
70
+ against `paperclip`, a pack that had passed all three gates three times. Every one was
71
+ reproduced before an edit; every one is fixed here.
72
+
73
+ ### Fixed — in `paperclip`, found by T29a
74
+
75
+ - **`--cream` was prescribed and never declared.** The dark primary button's hover was
76
+ specified to keep its label and border at `--cream`, a token this pack does not ship. It
77
+ means `--accent`, and now says so.
78
+ - **The dark card hover was a no-op.** A card rests at `--surface` and the hover was
79
+ written as `--surface`. A card and a grid cell are now separated: the cell rests at
80
+ `--bg` and hovers one step toward the card's fill; the card does not hover at all.
81
+ - **`--terminal-dim` at 2.92:1 was the label of a tab a reader has to click.** Repaired to
82
+ `--terminal-mid` (5.64:1). `--terminal-dim` survives for the prompt glyph, which is
83
+ `aria-hidden` punctuation, and now carries an `@role non-text:` note saying so.
84
+ - **`--shadow-alert` was a second resting shadow in a pack that claimed one** — and it
85
+ hardcoded the reference's **light**-theme amber into a value only ever painted on the
86
+ dark field. Derived from `--warn` with `color-mix()`, and the Texture section now names
87
+ both shadows.
88
+ - **All three stagger formulas hardcoded `.14s`.** Zeroing `--stagger` under reduced
89
+ motion would have left every one of them running. They spend `var(--stagger)` now, and
90
+ the pack says why in the sentence that used to say "change it in one place".
91
+ - **The reduced-motion blanket had no mechanism for half of what it promised.** The
92
+ marquee and the two 1.5s trace loops are literals inside `animation` shorthands, which no
93
+ token can zero. The pack now ships the rule block beside the token list.
94
+ - **The signature element's generation rule did not reproduce its own artwork.** The
95
+ bottom stop was stated at −10.3°/step and does not land on the last capsule; the value
96
+ implied by the anchors is **−10.45°**. "Near-constant saturation and lightness" was true
97
+ of the top ramp (S 96→84, L 56→48) and false of the bottom (S 96→69, L 56→33) — the
98
+ bottom stop darkens as it turns, which is what keeps the curtain's lower edge off the
99
+ field. Both ramps are now stated separately, and "forty-five gradients" no longer sits
100
+ two sentences from "every capsule is filled with its own": a column carries twelve and
101
+ the eight columns reuse the ramps, four of them in reverse.
102
+ - **The concentric-radius rule was arithmetically wrong about a nest that does not exist.**
103
+ `8 − 2 ≈ 4.8` is 6, and the reference's tab group sits inside a header with no radius.
104
+ The rule is now declared as the pack's own decision, with a worked example that computes,
105
+ and the reference's actual behaviour — pick by element size, no arithmetic — recorded.
106
+ - **`--radius-lg` was called "never spent" and is spent five times**, on the three large
107
+ mock panels. `--radius-md` is the rung that is never spent.
108
+ - Smaller, and all reproduced: the artwork called 1200px *tall* where 1200 is its frame's
109
+ width (it is a 560 × 630 curtain in a 1200 × 675 frame); "nothing in this pack overlaps"
110
+ in a pack whose hero is an overlap; a 1.5 line-height floor claimed against a display
111
+ ramp that runs 0.98; `--font-serif` and `--font-sans` named as if the layer declared
112
+ them; an icon range of 14–16px that excluded the pack's own 11px nav glyph; a mono ramp
113
+ called width-invariant beside an axis mark that steps at 768px; a Gotchas count of seven
114
+ where eight are defects; the grain's 512-unit filter in a 256px tile, which is the
115
+ reference's own arrangement and doubles the effective frequency to ~5.9 — now stated with
116
+ its consequence rather than repaired; weight 450 prescribed in a pack that documents 450
117
+ as unrenderable; and an invented "roughly 22 characters per line", replaced by the two
118
+ lines the reference actually sets.
119
+
120
+ ### Fixed — in neighbours, found by the same run
121
+
122
+ - **`ora`'s merge-time fork clause called this pack "three grotesques and a monospace".**
123
+ It is two grotesques and a monospace; the pack's own Bans cap it at three families.
124
+ - **`SKILL.md` marked three packs `(standalone)` and its ceiling paragraph named four.**
125
+ `ora`, `tenor` and `paperclip` all declare standalone in their own Registers and all
126
+ three pin a ceiling — 4, 4 and 5 — that the paragraph never mentioned. An agent choosing
127
+ any of them off the table alone would have taken `MOTION_INTENSITY` 7 from the marketing
128
+ row. All three are marked and all three ceilings enumerated.
129
+
130
+ ### Added
131
+
132
+ - **`--terminal-dot`, `--mark-rest`, `--scrim`** — three colours the pack spent as literals
133
+ in its Components section. `--scrim` is `#0a0a0a8c` in **both** themes, because the
134
+ reference veils a light modal in coal too, and it stays a literal because the palette gate
135
+ cannot compute a `color-mix()` into `transparent` — and an unparseable token is a failure
136
+ there, not a skip.
137
+ - **`--t-hero-art` and `--t-hero-copy` in the Motion tokens table**, which shipped in the
138
+ token layer and appeared only as prose. The table is now the whole set.
139
+ - **B-038 … B-043** — fifteen findings against `instrument-console` from T29b, filed rather
140
+ than fixed because they belong to a shipped pack this run does not own. Four reproduced
141
+ first: zero `--danger`/`--info` tokens against Bans that legislate for four statuses; a
142
+ pressed primary label at **3.06:1**; one of only two token layers with no
143
+ `prefers-reduced-motion` branch, in the pack that mandates a particle field; and a Bans
144
+ line that forbids coloured shadows "besides `--accent-glow`", which is a colour.
145
+
146
+ ## [1.30.0] - 2026-08-14
147
+
148
+ A twentieth pack, **`paperclip`**, extracted from a live reference rather than composed:
149
+ <https://paperclip.ing>, read from the two shipped stylesheets
150
+ (`/_next/static/chunks/0sw-z-v7xc9dd.css`, 622 rules; `/_next/static/chunks/19xj4kovk13jy.css`,
151
+ 712 rules), the hero's inline SVG and the `@font-face` block. It is the first pack whose
152
+ thesis is that **colour is ornament**: there is no functional colour anywhere in the
153
+ interface, and the whole chromatic budget is spent on two things a reader cannot click.
154
+
155
+ Authored on `feat/paperclip-pack` in a dedicated worktree while another run held the
156
+ `PACK-TENOR` lease on the shared checkout, per `docs/DOCMAP.md`. That run landed `ora` and
157
+ `tenor` as 1.29.0 while this branch was open — including the version this branch had
158
+ already taken — so the merge moved it to 1.30.0 and recounted every site from eighteen to
159
+ twenty. Nothing was lost in either direction; the counted-claims gate named all eleven
160
+ sites that needed moving.
161
+
162
+ ### Added
163
+
164
+ - **`styles/paperclip.md` + `styles/tokens/paperclip.css` — widened contract, all thirteen
165
+ headings.** A neutral coal field (`#0a0a0a`) with `#fafafa` ink at 18.97:1, and a light
166
+ twin on pure white at 19.80:1 that has **no elevation step at all**: the reference sets
167
+ `--background` and `--card` to the same white and separates a card from the page with a
168
+ 1px rule and nothing else.
169
+ - **The accent is the inverted field, and colour is ornament.** Every control is
170
+ monochrome — `.navbar-cta`, `.hero-btn-primary`, `.sim-submit` and `.cta-btn` are one
171
+ component wearing four names — and the pack's central rule is one sentence: a gradient
172
+ that can be clicked, hovered or focused has left the pack. The corollary is what makes
173
+ the four status hues land: because colour is spent entirely on things that do nothing,
174
+ anything coloured reads as scenery.
175
+ - **The capsule curtain as the signature element.** 96 capsules in 8 columns on a 70px
176
+ pitch, each 70 × 170 at `rx: 35`, stepped 34.5px so every capsule covers all but a
177
+ 34.5px band of the one above it. The 45 gradients filling them are **generated, not
178
+ chosen**: the top stop rotates forward around the hue wheel by ~12.4° per capsule and
179
+ the bottom stop backward by ~10.3°, at near-constant saturation and lightness — so the
180
+ stops stay near-complementary and each column inverts its own gradient between its first
181
+ capsule and its last. Measured across all 45 gradients and 89 distinct stops.
182
+ - **One noise recipe, on every saturated surface and nowhere else.** `fractalNoise`,
183
+ `baseFrequency 2.95`, 5 octaves, seed 9, tiled at 256px under `isolation: isolate` with
184
+ `mix-blend-mode: overlay` — 12% on a section badge, 86% over the artwork through an
185
+ alpha mask of the capsules themselves. The same seed on both, which is why a
186
+ twelve-gradient page does not band.
187
+ - **Twelve section-badge gradients, each with its own hand-picked label ink** — white on
188
+ six, and `#2a1530` / `#3d3010` / `#1a2a40` / `#2a2340` / `#1a3a38` on the five light
189
+ ramps, because a 90° gradient has two ends and one label has to clear both.
190
+ - **`kits/paperclip/` — the React reference kit**, the six-name spine plus seven signature
191
+ components: `CapsuleCurtain`, `SectionBadge`, `HairlineGrid`, `OrgNode`, `LedgerRow`,
192
+ `ScheduleLane`, `Terminal`. `src/styles.css` opens with the token layer byte for byte,
193
+ and four of the seven carry `container-type: inline-size`, so no component in the kit is
194
+ sized by the screen.
195
+ - **`T29` in `test/scenarios.md`** — the operator register and its fork against the
196
+ console, with the negative branch, and a second rejected pack because `ora` now sits
197
+ inside the same silhouette. **Written and not yet run**, and the scenario says so in its
198
+ own Result line rather than in a footnote.
199
+
200
+ ### Fixed — in the pack, against its own reference
201
+
202
+ - **`--info` is derived and marked derived.** The reference's dark block overrides five
203
+ status *icon* colours and leaves the four base status colours at their light values, so
204
+ `--status-task-in_progress` renders at **3.83:1** on the coal field and is set as text
205
+ (`● 1 live`). The pack ships `#60a5fa`, the 400 step of the same ramp, at 7.79:1.
206
+ - **The focus ring is kept.** The reference's one text input sets `outline: none` on focus
207
+ and replaces the ring with a 1px border colour change.
208
+ - **Two 1.5s infinite loops are stopped under `prefers-reduced-motion`.** `dotPulse` and
209
+ `statusBlink` survive the reference's own reduced-motion blocks, which do calm the hero,
210
+ the parallax, the marquee tracks and the modal.
211
+ - **The budget bar animates `transform: scaleX()`**, not `width` for 1.2s per bar with six
212
+ bars in view.
213
+
214
+ ### Changed
215
+
216
+ - **Four reciprocal fork clauses.** `instrument-console`, `workbench` and `orchard` each
217
+ gain one against `paperclip`; `ora` and `paperclip` gain the pair in both directions,
218
+ which is the one edge no gate could have asked for — neither pack existed in the other's
219
+ tree, so `validate_fork_reciprocity()` had nothing to check. The two are the closest in
220
+ the library: both dark by default, both refusing a brand hue, both spending the accent as
221
+ the inverted field. Three tests separate them, and both packs now carry all three.
222
+ - Counts moved from nineteen to twenty in the README, `bin/cli.js`, the three manifests,
223
+ `SURFACE_COMPOSITION.md`, `MOBILE_SURFACES.md` and `DESIGN_SYNC_BRIDGE.md`; the
224
+ `@role non-text:` tally is recomputed (fourteen of twenty, from thirteen of nineteen) and
225
+ the accent tally with it (eighteen, from seventeen).
226
+ - `/sheleg-design`'s by-name fast path said "the fourteen are" over a list of nineteen —
227
+ a count no gate reads, because it has no counted noun after it. It now says twenty and
228
+ lists them.
229
+ - `SKILL.md`'s core-contract paragraph: six of the twenty, the other fourteen.
230
+
7
231
  ## [1.29.0] - 2026-08-14
8
232
 
9
233
  A nineteenth pack, **`tenor`**, and the first one in the library extracted from a
package/README.md CHANGED
@@ -11,7 +11,7 @@ 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
13
  methodology** for cinematic, scroll-driven pages, **a motion doctrine** that
14
- decides whether to animate before it decides how, and **nineteen locked style
14
+ decides whether to animate before it decides how, and **twenty locked style
15
15
  packs** with ready-made design tokens, so what it builds reads as one system
16
16
  instead of a pile of effects.
17
17
 
@@ -64,6 +64,7 @@ into the cinematic layer, and says so in its own *Motion flavor* section.
64
64
  | `roster` | a white field in a faint grid of squares, hairlines instead of shadows, a display set in the **body** face while the section heads take another, and one orange that may never carry a word | products whose argument is **who already carries them** — AI-search and GEO visibility, SEO and content platforms, agencies, marketplaces, integration-led tooling |
65
65
  | `ora` | a warm coal field with cream ink and **no third hue** — the accent is the inverted field, so the one solid object on a page is the one meant to be pressed — a serif doing the sans job over a monospace that carries every machine fact, a terminal surface cut *below* the page plane, a six-step verdict ramp, and dark as the default theme rather than the option | products whose output is **a machine's verdict about the reader** — agent-readiness and crawlability scores, SEO and answer-engine audits, agent-run traces, MCP and protocol surfaces, bot observability |
66
66
  | `tenor` | warm paper with **zero radius and zero shadow anywhere**, a single hairline weight assembling every lattice, and one orange that exists only on hover and on focus — so the page screenshots with no colour in it at all — a sans held at weight 400 and tracked negative against a mono tracked positive, display at a line-height below one in an eight-to-twelve-character measure, and proof delivered as silent looping video in a 1px rectangle | products arguing a **management thesis** — that a new kind of thing has to be run like an existing organisation: AI-workforce and agent-operations platforms, autonomous back-office, revenue and sales operations, sold to the director who will have to manage it |
67
+ | `paperclip` | neutral coal with **no functional colour at all** — every control monochrome, elevation made of hairlines, and the whole chromatic budget spent on a curtain of 96 gradient capsules and twelve gradient section badges that cannot be clicked — a tight grotesque over a plain one over a monospace, and the capsule as the shape of everything from a button to a 10 × 20 schedule tick | products that ask a person to **run something that runs itself** — agent teams and orchestrators, autonomous back-office, schedulers, job runners, budget-governed compute |
67
68
 
68
69
  Each pack locks palette, type, texture, motion tokens, signature motifs and
69
70
  bans — and ships a `tokens/<pack>.css` to copy verbatim, so the agent never
@@ -138,7 +139,7 @@ skills.
138
139
  | `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 |
139
140
  | `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 |
140
141
  | `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 |
141
- | `styles/*.md` | The nineteen style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
142
+ | `styles/*.md` | The twenty style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
142
143
  | `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) |
143
144
  | `styles/STYLE_PACK_TEMPLATE.md` | The pack contract as a skeleton, so a new style is authored against the same headings rather than improvised |
144
145
 
@@ -209,7 +210,7 @@ cd ./ds-workbench && npm install && npm run build
209
210
  then `/design-sync` in that directory, from Claude Code. Three layers cross: the
210
211
  pack's **bans** as the design system's own README, `styles.css` built from
211
212
  `tokens/<pack>.css` verbatim, and the components — a six-name spine that is
212
- identical in all nineteen kits, so switching packs swaps identity rather than API,
213
+ identical in all twenty kits, so switching packs swaps identity rather than API,
213
214
  plus each pack's signature parts. **Motion does not cross**, exactly as it does
214
215
  not cross into Figma: a kit is the static half of a pack, and saying so is what
215
216
  stops an agent inventing motion to fill the silence.
@@ -255,7 +256,7 @@ a pack's four widened sections used to make two gates *quieter* and still green.
255
256
  One honest limit: the npx installer is checked by asserting its runtime bundle
256
257
  walker exists, not by reading a file list — it has none by design. What proves
257
258
  it ships the right files is CI, which installs the bundle through **both**
258
- installers and `diff -r`s the result against the source, then builds all nineteen
259
+ installers and `diff -r`s the result against the source, then builds all twenty
259
260
  kits.
260
261
 
261
262
  `test/scenarios.md` (T1–T19) is the behavioral harness: fresh subagents given a
package/bin/cli.js CHANGED
@@ -234,7 +234,7 @@ ${c("bold", "What it installs")}
234
234
  DESIGN_SYNC_BRIDGE.md the Claude Design contract (what a pack sends, and
235
235
  what does not cross)
236
236
  AI_PRODUCT_PATTERNS.md chat / agent / streaming surfaces (honest state)
237
- styles/ nineteen style packs — instrument-console (dark console),
237
+ styles/ twenty style packs — instrument-console (dark console),
238
238
  editorial-luxury (warm editorial), workbench (light/dark
239
239
  product UI), briefing-room (dark 16:9 presentation deck),
240
240
  atrium (warm cream consumer health), orchard (friendly
@@ -255,7 +255,10 @@ ${c("bold", "What it installs")}
255
255
  whose accent is the inverted field, a serif over mono,
256
256
  and a terminal cut below the page), tenor (warm paper at
257
257
  zero radius and zero shadow, one orange that exists only
258
- on hover, and proof delivered as silent looping video) —
258
+ on hover, and proof delivered as silent looping video),
259
+ paperclip (neutral coal with no functional colour at all
260
+ and one curtain of gradient capsules that cannot be
261
+ clicked, for products that run themselves) —
259
262
  plus a ready-made token CSS per pack and
260
263
  STYLE_PACK_TEMPLATE.md for authoring more
261
264
  `);
@@ -52,7 +52,11 @@ exists only on hover and on focus, a sans at weight 400 tracked negative
52
52
  against a mono tracked positive, display at a line-height below one in an
53
53
  eight-to-twelve-character measure, and proof delivered as silent looping
54
54
  video, for products arguing that a new kind of thing must be managed like an
55
- existing organisation);
55
+ existing organisation; paperclip — neutral coal with no functional colour
56
+ anywhere, every control monochrome and elevation made of hairlines, the whole
57
+ chromatic budget spent on a curtain of gradient capsules and a row of gradient
58
+ section badges that cannot be clicked, for products that ask a person to run
59
+ something that runs itself);
56
60
  otherwise follow the contract below (self-contained on purpose).
57
61
 
58
62
  ## Whether to animate at all — before how
@@ -0,0 +1,14 @@
1
+ {
2
+ "pkg": "@sheleg-design/paperclip",
3
+ "globalName": "ShelegPaperclip",
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,62 @@
1
+ # Paperclip — the design contract
2
+
3
+ The reference is <https://paperclip.ing>, measured 2026-08-14 from the two shipped
4
+ stylesheets (`/_next/static/chunks/0sw-z-v7xc9dd.css`, 622 rules, and
5
+ `/_next/static/chunks/19xj4kovk13jy.css`, 712 rules), the hero's inline SVG and the
6
+ `@font-face` block. Both themes read. The full pack is `styles/paperclip.md`; this file
7
+ is what a design agent must not get wrong.
8
+
9
+ ## The one thing this pack is
10
+
11
+ **No functional colour, and one loud object that does nothing.** A neutral coal field,
12
+ every control monochrome, elevation made of hairlines — and the entire chromatic budget
13
+ spent on a curtain of gradient capsules behind the headline and a row of gradient section
14
+ badges, neither of which can be clicked. Delete every colour from this page and it loses
15
+ its poster, not its meaning.
16
+
17
+ ## Non-negotiable
18
+
19
+ - **The accent is the inverted field.** Solid `--accent`, label in `--accent-ink`, capsule
20
+ radius, one per viewport. A brand hue has nowhere to live here.
21
+ - **A coloured thing is never interactive.** No gradient button, no gradient link, no
22
+ hover on a badge. This is the rule the whole composition rests on.
23
+ - **Status is never by colour alone.** `--good` and `--warn` separate by 6.2 under
24
+ protanopia and `--good` and `--info` by 6.7 under tritanopia — both below the 8.0
25
+ floor — and in the light theme `--good` (2.28:1) and `--warn` (2.15:1) are below the
26
+ 3:1 non-text floor on paper. Every dot, ring, tint and bar carries its word.
27
+ - **The capsule is the shape.** `--r-pill` on the button, the badge, the org node and the
28
+ 10 × 20 schedule mark alike. A circle is a point; a capsule is a paperclip's end. The
29
+ avatar is the single circle in the system, and the data bar's flat 4px the single
30
+ square-ended form.
31
+ - **Elevation is a hairline.** One resting shadow exists in the whole pack and it belongs
32
+ to the modal. No card floats, and the sticky nav gains nothing on scroll.
33
+ - **In light there is no surface step.** `--bg` and `--surface` are the same white. A grey
34
+ card fill turns this pack into a generic dashboard in one commit.
35
+ - **The tracking closes as the size opens** — −0.01em at 16px through −0.045em at 44px.
36
+ A 60px headline at the default 0em is the fastest way to lose the pack.
37
+ - **One noise recipe, on saturated surfaces only.** `fractalNoise`, `baseFrequency 2.95`,
38
+ 5 octaves, seed 9, tiled at 256px, `mix-blend-mode: overlay` under `isolation: isolate`
39
+ — 12% on a badge, 86% on the artwork. The field itself stays flat colour.
40
+ - **One stagger, 140ms, everywhere.** The org tree, the swimlanes, the goal cascade and
41
+ the card reveals share it. Change it in one place or not at all.
42
+ - **Hover is colour, border and fill. Never geometry.** Nothing lifts, scales or shifts.
43
+
44
+ ## What the reference gets wrong, and this kit does not
45
+
46
+ - `--status-task-in_progress` stays at its light value on the dark field — **3.83:1**,
47
+ set as text. The kit ships `#60a5fa` at 7.79:1 and marks it derived.
48
+ - The one text input sets `outline: none` on focus and replaces the ring with a 1px border
49
+ colour change. Keep the ring.
50
+ - Two 1.5s infinite loops (`dotPulse`, `statusBlink`) survive `prefers-reduced-motion`.
51
+ Stop them; their meaning is already in the word beside them.
52
+ - The budget bar transitions `width` for 1.2s, per bar, six bars in view. Never that —
53
+ `transform: scaleX()` from a left origin.
54
+ - There is no `@media (hover: hover)` anywhere, so every hover state fires on first touch.
55
+ - `font-weight: 450` is asked for and only 400 and 500 are loaded, as static instances.
56
+
57
+ ## Container, not viewport
58
+
59
+ Four components size against their own box and carry `container-type: inline-size`:
60
+ `HairlineGrid`, `OrgNode`, `LedgerRow`, `ScheduleLane`. The page's own breakpoints — the
61
+ nav, the hero padding, the artwork offset, the section rhythm — stay on the viewport,
62
+ because the page is not inside anybody's container.
@@ -0,0 +1,46 @@
1
+ # @sheleg-design/paperclip
2
+
3
+ The React reference kit for the SHELEG **Paperclip** style pack — a neutral coal field
4
+ with no functional colour at all, every control monochrome, elevation made of hairlines,
5
+ and the whole chromatic budget spent on one curtain of gradient capsules that cannot be
6
+ clicked.
7
+
8
+ It is generated from the pack, not authored beside it: `src/styles.css` opens with
9
+ `styles/tokens/paperclip.css` byte for byte, and the rules the design agent must obey are
10
+ in [`.design-sync/conventions.md`](./.design-sync/conventions.md).
11
+
12
+ ```bash
13
+ npm install && npm run build
14
+ ```
15
+
16
+ Then run `/design-sync` in Claude Code from this directory to push it to
17
+ claude.ai/design.
18
+
19
+ ## The spine, and this pack's seven
20
+
21
+ `Button`, `Card`, `Chip`, `Stat`, `Heading` and `Rule` are identical in name, props and
22
+ types across every SHELEG kit — switching packs swaps identity, not API.
23
+
24
+ | Component | What it is |
25
+ |---|---|
26
+ | `CapsuleCurtain` | 96 gradient capsules from one hue-rotation rule, under a noise mask — the **signature element** |
27
+ | `SectionBadge` | a mono uppercase label on one of twelve ramps, each with its own hand-picked ink |
28
+ | `HairlineGrid` | the gap *is* the rule: 1px over a border-coloured background, clipped by the container's radius |
29
+ | `OrgNode` | a capsule node at 1.5px, whose live state is a word and not only a ring |
30
+ | `LedgerRow` | a spend row in tabular figures whose bar is white and animates `scaleX`, never `width` |
31
+ | `ScheduleLane` | a swimlane whose ticks are 10 × 20 capsules and whose active tick says what it is doing |
32
+ | `Terminal` | the only warm surface in the pack, with a concentric tab group machined into its bar |
33
+
34
+ ## Container queries, not viewport queries
35
+
36
+ `HairlineGrid`, `OrgNode`, `LedgerRow` and `ScheduleLane` each take
37
+ `container-type: inline-size` and collapse against **their own width**. A three-across
38
+ grid dropped into a 320px sidebar on a 1440px screen keeps its columns and overflows
39
+ otherwise — which is the bug a kit's viewport query always becomes.
40
+
41
+ ## Two themes, one token layer
42
+
43
+ Dark is the default; `data-theme="light"` is the twin. The dark border token is *alpha*
44
+ (`#ffffff1a`), so the same hairline reads correctly over the field, over `--surface` and
45
+ over the warm terminal without being restated. In light there is no surface step at all —
46
+ `--bg` and `--surface` are the same white — and that is the theme's whole idea.
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@sheleg-design/paperclip",
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,23 @@
1
+ ---
2
+ category: Actions
3
+ ---
4
+
5
+ `primary` is the inverted field: solid `--accent`, label in `--accent-ink`, and the
6
+ capsule radius the whole pack is built from. **Its hover is theme-dependent and that is
7
+ deliberate** — on paper the fill goes whiter, on coal it goes away and leaves an outline.
8
+ Copying one gesture into both themes makes the button vanish in one of them, because on
9
+ paper there is nowhere brighter to go and on coal there is nowhere darker.
10
+
11
+ `secondary` is the pack's single exception to the capsule: `--r-md`, a hairline border,
12
+ a `--muted` label. It exists for the path that is not being recommended — the reference
13
+ spends it once, on `or install the local version` under the hero.
14
+
15
+ `ghost` is a text button; the label carries the whole affordance.
16
+
17
+ Nothing presses. There is no `:active` transform anywhere in this pack — hover is
18
+ colour, border and fill only.
19
+
20
+ ```tsx
21
+ <Button>Join the waitlist</Button>
22
+ <Button variant="secondary">or install the local version</Button>
23
+ ```
@@ -0,0 +1,33 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface ButtonProps {
4
+ /** `primary` is the inverted field — at most one per viewport. */
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={['pc-btn', `pc-btn--${variant}`, `pc-btn--${size}`, className]
25
+ .filter(Boolean)
26
+ .join(' ')}
27
+ disabled={disabled}
28
+ onClick={onClick}
29
+ >
30
+ {children}
31
+ </button>
32
+ );
33
+ }
@@ -0,0 +1,32 @@
1
+ ---
2
+ category: Signature
3
+ ---
4
+
5
+ **The signature element.** Eight columns on a 70px pitch, twelve 70 × 170 capsules each
6
+ at `rx: 35`, stepped 34.5px apart so every capsule covers all but a 34.5px band of the one
7
+ above it — a stack of overlapping paperclip ends falling from the top of the page.
8
+
9
+ The fills are **generated, not chosen**. The top stop rotates forward around the hue wheel
10
+ by ~12.4° per capsule and the bottom stop rotates backward by ~10.3°, at near-constant
11
+ saturation and lightness, so the two stops stay near-complementary and the column inverts
12
+ its own gradient between its first capsule and its last. The reference ships 45 gradients
13
+ and 89 distinct stops from that one rule.
14
+
15
+ Over all of it, the pack's single noise recipe — `fractalNoise`, `baseFrequency 2.95`,
16
+ 5 octaves, seed 9 — masked by the capsules themselves and composited `overlay`. Without
17
+ it a twelve-gradient artwork bands on any 8-bit panel.
18
+
19
+ **It is decoration and it must stay decoration.** `aria-hidden`, no pointer events, no
20
+ information. The composition only works when the copy sits *on top of it*: the reference
21
+ pushes the artwork up by `translateY(-310px)` so only its lower half is in frame and gives
22
+ the headline `margin-top: 124px` to land in the curtain's lower third. A hero that puts
23
+ the art beside the copy is a different pack.
24
+
25
+ Entrance and parallax belong to the page, not to this component — 1.1s rise on
26
+ `--ease-hero`, then a native `animation-timeline: view-timeline` inside `@supports`.
27
+
28
+ ```tsx
29
+ <div className="pc-hero__art" aria-hidden>
30
+ <CapsuleCurtain />
31
+ </div>
32
+ ```