sheleg-design-skill 1.31.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,65 @@ 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
+
7
66
  ## [1.31.0] - 2026-08-14
8
67
 
9
68
  **T29 ran, and the pack it was written for did not survive it intact.** Both branches
@@ -17,11 +17,25 @@
17
17
  a section as a different room (the reference spends it on one band and on
18
18
  the closing panel), and it never appears inside a card. */
19
19
  --paper: #f7f6f2;
20
+ /* The two materials. Everything here is one of them, a step between them, or
21
+ the one hue — and naming the coal is what lets the dark band say
22
+ `--ink: var(--paper)` instead of restating a literal that then has to agree. */
23
+ --coal: #10100f;
20
24
  --bg: var(--paper); /* the family's core role name */
21
25
  --bg-deep: #eeece6; /* --paper-deep */
22
26
 
23
- --ink: #10100f; /* 17.61:1 on --bg */
24
- --ink-soft: #777773; /* 4.16:1 — see the pack's Gotchas before setting body copy in it */
27
+ --ink: var(--coal); /* 17.61:1 on --bg */
28
+ --ink-soft: #777773; /* 4.16:1 as measured — it FAILS AA; prose takes --ink-soft-aa */
29
+ /* DERIVED — the value above is the reference's, and it does not clear AA;
30
+ Gotcha 1 records that. The remedy that Gotcha used to give, #6f6f6b, clears
31
+ the floor on the paper and reaches only 4.27 against the deeper field —
32
+ which this pack spends on a whole section, so the remedy failed on the
33
+ pack's own second room. This is the smallest step that holds on both:
34
+ --ink-soft-aa is 4.95:1 on --bg,
35
+ and --ink-soft-aa is 4.53:1 on --bg-deep.
36
+ Set prose in this; keep --ink-soft for the tracked mono labels, where it is
37
+ used at caps and the reference's value is what was read. */
38
+ --ink-soft-aa: #6b6b67;
25
39
  --ink-faint: #a3a29d; /* 2.36:1 — the hero's grey clause, and it fails even AA-large */
26
40
 
27
41
  /* Separation is a hairline over ink at 16%, and there is no second border
@@ -36,11 +50,23 @@
36
50
  when you touch something, not what the page looks like. */
37
51
  --orange: #e9672a;
38
52
  --accent: var(--orange); /* 3.02:1 on --bg — a fill and a ring, never a word */
39
- --accent-ink: var(--paper); /* text ON the accent — 3.02:1, so large text only; see the pack's Gotchas */
53
+ /* CORRECTED, and it is the one place this pack overrules its reference. The
54
+ site puts the paper on its orange fills, and
55
+ --paper is 3.02:1 on --accent
56
+ — the same figure as the fill on the field, because contrast is symmetric,
57
+ so every CTA in the reference fails AA at the moment it is hovered
58
+ (Gotcha 3). The coal on the same fill clears it outright:
59
+ --accent-ink is 5.84:1 on --accent.
60
+ The orange does not change between the paper page and the dark band, so
61
+ neither does the only label that can be read on it — which is why this is
62
+ `var(--coal)` rather than `var(--ink)`, and why the dark block below does
63
+ not override it. */
64
+ --accent-ink: var(--coal); /* text ON the accent */
40
65
 
41
66
  /* @role non-text: --accent, --warn — 3.02:1 on --bg. The orange is a fill, a
42
- 25px lockup square and the 2px focus ring; the reference never sets a word
43
- in it and neither may you. Both clear the 3:1 non-text floor and neither
67
+ 25px lockup square and the 2px focus ring; nothing set in the ORANGE carries
68
+ a word. (Text ON the orange is a different measurement and a different token:
69
+ see --accent-ink above.) Both clear the 3:1 non-text floor and neither
44
70
  clears AA. */
45
71
 
