sheleg-design-skill 1.44.0 → 1.45.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 (41) hide show
  1. package/CHANGELOG.md +252 -52
  2. package/README.md +2 -1
  3. package/cursor/rules/sheleg-design.mdc +3 -2
  4. package/kits/atrium/src/styles.css +12 -1
  5. package/kits/field-notes/src/styles.css +9 -0
  6. package/kits/instrument-console/src/styles.css +26 -0
  7. package/kits/maquette/src/styles.css +6 -1
  8. package/kits/notation/src/styles.css +7 -0
  9. package/kits/prism/src/styles.css +6 -0
  10. package/kits/scoreboard/src/styles.css +15 -6
  11. package/kits/showroom/src/styles.css +10 -1
  12. package/package.json +2 -2
  13. package/plugins/sheleg-design/.claude-plugin/plugin.json +1 -1
  14. package/plugins/sheleg-design/skills/sheleg-design/MOTION_DOCTRINE.md +9 -3
  15. package/plugins/sheleg-design/skills/sheleg-design/SHELEG_DESIGN.md +2 -1
  16. package/plugins/sheleg-design/skills/sheleg-design/SKILL.md +3 -2
  17. package/plugins/sheleg-design/skills/sheleg-design/SURFACE_COMPOSITION.md +22 -7
  18. package/plugins/sheleg-design/skills/sheleg-design/styles/almanac.md +5 -3
  19. package/plugins/sheleg-design/skills/sheleg-design/styles/atrium.md +7 -0
  20. package/plugins/sheleg-design/skills/sheleg-design/styles/awning.md +2 -1
  21. package/plugins/sheleg-design/skills/sheleg-design/styles/briefing-room.md +5 -3
  22. package/plugins/sheleg-design/skills/sheleg-design/styles/editorial-luxury.md +5 -2
  23. package/plugins/sheleg-design/skills/sheleg-design/styles/instrument-console.md +26 -9
  24. package/plugins/sheleg-design/skills/sheleg-design/styles/maquette.md +3 -1
  25. package/plugins/sheleg-design/skills/sheleg-design/styles/notation.md +3 -2
  26. package/plugins/sheleg-design/skills/sheleg-design/styles/orchard.md +6 -4
  27. package/plugins/sheleg-design/skills/sheleg-design/styles/pigeonhole.md +3 -1
  28. package/plugins/sheleg-design/skills/sheleg-design/styles/prism.md +9 -5
  29. package/plugins/sheleg-design/skills/sheleg-design/styles/proscenium.md +4 -1
  30. package/plugins/sheleg-design/skills/sheleg-design/styles/router.md +4 -2
  31. package/plugins/sheleg-design/skills/sheleg-design/styles/scoreboard.md +29 -9
  32. package/plugins/sheleg-design/skills/sheleg-design/styles/showroom.md +23 -6
  33. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/atrium.css +12 -1
  34. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/field-notes.css +9 -0
  35. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/instrument-console.css +26 -0
  36. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/maquette.css +6 -1
  37. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/notation.css +7 -0
  38. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/prism.css +6 -0
  39. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/scoreboard.css +15 -6
  40. package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/showroom.css +10 -1
  41. package/plugins/sheleg-design/skills/sheleg-design/styles/workbench.md +3 -2
