@felloinnovations/brand-kit 0.5.0 → 0.5.1

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 (59) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +24 -0
  3. package/README.md +6 -4
  4. package/design-system/01-how-claude-decides.md +1 -1
  5. package/design-system/03-colour.md +3 -2
  6. package/design-system/08-choosing-components.md +1 -1
  7. package/design-system/09-charts.md +1 -1
  8. package/design-system/10-patterns.md +1 -1
  9. package/design-system/13-motion.md +3 -3
  10. package/design-system/17-decisions.md +10 -0
  11. package/design-system/components/CheckRow/README.md +1 -1
  12. package/design-system/components/CheckRow/preview.html +1 -1
  13. package/design-system/components/CheckRow/style.css +1 -1
  14. package/design-system/components/KanbanBoard/README.md +1 -1
  15. package/design-system/components/KanbanBoard/style.css +1 -1
  16. package/design-system/components/ListDetail/preview.html +1 -1
  17. package/design-system/components/Matrix/README.md +1 -1
  18. package/design-system/components/Matrix/preview.html +1 -1
  19. package/design-system/components/Motion/README.md +2 -2
  20. package/design-system/components/Motion/preview.html +8 -8
  21. package/design-system/components/README.md +1 -1
  22. package/design-system/components/ScoreHero/README.md +2 -2
  23. package/design-system/components/ScoreHero/style.css +1 -1
  24. package/design-system/components/ShareBar/README.md +1 -1
  25. package/design-system/components/ShareBar/style.css +1 -1
  26. package/design-system/components/Skeleton/README.md +17 -16
  27. package/design-system/components/Skeleton/preview.html +1 -1
  28. package/design-system/components/Skeleton/style.css +9 -14
  29. package/design-system/components/Starter/README.md +1 -1
  30. package/design-system/components/Starter/preview.html +1 -1
  31. package/design-system/components/Table/README.md +1 -1
  32. package/design-system/components/Table/preview.html +1 -1
  33. package/design-system/components/Table/style.css +1 -1
  34. package/design-system/components/TickStrip/README.md +1 -1
  35. package/design-system/components/TickStrip/preview.html +1 -1
  36. package/design-system/components/TickStrip/style.css +1 -1
  37. package/design-system/components/Timeline/README.md +1 -1
  38. package/design-system/components/Well/README.md +1 -1
  39. package/design-system/components/Well/style.css +2 -2
  40. package/design-system/components/_house.css +1 -1
  41. package/design-system/components/bundle.css +18 -23
  42. package/design-system/tokens.json +3 -7
  43. package/dist/fello-core.css +2 -2
  44. package/dist/fello.css +2 -2
  45. package/dist/fello.scoped.css +2 -2
  46. package/dist/index.d.ts +2 -2
  47. package/dist/scoped.js +2 -2
  48. package/dist/tokens.d.ts +8 -8
  49. package/dist/tokens.js +8 -8
  50. package/package.json +1 -1
  51. package/tokens/_dark.css +1 -2
  52. package/tokens/_product.css +11 -11
  53. package/tokens/palettes.ts +1 -1
  54. package/tokens/shadcn-compat.css +1 -1
  55. package/tokens/shadcn-compat.hsl.css +1 -1
  56. package/tokens/tokens.css +10 -15
  57. package/tokens/tokens.md +4 -5
  58. package/tokens/tokens.root.css +10 -15
  59. package/tokens/tokens.ts +9 -9
package/AGENTS.md CHANGED
@@ -1,4 +1,4 @@
1
- # brand-kit for coding agents (0.5.0)
1
+ # brand-kit for coding agents (0.5.1)
2
2
 
3
3
  Read this before writing UI in any Fello project that uses `@felloinnovations/brand-kit`. It ships inside the
4
4
  package at `node_modules/@felloinnovations/brand-kit/AGENTS.md`. The HubSpot website (felix-theme) is out of scope:
@@ -24,7 +24,7 @@ All paths are under `node_modules/@felloinnovations/brand-kit/`.
24
24
  | `scripts/check-palette.mjs` | Checks an app's own palette file against the contract (Palettes, below). |
25
25
 
26
26
  The same guide is hosted, always current, at `https://brand-kit-site-production.up.railway.app/latest/llms.txt`
27
- (pinned copies under `/v/0.5.0/`).
27
+ (pinned copies under `/v/0.5.1/`).
28
28
 
29
29
  ---
30
30
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1 (10 Nov 2026)
4
+
5
+ Loaders are calm: the shimmer is one quiet grey. Amit looked at the skeletons in an app built on the kit and did not
6
+ like the salmon, purple and green tints sweeping every grey ghost block (Decisions, 10 Nov 2026).
7
+
8
+ - **The shimmer is one neutral tone.** `--ws-shimmer` is the ghost grey with a lighter pass of the same grey, no chart
9
+ hues, in light, night, the navy ground and every palette. North's timing stays: 1.8 s on `--ws-loop-shimmer` and
10
+ `--ws-ease-shimmer`, the 300 % band at 100 deg; still under reduced motion. Every ghost that wears the shimmer
11
+ (Skeleton, a pending Stat, StatTiles, Table, Well, TickStrip, ShareBar, ScoreHero and the rest) changes with no
12
+ markup change.
13
+ - **One ghost grey at rest and in motion.** `--ws-shimmer-ground` is now `--ws-ghost` (#E3DFDB, the night's #273544),
14
+ so a ghost shows on the cream (1.29:1) and on the tray (1.13:1) alike, and the still ghost under reduced motion is the
15
+ same grey. Skeleton's own ground for a card's foot or band is gone.
16
+ - **The chart ghost's colour band is gone.** `ws-skeleton__chart`'s bars are ghosts under the same shimmer; the band
17
+ that crossed the drawing in blend mode colour is removed (a neutral band there would paint nothing).
18
+ - **The docs say so**: the Skeleton card and preview, the Motion card (the shimmer row is now Close, the chart band row
19
+ Not yet), Colour, Motion, Patterns, Charts, Choosing components and every loading line in the catalog.
20
+ - **Pinned links keep working**: `/v/0.5.0/` is kept as a snapshot (`hosted/v/0.5.0`), so a page pinned to it still
21
+ loads after the bump. Pinned links in the docs now point at `/v/0.5.1/`.
22
+
23
+ **Upgrading from 0.5.0**: nothing to change. A copy of the old gradient, or of #ECE8E4 as the shimmer's grey, should
24
+ become `var(--ws-shimmer)` or `var(--ws-shimmer-ground)`. `StatusLine`'s working words keep their colours for now (open
25
+ in Decisions).
26
+
3
27
  ## 0.5.0 (4 Nov 2026)
4
28
 
5
29
  The kit the whole team can trust: teams kept hitting alignment, spacing and placement bugs, and Seth (the designer) has
package/README.md CHANGED
@@ -112,7 +112,7 @@ Then point the repo's agents at the guide: paste the block at the end of [AGENTS
112
112
  One line, pinned to a version:
113
113
 
114
114
  ```html
115
- <link rel="stylesheet" href="https://brand-kit-site-production.up.railway.app/v/0.5.0/fello.css">
115
+ <link rel="stylesheet" href="https://brand-kit-site-production.up.railway.app/v/0.5.1/fello.css">
116
116
  ```