46
72
  /* ── severity is VALUE, not hue ──────────────────────────────────────────
@@ -63,6 +89,17 @@
63
89
  --good: #296b46;
64
90
  --warn: var(--orange);
65
91
  --danger: var(--ink);
92
+ /* DERIVED — the accent pushed onto the value axis until it can carry a word.
93
+ `--warn` is the orange because that is what the reference does, and on a
94
+ marketing page warn is always a fill or a chip. A product surface sets warn
95
+ as TEXT — a count, a retention tag, a table cell — and at 3.02:1 the orange
96
+ cannot. This is the same hue pushed down the value axis until it can:
97
+ --warn-ink is 6.47:1 on --bg,
98
+ and --warn-ink is 5.93:1 on --bg-deep.
99
+ Use --warn for the mark (the dot, the 3px edge rule, the fill) and
100
+ --warn-ink for the word beside it; they are the same severity in two roles,
101
+ which is the pattern --sev-ask/--sev-limit/--sev-never already sets. */
102
+ --warn-ink: #94400f;
66
103
 
67
104
  /* The staircase's two middle rungs. The only oklch in the reference and the
68
105
  only achromatic values in it: pure neutrals sitting between a warm paper and
@@ -169,15 +206,30 @@
169
206
  [data-surface="dark"] {
170
207
  color-scheme: dark;
171
208
 
172
- --bg: #10100f;
173
- --bg-deep: #10100f;
174
- --ink: #f7f6f2; /* 17.61:1 on --bg */
209
+ --bg: var(--coal);
210
+ /* DERIVED — the reference aliases this to the field, because a band has no
211
+ hover and no resting chip and therefore needs no second room. A product
212
+ surface has both (see the pack's `## Product surface`), and a token that
213
+ resolves to the field it sits on is a rule that silently does nothing.
214
+ Paper at 8% over the coal, and everything still clears AA on it:
215
+ --ink is 14.73:1 on --bg-deep,
216
+ --ink-soft is 6.31:1 on --bg-deep,
217
+ --good is 7.07:1 on --bg-deep.
218
+ And --bg-deep is 1.20:1 on --bg — a different room rather than an elevation
219
+ step, which is exactly what --bg-deep means on the paper, where the same
220
+ pair is 1.09:1. */
221
+ --bg-deep: #222221;
222
+ --ink: var(--paper); /* 17.61:1 on --bg */
175
223
  --ink-soft: #a4a3a0; /* paper at 64% over the ink — 7.55:1 */
224
+ /* On this field the accent is 5.84:1 and clears AA outright, so warn keeps the
225
+ real hue here; the value-axis variant exists for the paper alone. */
226
+ --warn-ink: var(--orange);
176
227
  --ink-faint: #7f7e7c; /* paper at 48% — 4.69:1, labels only */
177
228
  --line: rgb(247 246 242 / 0.2);
178
229
  --line-light: rgb(16 16 15 / 0.16);
179
230
 
180
- --accent-ink: #f7f6f2;
231
+ /* --accent-ink is deliberately NOT overridden: the orange is the same orange
232
+ on both fields, so the one label that can be read on it is the same coal. */
181
233
  --sev-limit: #4a4a48;
