diff --git a/desktop-new/src/features/design-system/ui/ColourPage.tsx b/desktop-new/src/features/design-system/ui/ColourPage.tsx
index 875841f7be..abb68c01e2 100644
--- a/desktop-new/src/features/design-system/ui/ColourPage.tsx
+++ b/desktop-new/src/features/design-system/ui/ColourPage.tsx
@@ -97,6 +97,12 @@ export function ColourPage() {
{hue.usedBy ? `drawn from by ${hue.usedBy}` : "unassigned"}
+ {/* Each step carries what it is for, not just its number. The
+ registry has always held this text and no page rendered it,
+ which is how it drifted: it still described the generic scale
+ the values came from — step 4 as "component hover" — long after
+ this product had made step 4 its one border weight. Unrendered
+ documentation cannot be checked by looking. */}
{hue.steps.map((step) => (
{step.step}
+
+ {step.job}
+
))}
diff --git a/desktop-new/src/shared/styles/tokens.css b/desktop-new/src/shared/styles/tokens.css
index 014fe41357..4a061ff71c 100644
--- a/desktop-new/src/shared/styles/tokens.css
+++ b/desktop-new/src/shared/styles/tokens.css
@@ -263,23 +263,37 @@
============================================================ */
:root {
- /* --- Neutral. Twelve steps, each step a fixed job. --------
+ /* --- Neutral. Twelve steps. --------------------------------
Keeps its numbering: unlike the coloured families these steps
- really are a scale, and every step is in use. Step 1 stays
- pure white rather than the palette's off-white, because the
- app background is a deliberate choice, not a grey. */
- --neutral-1: #ffffff; /* app background */
- --neutral-2: #f9f9f9; /* subtle background */
- --neutral-3: #f0f0f0; /* component background */
- --neutral-4: #e8e8e8; /* component hover */
- --neutral-5: #e0e0e0; /* component selected */
- --neutral-6: #d9d9d9; /* subtle border */
- --neutral-7: #cecece; /* border */
- --neutral-8: #bbbbbb; /* border hover */
- --neutral-9: #8d8d8d; /* solid fill, tertiary text */
- --neutral-10: #646464; /* secondary text */
- --neutral-11: #262626; /* dark fill */
- --neutral-12: #0a0a0a; /* high-contrast text */
+ really are a scale. Step 1 stays pure white rather than the
+ palette's off-white, because the app background is a
+ deliberate choice, not a grey.
+
+ **The comments record what Buzz uses each step for, not what
+ Radix intended it for.** They said "component hover",
+ "subtle border", "border" — a generic scale's intentions,
+ transcribed with the values and then left alone while the
+ product decided otherwise. That is how the one border weight
+ came to sit on the step labelled "component hover" while the
+ two steps labelled for borders had no readers at all, and how
+ a designer reading this file would have been told the wrong
+ thing by the only documentation at hand.
+
+ Keep these current. A step whose comment disagrees with its
+ use is worse than no comment, because it reads as a decision
+ someone made. `pnpm census` lists the real readers. */
+ --neutral-1: #ffffff; /* bg-panel, bg-float, bg-chrome-selected */
+ --neutral-2: #f9f9f9; /* unused in light; bg-inset in dark */
+ --neutral-3: #f0f0f0; /* bg-inset; bg-panel in dark */
+ --neutral-4: #e8e8e8; /* border-primary — the one border weight */
+ --neutral-5: #e0e0e0; /* unused in light; float + selected, dark */
+ --neutral-6: #d9d9d9; /* the /design specimen frame edge only */
+ --neutral-7: #cecece; /* no readers */
+ --neutral-8: #bbbbbb; /* text-disabled */
+ --neutral-9: #8d8d8d; /* text-tertiary */
+ --neutral-10: #646464; /* text-secondary */
+ --neutral-11: #262626; /* inverse fill, paired with neutral-1 */
+ --neutral-12: #0a0a0a; /* text-primary */
/* --- Glass. A translucency ramp of fills. ---------------- */
--glass-1: #ffffff5c; /* barely there */
diff --git a/desktop-new/src/shared/tokens/registry.ts b/desktop-new/src/shared/tokens/registry.ts
index f040f23dfa..e5d5099318 100644
--- a/desktop-new/src/shared/tokens/registry.ts
+++ b/desktop-new/src/shared/tokens/registry.ts
@@ -63,23 +63,36 @@ export interface RoleGroup {
============================================================ */
/**
- * What each of the twelve steps is *for*. The same twelve jobs in every hue —
- * which is the whole point of a twelve-step scale, and what makes the
- * step-to-role mapping deterministic: a role picks a step number, not a colour.
- * Named from the neutral ramp because that is where every step is in use.
+ * What each of the twelve steps is *for*, as a starting point.
+ *
+ * The same twelve jobs in every hue is what makes a twelve-step scale useful and
+ * the step-to-role mapping deterministic: a role picks a step number, not a
+ * colour.
+ *
+ * **These are the scale's general intentions, not a record of Buzz's decisions,
+ * and the two have already diverged.** The list came with the values and said
+ * step 4 was "component hover" and step 6 "subtle border" — while in this product
+ * step 4 is the one border weight and step 6 has one reader on a documentation
+ * page. A generic label that contradicts the product is worse than none, because
+ * a designer reading `/design` takes it for a decision someone made.
+ *
+ * So: **the label answers "what is this step generally for", and the neutral
+ * ramp's own comments in `tokens.css` answer "what does Buzz actually do with
+ * it".** When a step's real use settles into something durable, move it here.
+ * `pnpm census` lists the real readers of every role.
*/
const STEP_JOBS = [
- "app background",
- "subtle background",
- "component background",
- "component hover",
- "component selected",
- "subtle border",
+ "lightest surface",
+ "subtle surface",
+ "tinted surface",
+ "tinted surface, hovered",
+ "quiet border, or a selected surface",
"border",
- "border hover",
+ "stronger border",
+ "border hover, focus ring",
"solid fill",
- "secondary text",
- "dark fill",
+ "solid fill, hovered",
+ "text on a tint, or an inverse fill",
"high-contrast text",
];