117
117
 
118
118
  Then use the `ws-*` classes and `var(--token)`; the markup for each component is in the gallery. `/latest/` exists
@@ -183,11 +183,13 @@ is no longer maintained. Only the kit's owners (Amit and Arpan) change tokens.
183
183
 
184
184
  ## Releasing
185
185
 
186
- CI publishes. Bump `version` in `package.json` (and `plugin/.claude-plugin/plugin.json`, and the pinned `/v/` links
187
- in `skill/SKILL.md`), run `yarn build` and `yarn skill`, commit, then push a tag that matches:
186
+ CI publishes. Before the bump, keep the released hosted tree: `yarn hosted`, then copy `site-dist/v/<released
187
+ version>` to `hosted/v/` (the gallery serves every snapshot there, so pinned links keep working). Bump `version` in
188
+ `package.json` and the pinned `/v/` links (`AGENTS.md`, `skill/SKILL.md`, this README, `Starter`, guide 01; the plugin is
189
+ unversioned), run `yarn build` and `yarn skill`, commit, then push a tag that matches:
188
190
 
189
191
  ```sh
190
- git tag v0.5.0 && git push origin v0.5.0
192
+ git tag v0.5.1 && git push origin v0.5.1
191
193
  ```
192
194
 
193
195
  `.github/workflows/publish.yml` checks the tag matches `package.json`, builds, and publishes to npm through npm's
@@ -57,7 +57,7 @@ rest; a mockup about to ship takes all steps.
57
57
  | Where | Setup |
58
58
  | --- | --- |
59
59
  | A claude.ai artifact | inline `fello-core.css` plus the styles of only the components used, in one `<style>` (an artifact loads stylesheets only from Google Fonts; the whole `fello.css` is too big to paste) |