182
234
  /* DERIVED, same reasoning as the light block and re-measured on this field:
183
235
  8.45:1 on --bg, and 10.7 from the accent under deuteranopia. A surface
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sheleg-design-skill",
3
- "version": "1.31.0",
3
+ "version": "1.32.0",
4
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 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 and paperclip. 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"
@@ -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 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). 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.",
5
- "version": "1.31.0",
5
+ "version": "1.32.0",
6
6
  "author": {
7
7
  "name": "ssheleg",
8
8
  "url": "https://x.com/sshlg93"
@@ -3,7 +3,7 @@ name: sheleg-design
3
3
  description: Use when building or upgrading a cinematic scroll-driven landing page, marketing site or hero (particle/WebGL background, scroll-linked animation, parallax, scrubbed sections) — when such a page feels busy or janky or its motion layers drift out of sync — or when styling product UI with its style packs - dashboards, admin panels, internal/dev tools, mobile app screens, design tokens, light/dark themes - or when carrying a visual system across the Figma border (publishing tokens as variables, implementing a design without importing raw values). Triggers - "cinematic landing" / "кинематографичный лендинг", "scroll animation" / "скролл-анимация", "dashboard style" / "стиль дашборда", "design tokens" / "дизайн-токены", "light/dark theme" / "светлая/тёмная тема", "figma variables / figma to code" / "переменные фигмы, фигма в код", "chat/agent UI" / "интерфейс чата или агента", "streaming output" / "стриминг ответа", "mobile screen" / "мобильный экран".
4
4
  license: MIT
5
5
  metadata:
6
- version: 1.31.0
6
+ version: 1.32.0
7
7
  ---
8
8
 
9
9
  # SHELEG Design
@@ -39,7 +39,11 @@ ambient gradient, so `MOTION_INTENSITY` above **4** has nothing legal to buy.
39
39
  **Not for:** consumer, playful or brand-led registers where colour carries
40
40
  identity — there is one hue here and it only appears under the cursor. Not for
41
41
  dense operator chrome: with no radius, no shadow and one border weight, a fourth
42
- nested panel has nothing to sit on, and that is `workbench`'s half. Not for a
42
+ nested panel has nothing to sit on, and that is `workbench`'s half. That refusal
43
+ is narrower than it reads, and
44
+ [On a product surface](#on-a-product-surface) measures where it actually bites —
45
+ a dashboard's panels and stat lattice carry the pack unchanged; a status chip
46
+ repeated down a table column is where the single hairline stops separating. Not for a
43
47
  page whose argument is an accumulating figure (`scoreboard`) or a documentation
44
48
  page whose focal element is a command (`manpage`).
45
49
 
@@ -67,21 +71,41 @@ verbatim instead of transcribing this table.
67
71
  | `--bg` | `#f7f6f2` | the page, and the fill of anything that is not inverted | — |
68
72
  | `--bg-deep` | `#eeece6` | a different room, not a raised surface | 1.09:1 |
69
73
  | `--ink` | `#10100f` | display, headings, every filled control | 17.61:1 |
70
- | `--ink-soft` | `#777773` | supporting prose and mono labels | 4.16:1 |
74
+ | `--ink-soft` | `#777773` | the tracked mono labels — **not prose**, see Gotcha 1 | 4.16:1 |
75
+ | `--ink-soft-aa` | `#6b6b67` | **derived** — supporting prose, on either field | 4.95:1 |
71
76
  | `--ink-faint` | `#a3a29d` | the hero's grey clause, and nothing smaller | 2.36:1 |
72
77
  | `--line` | `rgb(16 16 15 / 0.16)` | the only border weight in the system | — |
73
78
  | `--accent` | `#e9672a` | hover fill, focus ring, one 25px lockup square | 3.02:1 |
74
- | `--accent-ink` | `#f7f6f2` | text ON the accent | — |
79
+ | `--accent-ink` | `#10100f` | text ON the accent — **corrected**, see below | — |
75
80
  | `--good` | `#296b46` | **derived** — success on a product surface | 5.91:1 |
76
- | `--warn` | `#e9672a` | attention, and it is the accent | 3.02:1 |
81
+ | `--warn` | `#e9672a` | attention as a **mark**, and it is the accent | 3.02:1 |
82
+ | `--warn-ink` | `#94400f` | **derived** — attention as a **word** | 6.47:1 |
77
83
  | `--danger` | `#10100f` | prohibition, and it is the ink | 17.61:1 |
78
84
 
85
+ **`--accent-ink` is the coal, and this is the one place the pack overrules its
86
+ reference.** The site puts the paper on its orange fills, which measures 3.02:1 —
87
+ the same figure as the fill on the field, because contrast is symmetric — so
88
+ every CTA in the reference fails AA at the instant it is hovered. The coal on
89
+ that same fill measures **5.84:1**. Since the orange does not change between the
90
+ paper page and the dark band, neither does the only label that can be read on it,
91
+ which is why the token layer declares `--accent-ink` once and the dark block does
92
+ not override it. The consequence is worth stating plainly: **the hover fill is
93
+ legal after all.** Gotcha 3 used to route around it by moving the border instead
94
+ of the fill; that workaround is no longer the answer.
95
+
79
96
  **The dark band is a section, not a theme.** `[data-surface="dark"]` inverts one
80
97
  strip inside a paper page — the reference uses it for the use-case grid and the
81
98
  footer, and never for a whole page. Its greys are composites of the paper over
82
99
  the ink, which is why they are neutral rather than a second warm ramp: `--ink`
83
100
  `#f7f6f2` at 17.61:1, `--ink-soft` `#a4a3a0` at 7.55:1, `--ink-faint` `#7f7e7c`
84
- at 4.69:1, and `--good` re-derived to `#57c08c` at 8.45:1.
101
+ at 4.69:1, and `--good` re-derived to `#57c08c` at 8.45:1. On this field the
102
+ orange clears AA on its own, so `--warn-ink` is remapped back to the accent — the
103
+ value-axis variant exists for the paper alone.
104
+
105
+ `--bg-deep` on the band is **derived** rather than measured: the reference aliases
106
+ it to the field, because a band has no hover and no resting chip and therefore
107
+ needs no second room. `#222221` is paper at 8% over the coal, and a product
108
+ surface has both — see [On a product surface](#on-a-product-surface).
85
109
 
86
110
  **The accent is a hover state.** This is the pack's whole colour argument, so it
87
111
  is stated before anything else follows from it. At rest the page has one orange
@@ -90,10 +114,13 @@ other appearance is triggered — a filled control turning orange under the
90
114
  cursor, the 2px focus ring, one guardrail chip that means *ask first*. Three
91
115
  consequences: a page can be screenshotted with no colour in it at all and still
92
116
  be this pack; a resting orange fill is a design error rather than a variant; and
93
- because the orange sits at 3.02:1 on the paper, **it may never carry a word**.
94
- Contrast is symmetric, so paper on the orange is the same 3.02:1 — a label on an
95
- orange fill needs large text (24px, or 18.66px bold) to be conformant, and the
96
- reference's two orange-filled elements are both below that. See Gotchas.
117
+ because the orange sits at 3.02:1 on the paper, **nothing may be set in it**.
118
+
119
+ Text *on* the orange is the other direction and a different measurement, and the
120
+ two get conflated: the paper on it is the same 3.02:1, but the coal on it is
121
+ 5.84:1. So the rule has two halves and only one of them is a prohibition — the
122
+ orange never colours a word, and a word may sit on the orange provided it is
123
+ `--accent-ink`. See Gotcha 3.
97
124
 
98
125
  **Severity is value, not hue.** The guardrail chips prove it in one row: `ALWAYS
99
126
  ASK` is the orange, `LIMIT` is a grey, `NEVER` is the ink. Three levels, one hue,
@@ -231,9 +258,55 @@ disabled; where the reference paints no such state, the derivation is marked.
231
258
  loading state on a marketing surface; on a product surface, a 1px `--line`
232
259
  skeleton whose geometry matches the block it replaces, and no spinner.
233
260
  - **Empty states.** Also absent from the reference. Derived: a mono label, one
234
- sentence of `--ink-soft` prose in the `32ch` measure, and the single action
261
+ sentence of `--ink-soft-aa` prose in the `32ch` measure, and the single action
235
262
  that fills it, as a section CTA. No illustration.
236
263
 
264
+ ### On a product surface
265
+
266
+ Everything above is measured off a marketing page. The pack is also spent on the
267
+ dashboards and admin screens behind such a page, and five things break there that
268
+ a page never exercises. Each answer below is **derived**; all were found by
269
+ mounting the pack on a populated twenty-route dashboard rather than reasoned about.
270
+
271
+ - **There is no dark theme, and a product that has one needs a decision.** The
272
+ reference inverts a band inside a paper page; it never inverts the page. A
273
+ product with a theme toggle has three options and only the third is honest:
274
+ drop the toggle, invent a second ramp (which is inventing values), or **promote
275
+ the band's own measured greys to a theme** and add the one thing a band does
276
+ not have — a second field, `--bg-deep` `#222221`. Take the third and say so,
277
+ because a reader who knows the pack will otherwise assume the dark screens were
278
+ extracted and they were not.
279
+ - **Ranking by value costs the link its affordance.** With `--accent` moved onto
280
+ the ink so it can carry a word, a link is the same colour as the sentence
281
+ beside it. The pack already owns the fix and spends it only in the header: the
282
+ rule under the word whose origin flips, `right` at rest and `left` on hover.
283
+ Use it for a section's action link. For a link repeated down a table, use a
284
+ plain static underline in `--line` instead — fifty animated rules is the
285
+ "more than one marquee" ban wearing a different costume.
286
+ - **The selected row of a rail is the lattice cell's inversion, held open.** Not
287
+ an accent tint: there is no second hue to tint with, and `--accent-weak` on
288
+ this pack is just the deeper paper. Fill it `--ink`, set the label `--bg`, and
289
+ drop any suffix count to 63% — the same treatment a capability cell takes on
290
+ hover.
291
+ - **A column of chips is where the hairline stops working, and it is the pack's
292
+ own density warning made specific.** One border weight, no radius and no fill
293
+ means fifteen status chips down a table column read as a texture rather than as
294
+ fifteen states. The threshold measured here: a lattice of chips is legible
295
+ while they are *comparable and few* — a header row, a summary strip — and stops
296
+ being legible the moment they repeat per row. In a table, drop the box and set
297
+ the status as the word alone in its severity value, with `--warn` kept for the
298
+ mark beside it. Panels and tiles are unaffected: the same lattice at four cells
299
+ across a dashboard's stat row reads exactly as it does on the page.
300
+ - **Prose sits on two fields at once and `--ink-soft` fails on the second.** This
301
+ is what produced `--ink-soft-aa`; see Gotcha 1.
302
+
303
+ What does **not** change on a product surface: the spacing scale and the type
304
+ ramp. Tenor's section rhythm is `clamp(40px, 4.5vw, 64px)` and its display slope
305
+ runs to 8rem in an 8–12ch measure — both are page values, and a dashboard has
306
+ neither a section rhythm nor display type. Keep the product's own scale and take
307
+ the pack's *surface*: the field, the zero radius, the single hairline, the hue
308
+ that only appears under the cursor, and the two tracking ramps.
309
+
237
310
  ## Hero
238
311
 
239
312
  Four elements and no more: the investor lockup, the two-clause headline, the
@@ -411,24 +484,43 @@ reference itself, which is exactly why a copy of it inherits them.
411
484
  **4.16:1** on the paper, and it carries every lead paragraph and every
412
485
  supporting sentence at `clamp(1rem, 1.35vw, 1.25rem)` — 16px at the small end,
413
486
  which is not large text. It is short of 4.5:1 by a margin no one will notice
414
- and every audit will. Darken it to at least `#6f6f6b` for prose, or reserve it
415
- for the mono labels where it is used at tracked caps.
487
+ and every audit will. Reserve it for the mono labels, where it is used at
488
+ tracked caps, and set prose in `--ink-soft-aa`.
489
+
490
+ **The remedy this Gotcha used to give was itself short.** It said "darken it
491
+ to at least `#6f6f6b`", which clears the floor on the paper at 4.67:1 and
492
+ reaches only **4.27:1** on `--bg-deep` — a field the pack spends on a whole
493
+ section, so the fix failed on the pack's own second room and did so silently,
494
+ because nobody re-measures a remedy. `--ink-soft-aa` `#6b6b67` is 4.95:1 and
495
+ 4.53:1, the smallest step that holds on both. Found by putting the pack on a
496
+ product surface where muted text sits on both fields at once.
416
497
  2. **`--ink-faint` sets the hero and fails even the large-text floor.** At
417
498
  `#a3a29d` it is **2.36:1**, below the 3:1 that large text is allowed. It
418
499
  carries the grey half of the headline at 40.8px to 74.4px. The device is worth
419
500
  keeping and the value is not: the pack's rule is that the muted clause must
420
501
  clear 3:1, which is `#8a8985` or darker on this paper.
421
- 3. **The accent clears its floor by 0.02, and both of its filled elements sit on
422
- the wrong side of it.** `#e9672a` is **3.02:1** on `#f7f6f2` — legal as a
423
- non-text mark, with no margin at all, so one step lighter and the focus ring
424
- stops being conformant. Contrast is symmetric, so a paper label on an orange
425
- fill is the same 3.02:1, and both places the reference fills with orange put a
426
- label on it below the large-text threshold: the investor lockup's `Y` at
427
- 12.5px, and **every CTA at the moment it is hovered**, where the mono label at
428
- ~10.4px falls from 17.61:1 to 3.02:1. The rule this pack takes from the
429
- measurement: the orange may fill a control whose label is decorative or
430
- duplicated elsewhere, and a control whose label is the only statement of what
431
- it does keeps its ink fill and moves its **border** to the accent instead.
502
+ 3. **The accent clears its floor by 0.02, and the reference puts the wrong label
503
+ on it.** `#e9672a` is **3.02:1** on `#f7f6f2` — legal as a non-text mark, with
504
+ no margin at all, so one step lighter and the focus ring stops being
505
+ conformant. Contrast is symmetric, so a *paper* label on an orange fill is the
506
+ same 3.02:1, and both places the reference fills with orange put one there
507
+ below the large-text threshold: the investor lockup's `Y` at 12.5px, and
508
+ **every CTA at the moment it is hovered**, where the mono label at ~10.4px
509
+ falls from 17.61:1 to 3.02:1.
510
+
511
+ **The fix is the label, not the fill.** The coal on that same orange is
512
+ **5.84:1** — it clears AA at any size, on the paper page and on the dark band
513
+ alike, because the orange is the same orange in both. So a hovered control
514
+ changes two properties rather than one: the fill goes to `--accent` and the
515
+ label goes to `--accent-ink`. Nothing has to give up the hover fill, which is
516
+ this pack's most recognisable interaction.
517
+
518
+ *This entry used to end differently.* It said the orange may fill only a
519
+ control whose label is decorative or duplicated, and that a control whose
520
+ label is its only statement should keep its ink fill and move its **border**
521
+ to the accent. That workaround was derived from measuring one direction and
522
+ never the other; it is superseded, and a page still following it is not
523
+ wrong, only more cautious than it needs to be.
432
524
  4. **A variable font is loaded across two axes and used at one point.**
433
525
  Instrument Sans is requested as `wdth,wght@75..100,400..600`; the stylesheet
434
526
  contains zero `font-stretch` declarations, zero `font-variation-settings`, and
@@ -17,11 +17,25 @@
17
17
  a section as a different room (the reference spends it on one band and on
18
18
  the closing panel), and it never appears inside a card. */