package/CHANGELOG.md CHANGED
@@ -4,6 +4,189 @@ 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.45.0] - 2026-08-20
8
+
9
+ **Four packs contradicted their own token layers, and the layer is what an implementer
10
+ copies.** `scoreboard` still shipped the `--accent-hover` comment the pack retracted in
11
+ 1.13.1 — *"the one orange that may carry a link"*; its elevation comment said "two soft
12
+ stacks and a hairline" where four shadows ship, called both untinted while one is 16% and
13
+ another a blue-black, and left `--shadow-panel` in no prose at all; it banned radii above
14
+ 8px while `--radius-pill: 999px` ships and its own section tick requires it.
15
+ `instrument-console` legislated four statuses and shipped two colours, prescribed a pressed
16
+ primary whose label lands at **3.06:1**, and banned "colored shadows besides
17
+ `--accent-glow`" while mandating a composite the prose never named. `showroom` gave its
18
+ signature specimen frame two different radii in two sections, with a subtraction rule keyed
19
+ to the wrong one, and shipped one hex for both `--surface-2` and `--line-weak`, so a
20
+ hairline on a sunken well is invisible. `atrium` had the same collision, unrecorded.
21
+
22
+ **Six sweeps replace nine hand edits, and they found 24 more defects on their first run:**
23
+ 16 shadow or glow tokens no prose names across 11 packs (`proscenium`'s "Elevation is three
24
+ shadows" was four), a card at two radii, three status-map errors, two more hairline
25
+ collisions, a press outside the doctrine's band, three missing base layers. The motion band
26
+ and the UI ceiling are **parsed out of `MOTION_DOCTRINE.md`** rather than restated, and
27
+ `@role drawn-on:` is how a pack declares where a colliding hairline is actually drawn.
28
+
29
+ Registers that had stopped:
30
+
31
+ - **Run stamps complete to 1.44.0** — 26 rows reconstructed from `git log`, tags and the
32
+ CHANGELOG, with `Diverged?` left honestly *unrecorded*; a release at or above 1.5.0 with
33
+ no row now fails. The register had stopped at v1.26.0, eighteen versions back, which made
34
+ the "not fired in five run stamps" retirement trigger uncomputable.
35
+ - **The palette gate's own numbers**: it claimed 71 of 121 unguarded ratio claims measured
36
+ at sixteen packs and asserted all 71 had been hand-verified. Measured today: **513 claims,
37
+ 336 guarded, 177 unguarded at 22 packs** — and the run prints that pair every time, with
38
+ the hand-verification dated for what it was. Two more restated counts went the same way.
39
+ - **`package.json` said twenty-nine packs and named 27** — `awning` and `bulletin` missing
40
+ from the surface an npm reader chooses from. It is an enumeration site now.
41
+ - **Two `## [1.35.0]` sections** under one version, and four releases in the CHANGELOG with
42
+ no tag. The duplicate is resolved; the untagged four are **reported, not created** — a tag
43
+ nobody has is not this run's to invent.
44
+ - **Every pack that bans a weight or a slant owes a base layer** and two of 29 shipped one:
45
+ `<strong>` renders 700 and `<em>` italic with no stylesheet involved, so the ban was
46
+ invisible to a grep over CSS.
47
+
48
+ Two plants found holes in the checks they were written for, and two bugs the gate found in
49
+ itself: one sweep was reading a declaration out of a header comment and silently excluding
50
+ a whole pack, and a new check emitted a different number of checks with and without git
51
+ tags, which broke the ratchet in its own self-test copy.
52
+
53
+ **Found by the release, in the release's own gate.** The untagged-release check read
54
+ `bool(tags)` as "the whole tag set is visible". A release checkout fetches the released
55
+ ref and nothing else, so at `v1.45.0` exactly one tag was present and the other 49 shipped
56
+ releases read as untagged — the release went red for a reason with nothing to do with the
57
+ release. The same commit passed on `main` because a shallow checkout fetches NO tags, the
58
+ check switched itself off, and the difference between *no view* and *a one-tag view* was
59
+ invisible. Both are named as partial now, and a partial view is disclosed rather than
60
+ answered. Verified against a `--depth 1 --branch v1.45.0` clone, which is the environment
61
+ that failed.
62
+
63
+ Checks: `validate.py` 3398 to **3543**, `validate_palette.py` 1912 to **1924**, `sloplint.py`
64
+ 635. Ten new plants, all caught; 49 planted defects across the three self-tests, 0 missed.
65
+
66
+ ## [Unreleased]
67
+
68
+ ### Four packs contradicted themselves, and six sweeps now say so
69
+
70
+ A reader copies the token layer verbatim — every pack's Palette section tells
71
+ them to — so when the layer and the prose disagree, the layer wins and the prose
72
+ lies. Nine such contradictions were filed by hand across `scoreboard`,
73
+ `instrument-console`, `showroom` and `prism`. All nine are fixed, and where the
74
+ class repeats it is a sweep with a planted defect rather than nine edits.
75
+
76
+ **`scoreboard`** shipped `--accent-hover: #e03d00; /* the one orange that may
77
+ carry a link */` — the exact permission the pack retracted in 1.13.1, still in
78
+ the file a reader copies (B-033). Its elevation comment counted "two soft stacks
79
+ and a hairline" over four shadows, called `--shadow-card` untinted when
80
+ `rgba(16, 24, 40, …)` is a blue-black, and left `--shadow-panel` in no prose at
81
+ all (B-035). Its Bans forbade "radii above 8px" while `--radius-pill: 999px`
82
+ ships and the section tick requires it, and cited `font-smooth: never` — not a
83
+ legal value of the property the pack sets, and not a property any engine
84
+ implements (B-036).
85
+
86
+ **`instrument-console`** legislated four statuses and shipped two colours, so
87
+ `var(--danger)` and `var(--info)` were undefined custom properties — invalid at
88
+ computed-value time, falling back with no error anywhere — in the pack that
89
+ required them (B-038). Its pressed primary kept a label at **3.06:1**, one row
90
+ under its own warning that `--accent-dim` is a fill and not a label (B-039). And
91
+ it called `--accent-glow` "the only permitted glow" while mandating
92
+ `--signal-glow`, a composite its prose never named — so the pack banned its own
93
+ signature motif (B-041).
94
+
95
+ **`showroom`** specified its specimen frame at `--radius-2xl` in one section and
96
+ `--radius-3xl` in another, with a subtraction rule keyed to the outer value, so
97
+ every inner radius inherited the 4px error (B-022). It shipped one hex for two
98
+ jobs — `--line-weak` and `--surface-2` are both `#edeff3`, which makes a hairline
99
+ on the sunken well 1.00:1 — and a comment naming a colour the focus ring stopped
100
+ using fourteen releases ago (B-023). Three of its motion values contradicted the
101
+ doctrine in the same bundle (B-024). **`prism`** prescribed its CTA press over
102
+ `--dur-fast` at 200 ms, past the doctrine's 100–160 ms press band, with nothing
103
+ faster in the layer to reach for.
104
+
105
+ ### Six sweeps, twenty-four findings beyond the nine
106
+
107
+ - **`validate_elevation_tokens_named()`** — every `--shadow-*` and `--*-glow` a
108
+ pack declares is named in the pack's prose. **Sixteen unnamed tokens across
109
+ eleven packs** on its first run; `proscenium`'s own "Elevation is three
110
+ shadows" turned out to be four.
111
+ - **`validate_radius_single_valued()`** — a component is given one radius. It
112
+ attributes a token to the noun that FOLLOWS it, so the nesting sentence every
113
+ pack writes reads as one rule per noun. Found `scoreboard`'s card at two radii.
114
+ - **`validate_motion_bands()`** — a press sits inside the doctrine's press band,
115
+ a duration literal in prose is not a value the layer already holds, and a
116
+ control stays under the UI ceiling. The band and the ceiling are **parsed out of
117
+ `MOTION_DOCTRINE.md`**, so the gate cannot disagree with the document it
118
+ enforces.
119
+ - **`validate_emphasis_base_layer()`** — a pack that bans a weight or a slant
120
+ ships the base rule for it. `<strong>` renders 700 and `<em>` renders italic
121
+ with no stylesheet involved, so the ban was invisible to every grep over CSS
122
+ and to every browser. Two of twenty-nine shipped one; `atrium`, `notation` and
123
+ `field-notes` now do too (B-044).
124
+ - **`validate_status_vocabulary()`** — the cross-pack status map in
125
+ `SURFACE_COMPOSITION.md` is a table, compared against every token layer with
126
+ set equality. It was prose, and wrong in three places (B-016's live half).
127
+ - **`validate_line_surface_collision()`** in the palette gate — a line token and
128
+ a surface token resolving to the same colour fail unless the layer declares
129
+ `@role drawn-on:`. Found the unrecorded instance in `atrium` and the
130
+ deliberate-but-undeclared one in `maquette`.
131
+
132
+ ### The doctrine took two corrections
133
+
134
+ "UI motion stays **under** 300 ms" is now "**at or under**", because a control may
135
+ sit on the ceiling with a reason and 301 ms is over — and a gate needs a boundary.
136
+ And the "hover/entrance motion stays sub-500ms" sentence in `SKILL.md`,
137
+ `SHELEG_DESIGN.md`, `README.md` and the Cursor rule was the wrong half of its own
138
+ contradiction: it lumped hover with entrance and set a bound that `manpage`,
139
+ `tenor`, `bulletin`, `scoreboard`, `field-notes` and `roster` all exceed with
140
+ measured values. An entrance is not UI motion, may run longer when the value is
141
+ measured, and never gates content.
142
+
143
+ ### Three registers that had stopped describing the tree
144
+
145
+ - `CHANGELOG.md` carried **two `## [1.35.0] - 2026-08-15` sections** — two runs
146
+ took the number, the tag went to the second, and the loser's notes sat *above*
147
+ the winner's, so a release extractor reading the first match would have shipped
148
+ the wrong notes. One heading now, and the superseded section says what happened.
149
+ - `docs/evidence/retro.md`'s Run stamps table stopped at `v1.26.0` while `1.44.0`
150
+ shipped — eighteen versions — so the *has not fired in five run stamps*
151
+ retirement trigger read every standing instruction as dormant. Twenty-six rows
152
+ reconstructed from `git log`, the tags and the CHANGELOG, with `Diverged?` left
153
+ *unrecorded* rather than guessed (B-037, SG-04).
154
+ - `validate_release_register()` gates all of it: no duplicate version, a stamp for
155
+ every release at or after `1.5.0`, and a missing tag reported against a declared
156
+ list. **Reported, never created** — a tag nobody has is not a gate's to invent.
157
+
158
+ ### Numbers that were restated instead of computed
159
+
160
+ - `test/validate_palette.py` asserted "71 of 121 (59%) … all 71 were recomputed by
161
+ hand … nothing is wrong today" at sixteen packs. Counted today: **513 claims,
162
+ 177 unguarded (35%) at 22 packs**, and the hand-verification covered 71 of 121
163
+ on 2026-08-12 and has never been repeated. The figures print on every run and
164
+ the comment says plainly which of them was ever verified.
165
+ - `test/validate.py` said "the six packs shipped before the widening" (seven) and
166
+ "seven of the ten widened packs" (twenty-two widened). The split is printed now.
167
+ - `package.json` said "twenty-nine locked style packs" over a list of **27** —
168
+ `awning` and `bulletin` were missing. `ENUMERATION_SITES` gained `package.json`,
169
+ which is the description npmjs.com renders: its count was already policed and
170
+ the names beside it were not.
171
+
172
+ ### Fixed
173
+
174
+ - `_root_block()` stripped no comments, so `datasheet.css` — whose header explains
175
+ the reference's rem base with `html { font-size: 8px }` — sliced a
176
+ nine-character root block and was silently excluded from two sweeps. A block
177
+ scanner that reads a comment as code skips exactly the packs whose authors
178
+ explained themselves most.
179
+ - `validate_release_register()` emitted one check when `git` could see no tags and
180
+ two when it could, so the check count moved with the environment and the floor
181
+ measured on a real checkout failed inside the self-test's copy. Both branches
182
+ emit two now.
183
+
184
+ ### Gate
185
+
186
+ `npm test` → **3543 / 1924 / 635**, floors raised in `test/floors.json` with the
187
+ delta attributed per function. Ten new plants, all watched being refused; two of
188
+ them found holes in the checks they were written for.
189
+
7
190
  ## [1.44.0] - 2026-08-19
8
191
 
9
192
  ### Degrade to calm gained an observable
@@ -552,6 +735,75 @@ accessibility defects in it, and neither was reachable without building a page.
552
735
 
553
736
  ## [1.35.0] - 2026-08-15
554
737
 
738
+ > **The number was already in use.** A concurrent run had written a
739
+ > `## [1.35.0]` section for `ledger` before this one, and `v1.35.0` tags this
740
+ > commit — so the ledger notes moved to a heading of their own, directly
741
+ > below. Standing instruction 1 in `docs/evidence/retro.md` is about exactly
742
+ > this, and it caught the collision late rather than never.
743
+
744
+ **A twenty-second pack, and the reference it was asked for did not survive measurement.**
745
+ The request was "a pack in the style of taskip.net". Taskip turned out to be WordPress and
746
+ Elementor over a bought theme (Xilancer), carrying **three token systems that disagree** —
747
+ the theme's declared primary `#6074f6` appears nowhere on the rendered page, the visible
748
+ emerald lives in a second sheet, and a third set of values is Tailwind slate. Twelve radius
749
+ values, six shadows, seven weights, four font families, and `.3s` / `0.3s` / `300ms` written
750
+ as three different things. That is a page-builder output, not a vocabulary, and this library
751
+ exists on the premise that a pack is the reference's own vocabulary rather than a
752
+ reconstruction of one. It was declined as a source and the register was re-sourced instead.
753
+
754
+ ### Added — `awning`, the twenty-second pack
755
+
756
+ Origin: <https://www.shopify.com>, read 2026-08-15 from the served HTML plus its six linked
757
+ stylesheets. Chosen after measuring five candidates on the same axes; it was the only one
758
+ that paired the register with a real system.
759
+
760
+ - **The accent is black, and it is a resolved chain rather than a stylistic absence.**
761
+ `--color-component-button-primary-bg` → `--color-theme-bg-cta` → `#000`, with hover, active
762
+ and disabled declared beside it. No hue reaches the chrome at all, which is what leaves
763
+ every colour on the page belonging to the product screenshot inside it.
764
+ - **A three-tier token layer** — primitives, semantic roles, per-component states — so the
765
+ pack ships the indirection rather than the resolved values. `--radius-component-button:
766
+ var(--radius-theme-full)` is the only place the system says *why* a button is a pill.
767
+ - **420 and 550, and no 700 anywhere.** A variable grotesque used as one. Setting a heading
768
+ in 700 here is not a small deviation; it is the one number the system was built to avoid.
769
+ - **Tracking crosses zero inside one family** — negative on the display ramp, positive on the
770
+ body ramp, crossover around 1.375rem — where most packs in this library split tracking
771
+ across two faces.
772
+ - **Leading ships paired with size in `rem`**, not as a ratio, and the ratio *changes* down
773
+ the ramp: 1.08 at display, 1.12 at t2, 1.30 at t7.
774
+ - **One shadow, three layers** — ambient, contact, and a `0 0 2px` hairline edge that is what
775
+ stops a card dissolving on pure white. That third layer is the one people drop when they
776
+ copy a shadow by eye.
777
+ - Six Gotchas, three of them defects in the reference: `--ink-faint` at **4.40:1 on the
778
+ system's own second field**; three eases named as tokens against **ten unnamed inline
779
+ durations**; and `ease-in` shipped as a token while the doctrine bans it in UI.
780
+ - Routed through all seven surfaces the validator checks, mirrored to `.cursor`, added to
781
+ `install.sh`, and shipped with `kits/awning` — the six-name spine on the canonical API plus
782
+ `ProductFrame`, `PlanCard` and `FeatureRow`.
783
+
784
+ ### Fixed
785
+
786
+ - `paperclip` and `showroom` now link **back** to `awning`. The validator caught the one-way
787
+ fork: a neighbour reference that only points one direction is a dead end for anyone who
788
+ reaches the other pack first.
789
+ - Nine stated counts moved from twenty-one to twenty-two across `SKILL.md`, `README.md`,
790
+ `package.json`, both manifests, `bin/cli.js`, `MOBILE_SURFACES.md`, `SURFACE_COMPOSITION.md`
791
+ and `DESIGN_SYNC_BRIDGE.md`, plus core-contract packs from six to seven. Every one was
792
+ caught by the gate rather than remembered.
793
+
794
+ ## [ledger — shipped inside 1.35.0] - 2026-08-15
795
+
796
+ > **Two runs took the number 1.35.0, and the tag went to the other one.**
797
+ > `v1.35.0` is `e9c0bf6`, the `awning` release below; this section's work is
798
+ > `48f24d9`, which carried `1.35.0` in every manifest and was never tagged —
799
+ > `git checkout v1.35.0` gets you both, because the ledger commit is an
800
+ > ancestor of the tag. Two identical `## [1.35.0]` headings sat here from
801
+ > 2026-08-15 until 1.45.0, the ledger one ABOVE the tagged one, so a release
802
+ > extractor reading the first match for `## [1.35.0]` would have shipped the
803
+ > wrong notes. The heading is no longer a version because the version was
804
+ > never this section's to hold, and `validate_release_register()` now refuses
805
+ > a duplicate.
806
+
555
807
  **The twenty-first pack, and two counts that had been wrong for eight releases.**
556
808
  `ledger` was extracted from `basedash.com` — a warm cream console for a product
557
809
  that answers questions about data. Adding it walked the library past twenty for
@@ -614,58 +866,6 @@ table that stopped at twenty and a regex that read one modifier word.
614
866
  check that would have caught it — a name in a context that routes to it — is
615
867
  not written.
616
868
 
617
- ## [1.35.0] - 2026-08-15
618
-
619
- **A twenty-second pack, and the reference it was asked for did not survive measurement.**
620
- The request was "a pack in the style of taskip.net". Taskip turned out to be WordPress and
621
- Elementor over a bought theme (Xilancer), carrying **three token systems that disagree** —
622
- the theme's declared primary `#6074f6` appears nowhere on the rendered page, the visible
623
- emerald lives in a second sheet, and a third set of values is Tailwind slate. Twelve radius
624
- values, six shadows, seven weights, four font families, and `.3s` / `0.3s` / `300ms` written
625
- as three different things. That is a page-builder output, not a vocabulary, and this library
626
- exists on the premise that a pack is the reference's own vocabulary rather than a
627
- reconstruction of one. It was declined as a source and the register was re-sourced instead.
628
-
629
- ### Added — `awning`, the twenty-second pack
630
-
631
- Origin: <https://www.shopify.com>, read 2026-08-15 from the served HTML plus its six linked
632
- stylesheets. Chosen after measuring five candidates on the same axes; it was the only one
633
- that paired the register with a real system.
634
-
635
- - **The accent is black, and it is a resolved chain rather than a stylistic absence.**
636
- `--color-component-button-primary-bg` → `--color-theme-bg-cta` → `#000`, with hover, active
637
- and disabled declared beside it. No hue reaches the chrome at all, which is what leaves
638
- every colour on the page belonging to the product screenshot inside it.
639
- - **A three-tier token layer** — primitives, semantic roles, per-component states — so the
640
- pack ships the indirection rather than the resolved values. `--radius-component-button:
641
- var(--radius-theme-full)` is the only place the system says *why* a button is a pill.
642
- - **420 and 550, and no 700 anywhere.** A variable grotesque used as one. Setting a heading
643
- in 700 here is not a small deviation; it is the one number the system was built to avoid.
644
- - **Tracking crosses zero inside one family** — negative on the display ramp, positive on the
645
- body ramp, crossover around 1.375rem — where most packs in this library split tracking
646
- across two faces.
647
- - **Leading ships paired with size in `rem`**, not as a ratio, and the ratio *changes* down
648
- the ramp: 1.08 at display, 1.12 at t2, 1.30 at t7.
649
- - **One shadow, three layers** — ambient, contact, and a `0 0 2px` hairline edge that is what
650
- stops a card dissolving on pure white. That third layer is the one people drop when they
651
- copy a shadow by eye.
652
- - Six Gotchas, three of them defects in the reference: `--ink-faint` at **4.40:1 on the
653
- system's own second field**; three eases named as tokens against **ten unnamed inline
654
- durations**; and `ease-in` shipped as a token while the doctrine bans it in UI.
655
- - Routed through all seven surfaces the validator checks, mirrored to `.cursor`, added to
656
- `install.sh`, and shipped with `kits/awning` — the six-name spine on the canonical API plus
657
- `ProductFrame`, `PlanCard` and `FeatureRow`.
658
-
659
- ### Fixed
660
-
661
- - `paperclip` and `showroom` now link **back** to `awning`. The validator caught the one-way
662
- fork: a neighbour reference that only points one direction is a dead end for anyone who
663
- reaches the other pack first.
664
- - Nine stated counts moved from twenty-one to twenty-two across `SKILL.md`, `README.md`,
665
- `package.json`, both manifests, `bin/cli.js`, `MOBILE_SURFACES.md`, `SURFACE_COMPOSITION.md`
666
- and `DESIGN_SYNC_BRIDGE.md`, plus core-contract packs from six to seven. Every one was
667
- caught by the gate rather than remembered.
668
-
669
869
  ## [1.34.0] - 2026-08-15
670
870
 
671
871
  **The pack was applied correctly and the result still read as somebody else's typography.**
package/README.md CHANGED
@@ -88,7 +88,8 @@ motion layer never hard-codes a palette.
88
88
  3. **Hold, then redeploy.** Hold a formation ~80% of a section, then morph in a
89
89
  short, phase-staggered, arc-curved wave. No crossfades.
90
90
  4. **Earned motion.** Scrub is for instruments that narrate state over time;
91
- entrance motion stays sub-500ms and never gates content.
91
+ hover and press stay inside the doctrine's bands, an entrance may run past
92
+ them when measured, and neither gates content.
92
93
  5. **Degrade to calm.** Reduced-motion / coarse pointer / no-WebGL collapse to a
93
94
  static, fully-legible page.
94
95
 
@@ -119,7 +119,7 @@ Frequency decides before taste gets a vote. (Full doctrine:
119
119
  `linear`. Curves: `--ease-out: cubic-bezier(.23,1,.32,1)`,
120
120
  `--ease-in-out: cubic-bezier(.77,0,.175,1)`,
121
121
  `--ease-drawer: cubic-bezier(.32,.72,0,1)`.
122
- - **UI motion stays under 300 ms.** Button press 100–160ms · tooltip 125–200ms ·
122
+ - **UI motion stays at or under 300 ms.** Button press 100–160ms · tooltip 125–200ms ·
123
123
  dropdown 150–250ms · modal/drawer 200–500ms. Marketing and scrollytelling are
124
124
  deliberately longer.
125
125
  - Never animate a property that triggers layout (`width`, `height`, `top`,
@@ -143,7 +143,8 @@ Frequency decides before taste gets a vote. (Full doctrine:
143
143
  a short, phase-staggered, arc-curved wave. Crossfades between point sets
144
144
  are banned.
145
145
  4. **Earned motion.** Scrub only for instruments that narrate state over time
146
- (charts, step flows); hover/entrance motion stays sub-500ms and never
146
+ (charts, step flows); hover and press stay inside the duration bands above,
147
+ an entrance may run past them when the value is measured, and neither ever
147
148
  gates content visibility.
148
149
  5. **Degrade to calm.** `prefers-reduced-motion` / coarse pointer / no-WebGL
149
150
  collapse to a static, fully-legible page. The effect is a bonus, never a
@@ -9,7 +9,11 @@
9
9
  --surface-ink: #2a2b2f; /* the ONE inverted surface (media wells, banner) */
10
10
  --line: #d1c9bf; /* hairline — decorative strength, see Gotchas */
11
11
  --line-strong: #737373; /* borders that carry an affordance (inputs) */
12
- --line-ink: #2a2b2f; /* ghost-control border */
12
+ /* @role drawn-on: --bg, --surface — the ghost-control border, and the SAME hex
13
+ as --surface-ink (#2a2b2f): on the inverted banner it disappears completely.
14
+ A ghost control that lands on --surface-ink borders in --on-ink instead
15
+ (13.47:1), which is what the pack's Gotchas now say. */
16
+ --line-ink: #2a2b2f;
13
17
 
14
18
  /* ---- Ink ------------------------------------------------------------- */
15
19
  --ink: #2a2b2f; /* 13.5:1 on --bg */
@@ -167,6 +171,13 @@
167
171
  color-scheme: light;
168
172
  }
169
173
 
174
+ /* The base layer. This pack bans bold outright — its entire emphasis vocabulary is
175
+ the italic terracotta aside — so `<strong>` is pointed at the one weight above
176
+ body that the system owns. Left to the UA it renders 700, a weight no face here
177
+ ships, and inside the 300-weight serif the browser fakes it. `<em>` is deliberately
178
+ untouched: italic IS this pack's emphasis, and the serif has a real one. */
179
+ strong, b { font-weight: var(--weight-semibold); }
180
+
170
181
  /* The hero effect is a bonus, never a dependency: at reduced motion the canvas
171
182
  is REMOVED and the still image underneath is the hero. Do not slow it down —
172
183
  a slow refraction is still refraction. */
@@ -288,6 +288,15 @@
288
288
  --focus-ring: var(--brand);
289
289
  }
290
290
 
291
+ /* The base layer, and it is a synthesis rule rather than a weight or a style.
292
+ Bricolage Grotesque has no italic, so an `<em>` in a display heading gets a
293
+ browser-slanted fake — the "irregularity is the whole personality" argument in the
294
+ Gotchas, undone by a shear transform. `font-synthesis-style: none` refuses the
295
+ fake without touching Geist's real italic, which the body copy does use. The
296
+ declared `font-style` is the UA's own value, stated so the rule says what it keeps
297
+ as well as what it removes. */
298
+ em, i { font-style: italic; font-synthesis-style: none; }
299
+
291
300
  /* The reference ships a reduced-motion branch for every animated class, which
292
301
  is the right posture and this pack requires it. Durations collapse; the
293
302
  reveal resolves to its final state instead of transitioning to it. */
@@ -14,15 +14,41 @@
14
14
  --accent-dim: #1f5fb0;
15
15
  --accent-bright: #6bb3ff;
16
16
  --accent-ink: #0a0e14; /* text ON the accent — 6.17:1. White on #3392ff is 3.14 and fails. */
17
+ /* Two glows, two jobs, and both are named in the pack's Bans. --accent-glow is
18
+ the translucent halo behind a focused control; --signal-glow, declared below,
19
+ is the composite box-shadow the ONE active signal element wears. Until 1.45.0
20
+ the prose called --accent-glow "the only permitted glow" and then mandated the
21
+ composite, which it never named -- so the pack banned its own signature. */
17
22
  --accent-glow: rgba(51, 146, 255, 0.18);
23
+
24
+ /* ---- Status: four roles, and the pack owns three hues ------------------
25
+ The prose has legislated success, warning, danger and info together since
26
+ this pack's first release, and the token layer shipped two of them -- so
27
+ `var(--danger)` was an undefined custom property, which is invalid at
28
+ computed-value time and falls back with no error anywhere (B-038).
29
+ --info is the signal hue by decision, not by accident: an infrastructure
30
+ console's "here is a fact" and its "here is the thing to press" are the same
31
+ blue, and giving info its own hue would break the pack's one-accent rule.
32
+ --danger is a PACK DECISION, not a measurement: the reference this pack was
33
+ read off paints no danger state, so there was nothing to measure. Chosen to
34
+ clear AA on every field this pack ships (6.02:1 on --base, 5.77 on
35
+ --surface-1, 5.10 on --surface-3) and to stay above the library's separation
36
+ floors against every peer, including under simulated CVD -- the numbers are
37
+ in the pack's Palette. */
18
38
  --ok: #46d39a;
19
39
  --warn: #e0a030;
40
+ --danger: #f4526b;
41
+ --info: var(--accent);
20
42
 
21
43
  --r-sm: 4px;
22
44
  --r-md: 8px;
23
45
  --r-lg: 14px;
24
46
  --r-pill: 999px;
25
47
 
48
+ /* THE signature shadow: the one active signal element wears it, and nothing
49
+ else on the page does. Named here and in the pack's Texture, Micro-interactions
50
+ and Bans -- a mandated composite that appears in no prose is a value a reader
51
+ has to reconstruct from a literal. */
26
52
  --signal-glow: 0 0 0 1px rgba(51, 146, 255, 0.4),
27
53
  0 8px 30px rgba(51, 146, 255, 0.18);
28
54
 
@@ -53,7 +53,12 @@
53
53
  --model-top: #fff9f4; /* the lit top face — 17.49:1 */
54
54
  --model-face: #fff3d6; /* the front face, warmer — 16.56:1 */
55
55
  --model-side: #e8ddc8; /* the side in shade */
56
- --model-line: #151515; /* the model's own outline: the field colour */
56
+ /* @role drawn-on: --model-top, --model-face, --model-side the model's
57
+ own outline, and it is the SAME hex as --bg on purpose: the cream solids are
58
+ separated by the table showing between them, which is why the model reads as
59
+ cut paper rather than as an SVG. It is drawn on the model's own faces and
60
+ never on the field, where it would be 1.00:1. */
61
+ --model-line: #151515;
57
62
  --leader: #8a8f98; /* the dotted leader from a block to its label */
58
63
 
59
64
  /* ---- Elevation: ONE shadow, and its direction is not adjustable ------- */
@@ -122,6 +122,13 @@
122
122
  data-theme="dark" from a prefers-color-scheme listener — keep one switch,
123
123
  never two sources of truth for the theme. */
124
124
 
125
+ /* The base layer. `--w-semi` and `--w-bold` are both 500 because this pack has no
126
+ bold — emphasis is the serif, the mono or a rule — so `<strong>` resolves to that
127
+ 500 rather than to the UA's 700, which is the one weight the system does not
128
+ contain. Without this rule the ban lived only in the Bans list, where no browser
129
+ reads it. */
130
+ strong, b { font-weight: var(--w-bold); }
131
+
125
132
  @media (prefers-reduced-motion: reduce) {
126
133
  :root {
127
134
  --dur-state: 0s;
@@ -125,6 +125,12 @@
125
125
 
126
126
  /* ---- Motion ----------------------------------------------------------- */
127
127
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
128
+ /* Three durations, and the press has its own because the doctrine gives press
129
+ feedback a band of its own: 100-160 ms. Until 1.45.0 this layer held two, the
130
+ pack prescribed --dur-fast for the press, and 200 ms is 40 ms past the top of
131
+ that band with nothing faster in the layer to reach for. --dur-fast stays at
132
+ the reference's 200 ms for hover and colour, which is inside the UI ceiling. */
133
+ --dur-press: 0.14s;
128
134
  --dur-fast: 0.2s;
129
135
  --dur-base: 0.3s;
130
136
 
@@ -50,7 +50,11 @@
50
50
  marks": a 3x18px tick, a chip edge, a rule. --accent-ink is the one that may carry a
51
51
  word, and the 1.13.1 correction says no orange here may carry a link. */
52
52
  --accent: #ff4801;
53
- --accent-hover: #e03d00; /* 4.12:1 on --bg — the one orange that may carry a link */
53
+ /* 4.12:1 on --bg — the hover step of a MARK, and it may not carry a link either.
54
+ 1.13.0 called this "the one orange that may carry a link"; 1.13.1 retracted that
55
+ in the pack's Gotchas and left the sentence here, where a reader copies it. A
56
+ link is --ink with an --accent underline. */
57
+ --accent-hover: #e03d00;
54
58
  --accent-wash: #fff7ed; /* MEASURED — selected row, hovered cell */
55
59
  /* The accent's one filled use: a selected chip. 4.92:1 under --on-accent,
56
60
  which clears AA; white on the same fill is 3.40:1 and does not. The accent
@@ -105,11 +109,16 @@
105
109
  --chart-grid: #e4e4e7;
106
110
  --chart-axis: #71717b;
107
111
 
108
- /* ---- Elevation: two soft stacks and a hairline ------------------------ */
109
- /* MEASURED. Both stacks are two layers at 4–5% and neither is tinted. This
110
- pack lifts almost nothing: a card is a 1px --line-weak rule with the
111
- hairline under it, and --shadow-card is for the one report surface a
112
- section is built around. */
112
+ /* ---- Elevation: a hairline, a panel wash, one stack and one lift ------ */
113
+ /* MEASURED. Four shadows, and the pack's Texture section names all four:
114
+ --shadow-hairline (1 layer, 2.5%) sits under every card; --shadow-panel
115
+ (1 layer, 4%) is the [data-surface="panel"] band's own seat; --shadow-card
116
+ (2 layers, 5% and 5%, and it IS tinted — rgba(16,24,40) is a blue-black, on
117
+ purpose: the report surface is the one place the page reads as screen rather
118
+ than paper) is for the one report surface a section is built around; and
119
+ --shadow-lift (1 layer, 16%, untinted) is for something genuinely floating.
120
+ This pack lifts almost nothing: a card is a 1px --line-weak rule with the
121
+ hairline under it. */
113
122
  --shadow-hairline: 0 1px 2px 0 rgba(0, 0, 0, 0.025);
114
123
  --shadow-panel: 0 1px 6px rgba(0, 0, 0, 0.04);
115
124
  --shadow-card:
@@ -37,6 +37,11 @@
37
37
  --disabled: #a4adba;
38
38
 
39
39
  /* ---- Lines: elevation is a ring plus a stack, never a single shadow ---- */
40
+ /* @role drawn-on: --bg, --surface — --line-weak is the SAME hex as --surface-2
41
+ (#edeff3), so a hairline in it is invisible on the sunken well. That is a
42
+ decision, not an accident: hairlines in this pack are drawn on the paper and
43
+ on the card, never inside the well. If a rule is genuinely needed there it is
44
+ --line, which measures 1.24:1 against the well. */
40
45
  --line-weak: #edeff3;
41
46
  --line: #d3d8df;
42
47
  --line-strong: #cad0d9;
@@ -46,7 +51,11 @@
46
51
  the same blue can be a link and a filled button without a second token. */
47
52
  --accent: #266df0;
48
53
  --accent-hover: #245bc2;
49
- --accent-soft: #94b9ff; /* the focus ring's colour, and chart tint */
54
+ /* Chart tint and the selected-row edge. NOT the focus ring: --ring-focus is
55
+ derived from --accent below, at 35% alpha, and said so from 1.30.0 -- this
56
+ comment went on naming the ring for fourteen releases after the ring stopped
57
+ using it, in the layer a reader copies verbatim. */
58
+ --accent-soft: #94b9ff;
50
59
  --accent-wash: #e8f0ff; /* selected row, hovered cell */
51
60
  --on-accent: #ffffff;
52
61
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sheleg-design-skill",
3
- "version": "1.44.0",
4
- "description": "Design taste as an installable agent skill. Cinematic scroll-driven landing pages built on one scroll clock and layered degrade-to-calm motion, a motion doctrine that decides whether to animate before it decides how, three calibration dials, and twenty-nine locked style packs with ready-made design tokens — instrument-console, editorial-luxury, workbench, briefing-room, atrium, orchard, field-notes, cyclorama, showroom, blueprint, prism, maquette, scoreboard, datasheet, manpage, pigeonhole, roster, ora, tenor, paperclip, ledger, router, daylight, notation, almanac, vitrine and proscenium. Colour, slop and fork-reciprocity gates run as scripts, not opinions. Works with Cursor, Claude Code and any agent that reads a SKILL.md.",
3
+ "version": "1.45.0",
4
+ "description": "Design taste as an installable agent skill. Cinematic scroll-driven landing pages built on one scroll clock and layered degrade-to-calm motion, a motion doctrine that decides whether to animate before it decides how, three calibration dials, and twenty-nine locked style packs with ready-made design tokens — instrument-console, editorial-luxury, workbench, briefing-room, atrium, orchard, field-notes, cyclorama, showroom, blueprint, prism, maquette, scoreboard, datasheet, manpage, pigeonhole, roster, ora, tenor, paperclip, ledger, router, daylight, notation, almanac, vitrine, proscenium, awning and bulletin. Colour, slop and fork-reciprocity gates run as scripts, not opinions. Works with Cursor, Claude Code and any agent that reads a SKILL.md.",
5
5
  "bin": {
6
6
  "sheleg-design-skill": "bin/cli.js"
7
7
  },
@@ -2,7 +2,7 @@
2
2
  "name": "sheleg-design",
3
3
  "displayName": "SHELEG Design",
4
4
  "description": "SHELEG Design methodology: cinematic scroll-driven landing pages (single scroll clock, layered degrade-to-calm motion, WebGL particle formations), a motion doctrine that decides whether to animate before it decides how, and twenty-nine pluggable visual style packs — instrument-console (dark console), editorial-luxury (warm editorial), workbench (light/dark product UI for dashboards and tools), briefing-room (dark 16:9 deck), atrium (warm consumer health), orchard (friendly consumer biotech), field-notes (warm paper for dev tools sold on auditability), cyclorama (a pastel field on a 32s cycle), showroom (the product as the exhibit), blueprint (a drawing sheet, zero radius), prism (one iridescent wash over mono body), maquette (cream axonometric models on a dark table), scoreboard (warm paper, pixel numerals, a dark ledger of results), datasheet (an off-white spec sheet whose live instrument goes dark when it detects the reader is hiding), manpage (a developer landing page set in the reader's own system monospace on cream paper, with coral label chips that are real headings and a dark code frame as the argument), pigeonhole (a white sorting wall whose nine pastel categories are a filing scheme rather than a mood, each a two-layer chip whose label word is mandatory), roster (a white field in a faint grid of squares whose argument is other people's marks — client logotypes in pill-labelled industry columns, an engine's wordmark inside the headline — where the proof is a name rather than a number), ora (a warm coal field with cream ink and no third hue — the accent is the inverted field — a serif carrying every human sentence over a monospace carrying every machine fact, a terminal surface cut below the page, and a six-step verdict ramp, for products whose output is a machine's verdict about the reader), tenor (warm paper with zero radius and zero shadow, one hairline weight, an orange that exists only on hover and on focus, a sans tracked negative against a mono tracked positive, display at a line-height below one in an eight-to-twelve-character measure, and product proof delivered as silent looping video, for products arguing that a new kind of thing must be managed like an existing organisation), paperclip (neutral coal with no functional colour at all — every control monochrome and elevation made of hairlines, with the whole chromatic budget spent on a curtain of gradient capsules and twelve gradient section badges that cannot be clicked — for products that ask a person to run something that runs itself: agent teams, autonomous back-office, schedulers and budget-governed compute), ledger (warm cream paper ruled by a hairline at 12% ink and no shadow on any card, radius 15 nested concentrically, an ink primary button and a terracotta accent that never fills a control — it labels, as a 10px monospace uppercase kicker — with a seal on every card stating how its number is known, for the console of a product that answers questions about data: AI analysts, BI surfaces, query workspaces), router (a near-white field with a trace of blue and white cards standing on it, hairline seams instead of shadows anywhere, body at 14px and weight 450, and a status triplet in which the colour you paint with is not the colour you write with, for product consoles and the landing pages that have to look like them), daylight (a cool near-white portal field with generous radii and one very large soft shadow spent on a single object per screen, for client portals), notation (a near-white page drawn entirely in hairlines with a light serif over a monospace, no bold anywhere and an ink primary, for developer products sold on restraint), almanac (oatmeal paper with 2px seams and no 1px anywhere, a display set below a line-height of one, and mono tags notched through drawn boxes, for pages that assert a category), vitrine (a white hairline field with a serif display, an ink primary and one framed record carrying the evidence, for the front door of a product sold on trust). Ships the sheleg-design skill, the architecture reference, the motion doctrine, the Figma and Claude Design bridges, AI-surface patterns, style packs with ready-made token CSS, and the /sheleg-design command, and awning (a white forecourt where the accent is black and no hue reaches the chrome at all, a pill whose radius is a declared component token, one variable grotesque at 420/550 with no 700, and a single three-layer shadow, for commerce and platform front doors), and proscenium (a white field carrying two cool acts and one deep indigo act at the middle, an electric violet filling a control that stays nearly square at 4px against cards at 16, one family at nine weights, and a framed product panel the fold cuts off, for product-led marketing front doors whose argument is a demonstration), and bulletin (warm cream paper cut by flat pastel bands, every card and control a 1px ink outline standing on a hard zero-blur ink offset it travels into when pressed, a display face at 800 inside controls and 700 in the headline, and no tracking at any size, for front doors whose argument is breadth).",
5
- "version": "1.44.0",
5
+ "version": "1.45.0",
6
6
  "author": {
7
7
  "name": "ssheleg",
8
8
  "url": "https://x.com/sshlg93"
@@ -100,8 +100,14 @@ names its curve explicitly. A pack that ships no curve inherits these three, and
100
100
  | Modals, drawers, sheets | 200–500 ms |
101
101
  | Marketing, explanatory, scrollytelling | longer, deliberately |
102
102
 
103
- **UI motion stays under 300 ms.** A 180 ms select feels responsive; the same
104
- select at 400 ms feels like the app is thinking.
103
+ **UI motion stays at or under 300 ms.** A 180 ms select feels responsive; the
104
+ same select at 400 ms feels like the app is thinking. The boundary is stated
105
+ because a gate applies it: 300 ms is the ceiling itself and a control may sit on
106
+ it with a reason, 301 ms is over. **An entrance is not UI motion** and is not
107
+ bounded by this number — it may run longer when the value is measured off a
108
+ reference, provided it never gates content and the pack says which of the two
109
+ rules its token answers to. `--dur-reveal` at 500 ms and `--dur-fast` at 150 ms
110
+ are both correct; the same 500 ms on a button is not.
105
111
 
106
112
  Speed is not only comfort — it is perceived performance. A faster spinner makes
107
113
  an identical load feel shorter. A tooltip that skips its delay after the first
@@ -261,7 +267,7 @@ Before calling motion done:
261
267
  - [ ] Every animation survives the "why does this move?" sentence.
262
268
  - [ ] Nothing on the 100+/day path animates at all.
263
269
  - [ ] No `ease-in` in UI; curves are named, not inherited by accident.
264
- - [ ] UI durations under 300 ms; the table was consulted, not guessed.
270
+ - [ ] UI durations at or under 300 ms; entrances declared as entrances; the table was consulted, not guessed.
265
271
  - [ ] No banned form from §5 appears anywhere in the diff.
266
272
  - [ ] Every `scrub` carries `ease: "none"`.
267
273
  - [ ] Every ScrollTrigger has a cleanup path.
@@ -49,7 +49,8 @@ The five principles that make it work:
49
49
  then morphs in a short, phase-staggered, arc-curved wave — points fly to new
50
50
  posts. Crossfades are banned.
51
51
  4. **Earned motion.** Scrubbed animation belongs to instruments that narrate
52
- state over time. Hover/entrance motion is sub-500ms and never gates content.
52
+ state over time. Hover and press stay inside the doctrine's bands; an entrance
53
+ may run past them when the value is measured, and never gates content.
53
54
  5. **Degrade to calm.** `prefers-reduced-motion` / coarse pointer / no-WebGL all
54
55
  collapse to a static, fully-legible page. The effect is an enhancement, never
55
56
  a dependency.