60
- | A plain HTML page or a static site | link the pinned file: `https://brand-kit-site-production.up.railway.app/v/0.5.0/fello.css` |
60
+ | A plain HTML page or a static site | link the pinned file: `https://brand-kit-site-production.up.railway.app/v/0.5.1/fello.css` |
61
61
  | A Next, Vite or Turbo app that owns its page | install `@felloinnovations/brand-kit`, import `fello.css` (it sits in Tailwind's layers, so utilities win) or `tokens.css` (Tailwind v4), with the Instrument Sans `@import` first (before `@import "tailwindcss"`) or a `<link>`; read its `AGENTS.md` |
62
62
  | An app inside a host it does not own (a shared bundle, a platform's guest app), or any Tailwind v3 app | the scoped build: `fello.scoped.css`, or the string from `@felloinnovations/brand-kit/scoped` injected in a `<style>`, under `class="fello"` on the app's root and on every portal's root; nothing outside it changes; it carries no font, so link Instrument Sans (the `brand-adopt` skill has the steps) |
63
63
  | Claude Design or Slides | this system is the organisation's default; nothing to load |
@@ -40,7 +40,7 @@ positive. Marks keep Seth's exact tones; a word in a tone takes its AA step on t
40
40
  | The ink of a wash, a ring or a line of your own; the tint of a drop | `ws-ink`, `ws-shade` | navy (in dark, the heading's light ink and black) |
41
41
  | A floating navy message (a toast, the note tip) and the footer, and their words | `ws-inverse`, `ws-on-inverse` | the act and its words; in dark the brand navy and white |
42
42
  | An off control (a switch's track at rest) | `ws-control-off` | #7F7F7F |
43
- | The loading shimmer's ground | `ws-shimmer-ground` | #ECE8E4 |
43
+ | The loading shimmer's ground: the ghost grey, with a lighter pass of the same grey (never a chart hue) | `ws-shimmer-ground` | #E3DFDB (`ws-ghost`) |
44
44
  | A hero's glows, an assistant's working orb | `ws-glow-rose`, `ws-glow-pink`, `ws-glow-blue`, `ws-orb` | from the chart tones |
45
45
  | Focus | `ws-focus-color` | navy |
46
46
  | Behind a dialog | `ws-scrim` | navy 35% |
@@ -99,7 +99,8 @@ Never a state by colour alone: a word or a mark goes with it.
99
99
  - **An assistant's mark** takes one of the four tones and keeps it; no other colour names it.
100
100
  - **The AI colours** (`color-ai-*`) exist only inside an assistant's orb mark, if the product has one, and as faint washes
101
101
  in `ws-cool-glow` and `ws-team-glow` behind a page hero. No conic rings, purple glows or gradient text, except the
102
- status line's word while an answer works (`StatusLine`, in the chart colours) and the loading shimmer.
102
+ status line's word while an answer works (`StatusLine`, in the chart colours). The loading shimmer is one neutral
103
+ tone, the ghost grey and a lighter pass of it, never the chart colours (0.5.1).
103
104
  - **People are neutral**: a disc of `ws-surface-sunk` with navy initials.
104
105
  - **Marketing pages** keep the kit's own marketing colours (its gradient button, `color-text-primary`); they never enter a
105
106
  product screen.
@@ -106,7 +106,7 @@ Components new in 0.5.0 are marked (new).
106
106
 
107
107
  | Need | Component | Rule |
108
108
  | --- | --- | --- |
109
- | Content on its way | `Skeleton` (the shimmer in the chart colours over ghost shapes) | never a spinner for content |
109
+ | Content on its way | `Skeleton` (the shimmer, one quiet grey, over ghost shapes) | never a spinner for content |
110
110
  | An answer at work | `StatusLine` (new) | the agent, what it is doing, the step |
111
111
  | A long load with no figure | `LoadBar` (new) | it never claims to finish before it has |
112
112
  | A press waiting on its answer | `Button pending` | keeps its width; a second press waits; the button stays focusable |
@@ -89,7 +89,7 @@ Seth draws most shares as ticks. The rules every strip follows:
89
89
 
90
90
  ## States
91
91
 
92
- Loading and empty follow Patterns (a shimmer in the chart colours over the chart's ghost; the same card with its act).
92
+ Loading and empty follow Patterns (the shimmer, one quiet grey, over the chart's ghost; the same card with its act).
93
93
 
94
94
  | State | How |
95
95
  | --- | --- |
@@ -58,7 +58,7 @@ moves. A state never changes a thing's size, its type size or its place, so noth
58
58
  | Focus | a 2 px navy ring 2 px outside (`ws-focus-color`); inside a dense row, a well, a list or a clipped container the same ring drawn inside (`ws-focus-inset`) | `:focus-visible` only; never `outline: none` without the ring (Accessibility) |
59
59
  | Selected, open, current | the ground changes (the sunk cream, or the well for a pill in an inset list), the words go navy or 600; a list's selected fill slides from the row it left; the dividers beside an inset pill drop | the row keeps its height and type size; `aria-selected`, `aria-current` or `aria-expanded` says it |
60
60
  | Pending | the control keeps its width and its words; the working dot sits in its padding on the one beat; it stays focusable (`aria-disabled`, `aria-busy`) and refuses a second press | from 100 ms (Latency above); words that say what is happening ("Saving") |
61
- | Loading | the region's ghost in the chart colours' shimmer, the size of what it stands for; its head shows at once | never a spinner for content; still under reduced motion, with a word |
61
+ | Loading | the region's ghost under the shimmer (one quiet grey), the size of what it stands for; its head shows at once | never a spinner for content; still under reduced motion, with a word |
62
62
  | Disabled | dimmed (the component's own opacity), no pointer events, the reason said nearby | prefer leaving the act out, or keeping it focusable and saying why |
63
63
  | Others step back | while one row, part or tile is in focus, the rest dim (a matrix's other rows to 20%, a chart's other parts to `ws-dim`); the dimmed keep their grounds and dividers. A word that must stay readable steps to muted grey instead of fading (a heatmap's other squares fade their heat and status bar, their words stay AA) | the focused one never changes |
64
64
 
@@ -193,9 +193,9 @@ of cards wears `.ws-build`; each card in it wears `.ws-build__card` with `--ws-i
193
193
 
194
194
  ### Loading
195
195
 
196
- Content on its way is a ghost the size of what it stands for with the shimmer passing over it in the chart colours
197
- (`Skeleton`, or `.ws-shimmer` on a block of your own: every `--ws-loop-shimmer`, 1.8 s, on `--ws-ease-shimmer`), never
198
- a spinner. When the content lands, its details settle in top to bottom (`.ws-settle` with `--ws-i` on each, 22 ms
196
+ Content on its way is a ghost the size of what it stands for with the shimmer passing over it: one quiet tone, the
197
+ ghost grey and a lighter pass of the same grey, never a chart hue (`Skeleton`, or `.ws-shimmer` on a block of your own:
198
+ every `--ws-loop-shimmer`, 1.8 s, on `--ws-ease-shimmer`), never a spinner. When the content lands, its details settle in top to bottom (`.ws-settle` with `--ws-i` on each, 22 ms
199
199
  apart). An answer at work shows a `StatusLine`; a long load with no figure a `LoadBar`; a pressed button waiting keeps
200
200
  its width and shows its working dot on `--ws-loop`. Why: the layout is already in place, so nothing jumps when the real
201
201
  thing arrives. Under reduced motion the shimmer stops on its ghost and the words say what is loading.
@@ -494,3 +494,13 @@ the team builds on the kit gets them, not North alone.
494
494
  | 5 Nov 2026 | Amit (via Claude, open to veto) | `--ws-duration-fill-page` (1700 ms, North's "Metric + goal bars fill") is a token: the tiles' charts and the goal bars both use it (D4). A tile's foot figure rises in after the draw; it does not count up (the 4 Nov rule: a headline figure shows its value) | tokens, Motion |
495
495
  | 5 Nov 2026 | Amit (via Claude, open to veto) | `TrendLine`: North's revenue chart and its NRR line become one kit chart, a value over periods on an axis as a line (dots, the hatched area under it) or as columns, with the Bars / Line morph (`--ws-spring-morph-chart`), the hovered column band and the hovered dot. Overturns 09-charts' "a free line chart: make it thin bars" for one series on an axis; two series stay two cards. Its columns start at zero (North's ARR chart starts at $20M: the kit does not) | Charts, `TrendLine`, `TrendBars`, `StepLine` |
496
496
 
497
+ ## Rulings added 10 Nov 2026 (kit 0.5.1)
498
+
499
+ Amit looked at the loading skeletons in an app built on the kit: the shimmer swept salmon, purple and green tints across
500
+ every grey ghost block. He wants loaders calm and neutral.
501
+
502
+ | Date | By | Decision | Where it bites |
503
+ | --- | --- | --- | --- |
504
+ | 10 Nov 2026 | Amit (via Claude) | Loading is one quiet tone: the shimmer (`--ws-shimmer`) is the ghost grey with a lighter pass of the same grey, never a chart hue, in light, night, the navy ground and every palette. Overturns D7's "loading is a shimmer in the chart colours", the Motion row "The skeleton breathes" (4 Nov) for its colours, and the loading shimmer as an exception to "no gradient text" in Colour. North's timing stays: the 300 % band at 100 deg over 1.8 s (`--ws-loop-shimmer` on `--ws-ease-shimmer`), still under reduced motion | Skeleton, Motion, Colour, Patterns, every `ws-shimmer` ghost |
505
+ | 10 Nov 2026 | Amit (via Claude, open to veto) | How it is drawn. The ground is the ghost grey itself (`--ws-shimmer-ground` is now `--ws-ghost`: #E3DFDB, the night's #273544), the same at rest and in motion, so a ghost shows on the cream (1.29:1) and on the tray (1.13:1) in every theme and Skeleton's own ground for a card's foot is gone. The pass is the ghost 70 % of the way to the cream in light (#F6F3F0: 1.07:1 off the cream, 1.06:1 off the tray, so it shows on both) and 7 % toward the ink in dark (#354250; #364351 on the navy ground), the same step by eye (CIEDE2000 4.3); it derives from the ghost, the page and the ink, so a palette moves it. The chart ghost's colour band is dropped, not made neutral: in blend mode colour a neutral band has no hue and paints nothing, and in normal blend it would paint the card between the bars. Each bar is now a ghost under the same shimmer, so one token drives every loader | tokens (`_product.css`, `_dark.css`), Skeleton, the Motion card (its two rows now Close and Not yet) |
506
+ | 10 Nov 2026 | Open, for Amit to rule | Not changed: `StatusLine`'s working words still pass through the AA steps of salmon, purple and teal. They are words at work, not a ghost; if "loaders" covers them too, they take a neutral pass next | StatusLine |
@@ -69,7 +69,7 @@ Seth's checks list (301:1728) and Fixes checklist (308:2466).
69
69
  - **Focus**: the 2 px navy ring drawn inside the row.
70
70
  - **Not checked**: as above.
71
71
  - **Done** (a fix, `--done`): the box ticked, the title muted, the done line under it in the positive word.
72
- - **Loading**: the name and the ticks as ghosts in the chart colours' sweep (`__ghost ws-shimmer`, `__ticks ws-shimmer`);
72
+ - **Loading**: the name and the ticks as ghosts under the shimmer (`__ghost ws-shimmer`, `__ticks ws-shimmer`);
73
73
  still under reduced motion.
74
74
  - **Long name**: wraps within its 150; the row grows, every column still lines up.
75
75
 
@@ -110,7 +110,7 @@
110
110
  </div>
111
111
 
112
112
  <div class="ws-stack" style="width: 560px;">
113
- <span class="ws-muted">Loading: the rows' places as ghosts in the chart colours' sweep</span>
113
+ <span class="ws-muted">Loading: the rows' places as ghosts under the shimmer</span>
114
114
  <ul class="ws-check-row" aria-busy="true" aria-label="Checks, loading">
115
115
  <li><div class="ws-check-row__row" aria-hidden="true">
116
116
  <span class="ws-check-row__name"><span class="ws-check-row__ghost ws-shimmer" style="width: 70%;"></span></span>
@@ -38,7 +38,7 @@
38
38
  .ws-check-row__line > .ws-check-row__chev { transition: transform var(--ws-spring-fold-duration) var(--ws-spring-fold); }
39
39
  .ws-check-row__ticks > b { transform-origin: bottom; animation: ws-grow-up var(--ws-duration-fill) var(--ws-ease-settle) backwards; animation-delay: calc(sibling-index() * var(--ws-ripple)); }
40
40
  }
41
- /* Loading: the name and the ticks as ghosts in the chart colours' sweep (add ws-shimmer). */
41
+ /* Loading: the name and the ticks as ghosts under the shimmer (add ws-shimmer). */
42
42
  .ws-check-row__ghost { display: block; height: calc(var(--space-xs) + var(--space-3xs)); border-radius: var(--ws-radius-bar); background: var(--ws-track); }
43
43
  .ws-check-row__ghost.ws-shimmer, .ws-check-row__ticks.ws-shimmer { background: var(--ws-shimmer); background-size: 300% 100%; }
44
44
 
@@ -51,7 +51,7 @@ Columns of cards for a pipeline: a stage per column, a card per thing moving thr
51
51
  reorder", `springs.reorder` .4 / 0): wrap the move in `reorder()` (below).
52
52
  - **Empty**: the column keeps its full width, its head and its count; a muted sentence in place of cards. It never
53
53
  hides, which would reflow every column beside it mid-task.
54
- - **Loading**: ghost cards the height of a card in the chart colours' sweep (`__ghost ws-shimmer`), the heads shown at
54
+ - **Loading**: ghost cards the height of a card under the shimmer (`__ghost ws-shimmer`), the heads shown at
55
55
  once; still under reduced motion.
56
56
  - **Scrolled**: the far-edge fade while stages are hidden, gone at the end; in `--fill`, a column's foot fades while cards
57
57
  are hidden below it, gone at its end.
@@ -30,7 +30,7 @@
30
30
  .ws-kanban-board__who { display: flex; align-items: center; gap: var(--space-xs); min-width: 0; }
31
31
  .ws-kanban-board__meta { font-size: var(--ws-text-control); line-height: var(--ws-leading-control); color: var(--color-text-muted); }
32
32
  .ws-kanban-board__empty { padding: var(--space-md) var(--space-xs); text-align: center; font-size: var(--ws-text-control); line-height: var(--ws-leading-control); color: var(--color-text-muted); }
33
- /* Loading: a ghost the height of a card, in the chart colours' sweep (add ws-shimmer). */
33
+ /* Loading: a ghost the height of a card under the shimmer (add ws-shimmer). */
34
34
  .ws-kanban-board__ghost { display: block; height: calc(var(--ws-card-padding) * 2 + var(--ws-control-h-sm) + var(--space-xxs) + var(--ws-leading-control)); border-radius: var(--ws-radius-card); background: var(--ws-track); }
35
35
  .ws-kanban-board__ghost.ws-shimmer { background: var(--ws-shimmer); background-size: 300% 100%; }
36
36
  /* A board page (K16): the board takes the rest of a height-bound column (the shell's body, a fill page), every column
@@ -175,7 +175,7 @@
175
175
  </div>
176
176
 
177
177
  <div class="ws-stack" style="width: 640px;">
178
- <span class="ws-muted">Loading: the list's rows and the detail as ghosts in the chart colours' sweep (under 48rem the pair stacks, list first)</span>
178
+ <span class="ws-muted">Loading: the list's rows and the detail as ghosts under the shimmer (under 48rem the pair stacks, list first)</span>
179
179
  <div class="ws-list-detail" aria-busy="true">
180
180
  <div class="ws-list-detail__grid">
181
181
  <section class="ws-list-detail__list" aria-label="Reviews, loading">
@@ -55,7 +55,7 @@ answers grid (305:2341): which AI assistants named you, for each of the question
55
55
  and the foot stay; the hovered row does not change. The whole question shows in the note.
56
56
  - **Focus** (keyboard, or a tap that focuses the question): the same dim and the same note. A page script may set
57
57
  `aria-expanded="true"` on the question to keep the note open after a tap where the browser does not focus buttons.
58
- - **Loading**: every cell a ghost in the chart colours' sweep (`__cell ws-shimmer`), the questions and sources shown at
58
+ - **Loading**: every cell a ghost under the shimmer (`__cell ws-shimmer`), the questions and sources shown at
59
59
  once; still under reduced motion.
60
60
  - **Narrow**: source names drop to their marks in 32 px columns (a screen reader still hears each source through the
61
61
  head's label), and the foot's line drops under its title.
@@ -62,7 +62,7 @@
62
62
  </div>
63
63
 
64
64
  <div class="ws-stack" style="width: 420px;">
65
- <span class="ws-muted">Loading: every cell a ghost in the chart colours' sweep, the questions and sources shown at once</span>
65
+ <span class="ws-muted">Loading: every cell a ghost under the shimmer, the questions and sources shown at once</span>
66
66
  <div class="ws-matrix" aria-busy="true">
67
67
  <div class="ws-matrix__table" role="table" aria-label="Which AI assistants named you, checking">
68
68
  <div class="ws-matrix__head" role="rowgroup">
@@ -71,14 +71,14 @@ Coverage, 206 behaviours (the page counts them in its head):
71
71
  | 6. Focus | 7 | 4 | 2 | 0 | 1 |
72
72
  | 7. Open and close | 23 | 10 | 5 | 2 | 6 |
73
73
  | 8. Panels docking | 12 | 6 | 1 | 1 | 4 |
74
- | 9. Loading, working and loops | 11 | 5 | 2 | 0 | 4 |
74
+ | 9. Loading, working and loops | 11 | 3 | 3 | 0 | 5 |
75
75
  | 10. Number and chart build-ins | 13 | 5 | 2 | 0 | 6 |
76
76
  | 11. Tooltips and hover cards | 6 | 2 | 4 | 0 | 0 |
77
77
  | 12. Stagger | 11 | 6 | 2 | 1 | 2 |
78
78
  | 13. Reduced motion | 4 | 4 | 0 | 0 | 0 |
79
79
  | 14. What never moves | 10 | 6 | 3 | 0 | 1 |
80
80
  | 17. Interaction states | 13 | 7 | 2 | 1 | 3 |
81
- | All | 206 | 115 | 45 | 5 | 41 |
81
+ | All | 206 | 113 | 46 | 5 | 42 |
82
82
 
83
83
  ## States
84
84
 
@@ -36,7 +36,7 @@
36
36
  <li class="ws-cluster" style="flex-wrap: nowrap; align-items: flex-start; gap: var(--space-xs);"><span class="ws-badge ws-badge--navy" aria-hidden="true" style="flex: none; min-width: var(--space-lg);">11</span><span class="ws-stack ws-stack--tight" style="min-width: 0;"><span class="ws-row-name">Sort the list</span><span class="ws-meta">Pick an order: the rows glide to their new places.</span></span></li>
37
37
  <li class="ws-cluster" style="flex-wrap: nowrap; align-items: flex-start; gap: var(--space-xs);"><span class="ws-badge ws-badge--navy" aria-hidden="true" style="flex: none; min-width: var(--space-lg);">12</span><span class="ws-stack ws-stack--tight" style="min-width: 0;"><span class="ws-row-name">Press any button</span><span class="ws-meta">It gives under your finger and springs back.</span></span></li>
38
38
  <li class="ws-cluster" style="flex-wrap: nowrap; align-items: flex-start; gap: var(--space-xs);"><span class="ws-badge ws-badge--navy" aria-hidden="true" style="flex: none; min-width: var(--space-lg);">13</span><span class="ws-stack ws-stack--tight" style="min-width: 0;"><span class="ws-row-name">Point at a health square</span><span class="ws-meta">After a breath it grows open in place.</span></span></li>
39
- <li class="ws-cluster" style="flex-wrap: nowrap; align-items: flex-start; gap: var(--space-xs);"><span class="ws-badge ws-badge--navy" aria-hidden="true" style="flex: none; min-width: var(--space-lg);">14</span><span class="ws-stack ws-stack--tight" style="min-width: 0;"><span class="ws-row-name">Refresh the sources</span><span class="ws-meta">A shimmer in the chart colours, then each line settles in.</span></span></li>
39
+ <li class="ws-cluster" style="flex-wrap: nowrap; align-items: flex-start; gap: var(--space-xs);"><span class="ws-badge ws-badge--navy" aria-hidden="true" style="flex: none; min-width: var(--space-lg);">14</span><span class="ws-stack ws-stack--tight" style="min-width: 0;"><span class="ws-row-name">Refresh the sources</span><span class="ws-meta">A shimmer, one quiet grey, then each line settles in.</span></span></li>
40
40
  <li class="ws-cluster" style="flex-wrap: nowrap; align-items: flex-start; gap: var(--space-xs);"><span class="ws-badge ws-badge--navy" aria-hidden="true" style="flex: none; min-width: var(--space-lg);">15</span><span class="ws-stack ws-stack--tight" style="min-width: 0;"><span class="ws-row-name">Replay the arrival</span><span class="ws-meta">The cards rise in, the columns grow in one after another and the goals fill.</span></span></li>
41
41
  </ol>
42
42
  <p class="ws-muted" data-reduced-readout></p>
@@ -270,7 +270,7 @@
270
270
  <div class="ws-stack" style="gap: var(--ws-gap-group); padding-top: var(--ws-gap-component);">
271
271
  <div class="ws-stack">
272
272
  <p class="ws-body">Each row is one of North's behaviours by Seth's own label (north-motion.md), North's values, a live kit demo to hover, press or play, the kit token or class to build with, and how close the kit is. 206 behaviours: 115 exact, 45 close, 5 through a small JS helper, 41 not in the kit yet.</p>
273
- <span class="ws-cluster"><span class="ws-chip ws-chip--live" style="min-width: var(--space-6xl); justify-content: center;">Exact 115</span><span class="ws-chip ws-chip--middle" style="min-width: var(--space-6xl); justify-content: center;">Close 45</span><span class="ws-chip ws-chip--accent" style="min-width: var(--space-6xl); justify-content: center;">JS helper 5</span><span class="ws-chip" style="min-width: var(--space-6xl); justify-content: center;">Not yet 41</span></span>
273
+ <span class="ws-cluster"><span class="ws-chip ws-chip--live" style="min-width: var(--space-6xl); justify-content: center;">Exact 113</span><span class="ws-chip ws-chip--middle" style="min-width: var(--space-6xl); justify-content: center;">Close 46</span><span class="ws-chip ws-chip--accent" style="min-width: var(--space-6xl); justify-content: center;">JS helper 5</span><span class="ws-chip" style="min-width: var(--space-6xl); justify-content: center;">Not yet 42</span></span>
274
274
  <p class="ws-muted">Slow motion (in Try it) is this page's own: it multiplies every duration, delay and stagger token by --ws-motion-slow (4), so a spring's shape shows. Reduced motion: with prefers-reduced-motion set, every row here is still (instant state changes, no springs, no view transitions, shimmers stop on their ghost), and Slow motion has nothing to slow. A browser without a feature (linear(), anchor positioning, @starting-style, interpolate-size, view transitions) shows the change at once, never a broken layout.</p>
275
275
  </div>
276
276
 
@@ -1436,21 +1436,21 @@
1436
1436
 
1437
1437
  <section class="ws-stack" aria-labelledby="mo-loading">
1438
1438
  <h2 class="ws-section" id="mo-loading">9. Loading, working and loops</h2>
1439
- <p class="ws-muted">Every working signal says in words what it is doing; the shimmer passes in the chart colours over ghost shapes.</p>
1439
+ <p class="ws-muted">Every working signal says in words what it is doing; the shimmer passes over ghost shapes in one quiet grey.</p>
1440
1440
  <div class="ws-board">
1441
1441
  <article class="ws-card" aria-label="Shimmer in chart colours"><div class="ws-head">
1442
1442
  <div class="ws-stack ws-stack--tight">
1443
- <span class="ws-cluster"><span class="ws-chip ws-chip--live" style="min-width: var(--space-6xl); justify-content: center;">Exact</span><span class="ws-row-name">Shimmer in chart colours</span></span>
1443
+ <span class="ws-cluster"><span class="ws-chip ws-chip--middle" style="min-width: var(--space-6xl); justify-content: center;">Close</span><span class="ws-row-name">Shimmer in chart colours</span></span>
1444
1444
  <span class="ws-meta">North: text and blocks: a 100deg band of #f6ddd8, #e4dcf3, #d6eaea over #ece8e4, 300% wide, 1.8 s shimmer, infinite (css:1458)</span>
1445
- <span class="ws-meta">Kit: .ws-skeleton, .ws-shimmer: --ws-shimmer over --ws-loop-shimmer on --ws-ease-shimmer; still ghost under reduced motion</span>
1445
+ <span class="ws-meta">Kit: .ws-skeleton, .ws-shimmer: --ws-shimmer over --ws-loop-shimmer on --ws-ease-shimmer, North's band, width and beat in one quiet grey: the ghost #e3dfdb with a lighter pass #f6f3f0, no chart hues (Amit, 10 Nov 2026); still ghost under reduced motion</span>
1446
1446
  </div>
1447
1447
  <div class="ws-cluster"><span class="ws-stack" style="width: var(--space-9xl);" aria-hidden="true"><span class="ws-skeleton ws-skeleton--title" style="width: 60%;"></span><span class="ws-skeleton ws-skeleton--line"></span><span class="ws-skeleton ws-skeleton--line" style="width: 66%;"></span></span></div>
1448
1448
  </div></article>
1449
1449
  <article class="ws-card" aria-label="Empty chart shapes take the colour band"><div class="ws-head">
1450
1450
  <div class="ws-stack ws-stack--tight">
1451
- <span class="ws-cluster"><span class="ws-chip ws-chip--live" style="min-width: var(--space-6xl); justify-content: center;">Exact</span><span class="ws-row-name">Empty chart shapes take the colour band</span></span>
1451
+ <span class="ws-cluster"><span class="ws-chip" style="min-width: var(--space-6xl); justify-content: center;">Not yet</span><span class="ws-row-name">Empty chart shapes take the colour band</span></span>
1452
1452
  <span class="ws-meta">North: #e3dfdb shapes, a coral, purple, teal band at mix-blend color, .85, the same 1.8 s</span>
1453
- <span class="ws-meta">Kit: .ws-skeleton__chart</span>
1453
+ <span class="ws-meta">Kit: not taken: loaders are one neutral tone (Amit, 10 Nov 2026); .ws-skeleton__chart's bars are ghosts under the same shimmer</span>
1454
1454
  </div>
1455
1455
  <div class="ws-cluster"><span class="ws-skeleton__chart" style="width: var(--space-9xl);" aria-hidden="true"><i style="height: 35%;"></i><i style="height: 60%;"></i><i style="height: 45%;"></i><i style="height: 75%;"></i><i style="height: 55%;"></i><i style="height: 90%;"></i><i style="height: 70%;"></i><i style="height: 50%;"></i></span></div>
1456
1456
  </div></article>
@@ -2514,7 +2514,7 @@
2514
2514
  veil.addEventListener('click', closeChat);
2515
2515
  chat.addEventListener('keydown', (e) => { if (e.key === 'Escape' && mode === 'bar') closeChat(); });
2516
2516
 
2517
- /* 14: the sources load: a shimmer in the chart colours, then each line settles in, top to bottom. */
2517
+ /* 14: the sources load: the shimmer, one quiet grey, then each line settles in, top to bottom. */
2518
2518
  const sources = play.querySelector('[data-play-sources]'), sourcesView = sources.querySelector('[data-sources-view]');
2519
2519
  let loading = 0;
2520
2520
  const load = () => {
@@ -16,7 +16,7 @@ The catalog: 103 components by gallery group, one line each, plus `Cover`, the g
16
16
  - [Fold](Fold/README.md): The one disclosure: something folded away until wanted, in three looks, built on the browser's native `<details>`.
17
17
  - [Morph](Morph/README.md): A thing that changes its place or its size goes there as itself: a card flying to the full screen and back, a figure growing open across its row, the chat moving between its modes. The browser's own view transitions, started by `morph()` from the package, on Seth's curves.
18
18
  - [Plate](Plate/README.md): A quiet block set apart inside a card: the cream a shade darker, for a card's facts, a track or an aside.
19
- - [Skeleton](Skeleton/README.md): A ghost of what is coming, in the shape it will take, with North's shimmer in the chart colours passing over it, so nothing jumps when the real content lands.
19
+ - [Skeleton](Skeleton/README.md): A ghost of what is coming, in the shape it will take, with North's shimmer passing over it in one quiet grey, so nothing jumps when the real content lands.
20
20
  - [Well](Well/README.md): The system's grey well: a plate holding a short list of pressable rows, for every "what to ask" list.
21
21
 
22
22
  ## Charts
@@ -41,8 +41,8 @@ A report's score the way Seth draws it: the 96 px figure, a strip of ticks acros
41
41
  once the draw is half way. The figure does not count up (North: headline figures are static).
42
42
  - Not checked: an en dash in muted words in place of the figure (`__figure--none`, with `aria-hidden`; the section's
43
43
  label says "not checked"), every tick the track, "Could not check" and why.
44
- - Loading: a ghost the figure's height, the strip as a ghost (`--loading`) and a ghost line, all in the chart colours'
45
- sweep; `aria-busy="true"` on the section.
44
+ - Loading: a ghost the figure's height, the strip as a ghost (`--loading`) and a ghost line, all under the shimmer;
45
+ `aria-busy="true"` on the section.
46
46
  - Long sentence: wraps as running text under the rating; the figure never wraps.
47
47
  - Reduced motion: no draw, no settle; the ghosts stay still.
48
48
  - Hover, focus, pressed: do not apply; it is read, not pressed.
@@ -19,7 +19,7 @@
19
19
  .ws-score-hero--needs-work { --tone-word: var(--ws-word-needs-work); }
20
20
  .ws-score-hero--needs-work .ws-tick-strip { --tone: var(--ws-rating-needs-work); }
21
21
  .ws-score-hero--none { --tone-word: var(--color-text-muted); }
22
- /* Loading: ghost blocks the size of what they stand for, in the chart colours' sweep. */
22
+ /* Loading: ghost blocks the size of what they stand for under the shimmer. */
23
23
  .ws-score-hero__ghost { width: calc(var(--space-6xl) * 2); max-width: 100%; height: var(--ws-leading-score); }
24
24
  .ws-score-hero__ghost--line { width: min(100%, calc(var(--space-9xl) * 2)); height: var(--ws-leading-section); }
25
25
  @container (max-width: 26rem) {
@@ -28,7 +28,7 @@ Where a whole goes: one stacked bar of parts in their tones over what stays, a h
28
28
  - Draw (`--draw`): each part grows from its left edge in turn, 70 ms apart (`--ws-stagger-part`), over 700 ms on the
29
29
  settle curve. Set `--i` on each part.
30
30
  - Nothing moves: the bar is all ground; the key says what stays.
31
- - Loading (`--loading`): the bar as a ghost in the chart colours' sweep.
31
+ - Loading (`--loading`): the bar as a ghost under the shimmer.
32
32
  - Narrow: the head and the key wrap; the bar keeps its parts in proportion.
33
33
  - Reduced motion: the parts in place, the ghost still.
34
34
  - Hover, focus: none; the key carries the words.
@@ -16,7 +16,7 @@
16
16
  .ws-share-bar__item::before { content: ""; position: absolute; inset-inline-start: 0; top: calc((var(--space-md) - var(--space-xs)) / 2); width: var(--space-xs); height: var(--space-xs); border-radius: var(--ws-radius-chip); background: var(--tone, var(--ws-chart-rest)); }
17
17
  /* Seth's key is one tone: the figure keeps the words' weight and colour, only its numerals are tabular. */
18
18
  .ws-share-bar__item b { font-weight: inherit; color: inherit; font-variant-numeric: tabular-nums; }
19
- /* Loading: the bar as a ghost in the chart colours' sweep, the key held back. */
19
+ /* Loading: the bar as a ghost under the shimmer, the key held back. */
20
20
  .ws-share-bar--loading .ws-share-bar__bar { background: var(--ws-shimmer); background-size: 300% 100%; }
21
21
  @media (prefers-reduced-motion: no-preference) {
22
22
  .ws-share-bar--loading .ws-share-bar__bar { animation: ws-shimmer var(--ws-loop-shimmer) var(--ws-ease-shimmer) infinite; }
@@ -1,4 +1,4 @@
1
- A ghost of what is coming, in the shape it will take, with North's shimmer in the chart colours passing over it, so
1
+ A ghost of what is coming, in the shape it will take, with North's shimmer passing over it in one quiet grey, so
2
2
  nothing jumps when the real content lands.
3
3
 
4
4
  ## Use it when
@@ -15,16 +15,15 @@ nothing jumps when the real content lands.
15
15
 
16
16
  ## Anatomy
17
17
 
18
- - A ghost block (`ws-skeleton`): 4 px corners (`--ws-radius-control`), the shimmer for its ground (`--ws-shimmer`:
19
- the warm grey #ECE8E4 with a pass of salmon, purple and teal at 300 %), sized where used. Steps: `--line` 12 px
18
+ - A ghost block (`ws-skeleton`): 4 px corners (`--ws-radius-control`), the shimmer (`--ws-shimmer`: the ghost grey
19
+ #E3DFDB with a lighter pass of the same grey, #F6F3F0, at 300 %; no chart hues), sized where used. Steps: `--line` 12 px
20
20
  tall, `--title` 28 px (a title's line), `--button` 120 x 36 with 6 px corners (North's button place, on the grid).
21
21
  - Lines: a column 8 px apart (`ws-stack`), full width except the last, two thirds.
22
22
  - A card skeleton: the same card (`ws-card`) with ghosts for its head (`ws-skeleton__head`, 20 in), its body
23
- (`ws-skeleton__body`) and its band; a tile keeps its tray foot. On the tray (a foot) and in a band the ghosts are
24
- built on the hover grey (`--ws-well-hover`), since the shimmer's own grey is the tray's (1.04:1) and vanished there.
25
- - A chart ghost (`ws-skeleton__chart`): 160 px tall, the bars 4 px apart in a quiet ghost grey (`--ws-well-hover`),
26
- with one colour band (salmon, purple, teal) passing over the whole drawing in blend mode colour at 85 %, so each bar
27
- takes the band's hue as it crosses it (North's loading chart).
23
+ (`ws-skeleton__body`) and its band; a tile keeps its tray foot. The ghost grey shows on the tray too (1.13:1, the
24
+ cream 1.29:1), so a ghost in a foot or a band is the same ghost.
25
+ - A chart ghost (`ws-skeleton__chart`): 160 px tall, the bars 4 px apart, each a ghost under the same shimmer as every
26
+ other ghost. North's colour band over the drawing is not taken (0.5.1): loaders are one neutral tone.
28
27
 
29
28
  ## Variants and sizes
30
29
 
@@ -38,12 +37,13 @@ nothing jumps when the real content lands.
38
37
  ## States
39
38
 
40
39
  - **Loading** (the only state): the shimmer passes over every ghost every 1.8 s (`--ws-loop-shimmer` on
41
- `--ws-ease-shimmer`); the chart's colour band on the same beat.
40
+ `--ws-ease-shimmer`), the chart's bars included.
42
41
  - **Loaded**: the skeleton is removed and the real content takes its place; nothing jumps, since the ghosts use the
43
42
  content's own sizes.
44
- - **Reduced motion**: nothing travels. The ghosts are one still ghost grey (`--ws-well-hover`, North's ghost, the
45
- chart ghost's own), never a frozen frame of the sweep, and the chart band is not drawn; still plainly a placeholder.
46
- - **Dark**: the shimmer and the ghost grey are theme tokens; the band keeps the brand hues.
43
+ - **Reduced motion**: nothing travels. The ghosts are the still ghost grey (`--ws-ghost`, the shimmer's own ground),
44
+ never a frozen frame of the sweep; still plainly a placeholder.
45
+ - **Dark and palettes**: the ghost and its pass are theme tokens (the night's ghost #273544 with a pass of 7 % ink), so
46
+ the shimmer is one neutral tone in every theme and palette.
47
47
 
48
48
  ## Behaviour
49
49
 
@@ -75,8 +75,9 @@ The kit's own `Skeleton` takes a `className` for its shape and size directly (he
75
75
 
76
76
  ## Source
77
77
 
78
- **Derived from**: North's loading (style1.css:1458-1469: the chart-colour shimmer over blocks, the ghost shapes with a
79
- colour band in blend mode colour, the 116 x 38 button place) and the kit's own `Skeleton`. It replaces the breathing
78
+ **Derived from**: North's loading (style1.css:1458-1469: the shimmer over blocks, the ghost shapes, the 116 x 38
79
+ button place) and the kit's own `Skeleton`. North's sweep in the chart colours and its colour band over the chart are
80
+ not taken: loaders are one quiet grey (Amit, 10 Nov 2026, Decisions). It replaces the breathing
80
81
  pulse, which read as blank (1.10:1 on the cream, field evidence S01). **Precedent**: the first product built on the
81
82
  system.
82
83
 
@@ -98,5 +99,5 @@ system.
98
99
  ## Styles
99
100
 
100
101
  `Skeleton/style.css`, built into `bundle.css` and `fello.css`. The keyframe is the house's `ws-shimmer`. Tokens:
101
- `--ws-shimmer`, `--ws-loop-shimmer`, `--ws-ease-shimmer`, `--ws-well-hover`, `--ws-chart-under-half`,
102
- `--ws-chart-past-half`, `--ws-chart-finished`, `--ws-radius-control`, `--ws-radius-row`.
102
+ `--ws-shimmer` (over `--ws-shimmer-ground`), `--ws-ghost`, `--ws-loop-shimmer`, `--ws-ease-shimmer`,
103
+ `--ws-radius-control`, `--ws-radius-row`, `--ws-radius-bar`.
@@ -30,7 +30,7 @@
30
30
  </div>
31
31
 
32
32
  <div class="ws-stack" style="width: 380px;">
33
- <span class="ws-muted">A chart card still loading: the ghost bars take the colour band as it passes</span>
33
+ <span class="ws-muted">A chart card still loading: each bar a ghost under the same shimmer</span>
34
34
  <div class="ws-card ws-card--compound" aria-busy="true">
35
35
  <span class="ws-sr">Loading the chart</span>
36
36
  <div class="ws-skeleton__head" aria-hidden="true">
@@ -1,22 +1,17 @@
1
- /* ---- Skeleton: ghost shapes of what is coming, with North's shimmer in the chart colours running over them; sized where used ---- */
2
- /* A ghost block: the shimmer (the warm grey, a pass of salmon, purple and teal) at 300 %, 1.8 s. It replaces the
3
- breathing pulse (ws-working-slow), which read as blank. Under reduced motion it is a still ghost in North's ghost grey
4
- (the chart ghost's), never a frozen frame of the sweep: at rest the 300 % gradient showed its pink edge. */
1
+ /* ---- Skeleton: ghost shapes of what is coming, with North's shimmer, one quiet grey, running over them; sized where used ---- */
2
+ /* A ghost block: the shimmer (the ghost grey with a lighter pass of the same grey) at 300 %, 1.8 s. It replaces the
3
+ breathing pulse (ws-working-slow), which read as blank. Under reduced motion it is the still ghost, the same grey
4
+ (North's ghost, the chart ghost's), never a frozen frame of the sweep. The ghost shows on the tray too (a card's foot,
5
+ a band), so it needs no ground of its own there. */
5
6
  .ws-skeleton { border-radius: var(--ws-radius-control); background: var(--ws-ghost); }
6
7
  .ws-skeleton--line { height: var(--space-sm); }
7
8
  .ws-skeleton--title { height: var(--ws-leading-title); }
8
9
  /* A button's place (North's 116 x 38 placeholder, on the grid: 120 x 36, 6 px corners). */
9
10
  .ws-skeleton--button { width: var(--space-7xl); height: var(--ws-control-h-md); border-radius: var(--ws-radius-row); }
10
- /* On the tray (a card's foot) and in a band the ghost's grey was the ground's own (1.04:1 on the tray in light, the same
11
- grey as the track in dark), so the placeholder vanished: there it is built on the hover grey, with the dark theme's
12
- recipe of 14 % salmon, purple and teal passes, on the token's stops (plain to 34 % and from 66 %, so the loop's end frames show no tint). */
13
- :is(.ws-card__foot, .ws-band) .ws-skeleton { --ws-shimmer: linear-gradient(100deg, var(--ws-well-hover) 0 34%, color-mix(in srgb, var(--ws-chart-under-half) 14%, var(--ws-well-hover)) 44%, color-mix(in srgb, var(--ws-chart-past-half) 14%, var(--ws-well-hover)) 50%, color-mix(in srgb, var(--color-stat-positive) 14%, var(--ws-well-hover)) 56%, var(--ws-well-hover) 66% 100%); }
14
- @media (prefers-reduced-motion: no-preference) { .ws-skeleton { background: var(--ws-shimmer); background-size: 300% 100%; animation: ws-shimmer var(--ws-loop-shimmer) var(--ws-ease-shimmer) infinite; } }
15
11
  .ws-skeleton__head { display: flex; flex-direction: column; gap: var(--space-xs); padding: var(--ws-card-inset); }
16
12
  .ws-skeleton__body { display: flex; flex-direction: column; gap: var(--space-xs); padding: 0 var(--ws-card-inset) var(--space-md); }
17
- /* A chart still loading: its empty shapes in a quiet ghost grey, and one colour band (salmon, purple, teal) passing
18
- over the whole drawing in blend mode colour, so the bars take the band's hue as it crosses them. */
19
- .ws-skeleton__chart { position: relative; display: flex; align-items: flex-end; gap: var(--space-xxs); height: var(--space-8xl); }
13
+ /* A chart still loading: its empty shapes, each a ghost with the same sweep as every other ghost. North's colour band
14
+ over the drawing is gone (0.5.1): loaders are one neutral tone, and a neutral band in blend mode colour paints nothing. */
15
+ .ws-skeleton__chart { display: flex; align-items: flex-end; gap: var(--space-xxs); height: var(--space-8xl); }
20
16
  .ws-skeleton__chart > * { flex: 1 1 0; min-width: 0; border-radius: var(--ws-radius-bar) var(--ws-radius-bar) 0 0; background: var(--ws-ghost); }
21
- .ws-skeleton__chart::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(100deg, transparent 28%, var(--ws-chart-under-half) 40%, var(--ws-chart-past-half) 50%, var(--color-stat-positive) 60%, transparent 72%); background-size: 300% 100%; mix-blend-mode: color; opacity: 0; }
22
- @media (prefers-reduced-motion: no-preference) { .ws-skeleton__chart::after { opacity: 0.85; animation: ws-shimmer var(--ws-loop-shimmer) var(--ws-ease-shimmer) infinite; } }
17
+ @media (prefers-reduced-motion: no-preference) { :is(.ws-skeleton, .ws-skeleton__chart > *) { background: var(--ws-shimmer); background-size: 300% 100%; animation: ws-shimmer var(--ws-loop-shimmer) var(--ws-ease-shimmer) infinite; } }
@@ -23,7 +23,7 @@ paste the CSS into the `<style>`, then replace the sample content with the real
23
23
  `fello-core.css`, then the styles of each component the page uses (each component's card lists them; this page needs
24
24
  `Page`, `PageBar`, `Card`, `Button` and `Well`; the whole `fello.css` is too big to paste). The buttons and the well
25
25
  rows need their own blocks: `fello-core.css` holds only their 0.4 look. A plain page links the whole file instead,
26
- pinned: `https://brand-kit-site-production.up.railway.app/v/0.5.0/fello.css`.
26
+ pinned: `https://brand-kit-site-production.up.railway.app/v/0.5.1/fello.css`.
27
27
  - `<main class="ws-page">`: the page (see `Page`), Seth's 32 gutter.
28
28
  - `PageBar`: the page's 56 px header, its one `h1` (16 / 22 semibold) and a word of context beside it, and its acts
29
29
  with the page's one navy primary last.
@@ -7,7 +7,7 @@
7
7
  <title>Starter</title>
8
8
  <!-- In a claude.ai artifact, paste fello-core.css into the <style> below, then the styles of each component you use
9
9
  (each component's card lists them): an artifact may load no stylesheet but Google Fonts. On a plain page, link the
10
- whole kit instead, pinned: https://brand-kit-site-production.up.railway.app/v/0.5.0/fello.css -->
10
+ whole kit instead, pinned: https://brand-kit-site-production.up.railway.app/v/0.5.1/fello.css -->
11
11
  <link rel="preconnect" href="https://fonts.googleapis.com">
12
12
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
13
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400..700&display=swap">
@@ -81,7 +81,7 @@ a phone fold. This is the whole wide-table pattern; build every records table fr
81
81
  stuck columns leave the sliding ones over 100 px, not a sliver. A name that fits keeps its one line.
82
82
  - **Empty, no matches**: the same card, a sentence and the act that clears the filter (`__empty`).
83
83
  - **Empty, first use**: the same card, a sentence inviting the first record and the act that adds one.
84
- - **Loading**: a ghost bar per cell in the chart colours' sweep (`__placeholder ws-shimmer`), the head shown at once;
84
+ - **Loading**: a ghost bar per cell under the shimmer (`__placeholder ws-shimmer`), the head shown at once;
85
85
  still under reduced motion.
86
86
  - **Touch**: the check target, the More act and the row acts reach 40, the sort button 24.
87
87
 
@@ -151,7 +151,7 @@
151
151
  </figure>
152
152
 
153
153
  <div class="ws-stack" style="width: 300px;">
154
- <span class="ws-muted">Loading: ghost bars in the chart colours' sweep, the head shown at once</span>
154
+ <span class="ws-muted">Loading: ghost bars under the shimmer, the head shown at once</span>
155
155
  <section class="ws-card ws-table" aria-busy="true" aria-label="Leads, loading">
156
156
  <div class="ws-table__scroll">
157
157
  <table>
@@ -97,7 +97,7 @@
97
97
  .ws-table .ws-table__more { display: inline-flex; }
98
98
  .ws-table .ws-table__name { min-width: 40cqi; white-space: normal; }
99
99
  }
100
- /* Loading: a ghost bar in each cell, in the chart colours' sweep (add ws-shimmer), the head shown at once. */
100
+ /* Loading: a ghost bar in each cell under the shimmer (add ws-shimmer), the head shown at once. */
101
101
  .ws-table__placeholder { height: calc(var(--space-xs) + var(--space-3xs)); border-radius: var(--ws-radius-bar); background: var(--ws-track); }
102
102
  .ws-table__placeholder.ws-shimmer { background: var(--ws-shimmer); background-size: 300% 100%; }
103
103
  /* Empty: the same card, a sentence and the act that clears the filter. */
@@ -55,7 +55,7 @@ A share drawn as equal ticks across the whole width: the done ones in one tone,
55
55
  - Draw (`--draw`): one 900 ms draw (`--ws-duration-draw`); tick i starts at its share of the first 55% and rises from
56
56
  its foot on `--ws-ease-settle`. Set `--i` on each lit tick.
57
57
  - Not checked or zero: every tick the track; the figure beside it says so in words (a dash, "Could not check").
58
- - Loading (`--loading`): the ticks as a still ghost with the chart colours' sweep (`--ws-shimmer`, 1.8 s). The ticks
58
+ - Loading (`--loading`): the ticks as a still ghost with the shimmer passing over them (`--ws-shimmer`, 1.8 s). The ticks
59
59
  inside are hidden, so the ghost has the strip's exact shape.
60
60
  - Hover (`--hover`, opt in): the tick under the pointer grows to 116% from its foot on `--ws-ease-lift`, its two
61
61
  neighbours half as much 4 ms later, the rest dim to 30%. Only with a hovering pointer.