19
19
  --paper: #f7f6f2;
20
+ /* The two materials. Everything here is one of them, a step between them, or
21
+ the one hue — and naming the coal is what lets the dark band say
22
+ `--ink: var(--paper)` instead of restating a literal that then has to agree. */
23
+ --coal: #10100f;
20
24
  --bg: var(--paper); /* the family's core role name */
21
25
  --bg-deep: #eeece6; /* --paper-deep */
22
26
 
23
- --ink: #10100f; /* 17.61:1 on --bg */
24
- --ink-soft: #777773; /* 4.16:1 — see the pack's Gotchas before setting body copy in it */
27
+ --ink: var(--coal); /* 17.61:1 on --bg */
28
+ --ink-soft: #777773; /* 4.16:1 as measured — it FAILS AA; prose takes --ink-soft-aa */
29
+ /* DERIVED — the value above is the reference's, and it does not clear AA;
30
+ Gotcha 1 records that. The remedy that Gotcha used to give, #6f6f6b, clears
31
+ the floor on the paper and reaches only 4.27 against the deeper field —
32
+ which this pack spends on a whole section, so the remedy failed on the
33
+ pack's own second room. This is the smallest step that holds on both:
34
+ --ink-soft-aa is 4.95:1 on --bg,
35
+ and --ink-soft-aa is 4.53:1 on --bg-deep.
36
+ Set prose in this; keep --ink-soft for the tracked mono labels, where it is
37
+ used at caps and the reference's value is what was read. */
38
+ --ink-soft-aa: #6b6b67;
25
39
  --ink-faint: #a3a29d; /* 2.36:1 — the hero's grey clause, and it fails even AA-large */
26
40
 
27
41
  /* Separation is a hairline over ink at 16%, and there is no second border
@@ -36,11 +50,23 @@
36
50
  when you touch something, not what the page looks like. */
37
51
  --orange: #e9672a;
38
52
  --accent: var(--orange); /* 3.02:1 on --bg — a fill and a ring, never a word */
39
- --accent-ink: var(--paper); /* text ON the accent — 3.02:1, so large text only; see the pack's Gotchas */
53
+ /* CORRECTED, and it is the one place this pack overrules its reference. The
54
+ site puts the paper on its orange fills, and
55
+ --paper is 3.02:1 on --accent
56
+ — the same figure as the fill on the field, because contrast is symmetric,
57
+ so every CTA in the reference fails AA at the moment it is hovered
58
+ (Gotcha 3). The coal on the same fill clears it outright:
59
+ --accent-ink is 5.84:1 on --accent.
60
+ The orange does not change between the paper page and the dark band, so
61
+ neither does the only label that can be read on it — which is why this is
62
+ `var(--coal)` rather than `var(--ink)`, and why the dark block below does
63
+ not override it. */
64
+ --accent-ink: var(--coal); /* text ON the accent */
40
65
 
41
66
  /* @role non-text: --accent, --warn — 3.02:1 on --bg. The orange is a fill, a
42
- 25px lockup square and the 2px focus ring; the reference never sets a word
43
- in it and neither may you. Both clear the 3:1 non-text floor and neither
67
+ 25px lockup square and the 2px focus ring; nothing set in the ORANGE carries
68
+ a word. (Text ON the orange is a different measurement and a different token:
69
+ see --accent-ink above.) Both clear the 3:1 non-text floor and neither
44
70
  clears AA. */
45
71
 
46
72
  /* ── severity is VALUE, not hue ──────────────────────────────────────────
@@ -63,6 +89,17 @@
63
89
  --good: #296b46;
64
90
  --warn: var(--orange);
65
91
  --danger: var(--ink);
92
+ /* DERIVED — the accent pushed onto the value axis until it can carry a word.
93
+ `--warn` is the orange because that is what the reference does, and on a
94
+ marketing page warn is always a fill or a chip. A product surface sets warn
95
+ as TEXT — a count, a retention tag, a table cell — and at 3.02:1 the orange
96
+ cannot. This is the same hue pushed down the value axis until it can:
97
+ --warn-ink is 6.47:1 on --bg,
98
+ and --warn-ink is 5.93:1 on --bg-deep.
99
+ Use --warn for the mark (the dot, the 3px edge rule, the fill) and
100
+ --warn-ink for the word beside it; they are the same severity in two roles,
101
+ which is the pattern --sev-ask/--sev-limit/--sev-never already sets. */
102
+ --warn-ink: #94400f;
66
103
 
67
104
  /* The staircase's two middle rungs. The only oklch in the reference and the
68
105
  only achromatic values in it: pure neutrals sitting between a warm paper and
@@ -169,15 +206,30 @@
169
206
  [data-surface="dark"] {
170
207
  color-scheme: dark;
171
208
 
172
- --bg: #10100f;
173
- --bg-deep: #10100f;
174
- --ink: #f7f6f2; /* 17.61:1 on --bg */
209
+ --bg: var(--coal);
210
+ /* DERIVED — the reference aliases this to the field, because a band has no
211
+ hover and no resting chip and therefore needs no second room. A product
212
+ surface has both (see the pack's `## Product surface`), and a token that
213
+ resolves to the field it sits on is a rule that silently does nothing.
214
+ Paper at 8% over the coal, and everything still clears AA on it:
215
+ --ink is 14.73:1 on --bg-deep,
216
+ --ink-soft is 6.31:1 on --bg-deep,
217
+ --good is 7.07:1 on --bg-deep.
218
+ And --bg-deep is 1.20:1 on --bg — a different room rather than an elevation
219
+ step, which is exactly what --bg-deep means on the paper, where the same
220
+ pair is 1.09:1. */
221
+ --bg-deep: #222221;
222
+ --ink: var(--paper); /* 17.61:1 on --bg */
175
223
  --ink-soft: #a4a3a0; /* paper at 64% over the ink — 7.55:1 */
224
+ /* On this field the accent is 5.84:1 and clears AA outright, so warn keeps the
225
+ real hue here; the value-axis variant exists for the paper alone. */
226
+ --warn-ink: var(--orange);
176
227
  --ink-faint: #7f7e7c; /* paper at 48% — 4.69:1, labels only */
177
228
  --line: rgb(247 246 242 / 0.2);
178
229
  --line-light: rgb(16 16 15 / 0.16);
179
230
 
180
- --accent-ink: #f7f6f2;
231
+ /* --accent-ink is deliberately NOT overridden: the orange is the same orange
232
+ on both fields, so the one label that can be read on it is the same coal. */
181
233
  --sev-limit: #4a4a48;
182
234
  /* DERIVED, same reasoning as the light block and re-measured on this field:
183
235
  8.45:1 on --bg, and 10.7 from the accent under deuteranopia. A surface