RamosLabs DS

Answer

Which token should I use for muted text?

Use --color-text-muted (#64748b)[1] for muted text on white. It measures 4.76:1 against --color-surface (#ffffff)[6], above the 4.5:1 that WCAG requires for normal text[5]. On the pale indigo --color-primary-surface it measures 4.26:1 and falls below that minimum[6], so use --color-text-secondary there.

Measured contrast of the six text roles

The six text roles are neutral slate tokens[1]. The table gives each one measured against white (--color-surface). The last column states whether the ratio reaches the 4.5:1 minimum for normal text[5]. The DS presents the first five as one neutral-hue text scale and --color-text-disabled as state only[2].

Text role tokens, hex values[1], and ratios on white[6]
TokenHexRatio on whiteReaches 4.5:1
--color-text-heading#0f172a[1]17.85:1[6]Yes
--color-text-strong#1e293b[1]14.63:1[6]Yes
--color-text-body#334155[1]10.35:1[6]Yes
--color-text-secondary#475569[1]7.58:1[6]Yes
--color-text-muted#64748b[1]4.76:1[6]Yes
--color-text-disabled#cbd5e1[1]1.48:1[6]No

Where muted text stops working

Muted text clears the minimum on white and on the light gray surface, with a thin margin on the gray. It does not clear it on the indigo tint.[6][5]

--color-text-muted (#64748b) on other surfaces[1], measured[6]
BackgroundHexRatioReaches 4.5:1
--color-surface#ffffff[1]4.76:1[6]Yes
--color-surface-secondary#f8fafc[1]4.55:1[6]Yes, barely
--color-primary-surface#eef2ff[1]4.26:1[6]No

The DS floor for muted text

Rule: muted text is never lighter than #64748b (slate 500) on white[3]. Why: lighter slate values fall below 4.5:1; slate 400 (#94a3b8) measures 2.56:1 on white[6], below the 4.5:1 minimum[5].

On --color-primary-surface use --color-text-secondary (#475569): it measures 6.78:1 there[6].

Copyable CSS

Import the tokens once at the app entry, then reference the role token. Never hardcode the hex[3].

app entry stylesheetcss
@import '@ramoslabs/tokens/css';
muted caption, and the replacement on an indigo tintcss
.card-meta {
  color: var(--color-text-muted);
  background: var(--color-surface);
}

.card-meta--on-indigo-tint {
  color: var(--color-text-secondary);
  background: var(--color-primary-surface);
}

Reproduce the numbers

The ratios on this page come from the script below, which applies the WCAG relative-luminance and contrast-ratio definitions[4] to the published token values. Run it in a project that has @ramoslabs/tokens installed; it prints 4.76 and 6.29.

contrast.mjs (Node 18 or newer)js
import { readFileSync } from 'node:fs'

// WCAG 2.2 relative luminance and contrast ratio, applied to the published token values.
const lin = (c) => ((c /= 255) <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4)
const lum = (hex) => {
  const n = parseInt(hex.slice(1), 16)
  return 0.2126 * lin((n >> 16) & 255) + 0.7152 * lin((n >> 8) & 255) + 0.0722 * lin(n & 255)
}
const ratio = (a, b) => {
  const [hi, lo] = [lum(a), lum(b)].sort((x, y) => y - x)
  return (hi + 0.05) / (lo + 0.05)
}

const tokens = JSON.parse(readFileSync('node_modules/@ramoslabs/tokens/dist/tokens.json', 'utf8'))
const pair = (fg, bg) => ratio(tokens[fg], tokens[bg]).toFixed(2)

console.log(pair('color-text-muted', 'color-surface')) // 4.76
console.log(pair('color-primary', 'color-surface')) // 6.29

Frequently asked questions

Which token should I use for muted text on a white background?
Use --color-text-muted (#64748b)[1]. It measures 4.76:1 on white[6], above the 4.5:1 minimum for normal text[5].
Can I use a lighter gray for muted text?
Not on white under the DS rule: muted text is never lighter than #64748b[3]. Slate 400 (#94a3b8) measures 2.56:1 on white[6], below 4.5:1[5].
What should I use for muted text on an indigo tinted background?
Use --color-text-secondary (#475569). --color-text-muted measures 4.26:1 on --color-primary-surface (#eef2ff), below 4.5:1, while secondary text measures 6.78:1 there[6].
Is --color-text-disabled a good choice for less important text?
No. It measures 1.48:1 on white[6] and the DS reserves it for the disabled state, not readable text[2].
Does muted text pass on the light gray surface?
Yes, with a thin margin: 4.55:1 on --color-surface-secondary (#f8fafc)[6], against a 4.5:1 minimum[5].
Should I hardcode the muted gray value?
No. Reference var(--color-text-muted) after importing @ramoslabs/tokens/css once; a raw hex in CSS is a defect under the DS rules[3].

References

Every factual statement above points to one of these. External sources are listed with their own date or version and the day we read them; DS sources are pinned to a repository commit; measurements say what was run and when.

  1. Source tokens: color.primitive.json and color.semantic.json (@ramoslabs/tokens) RamosLabs DS repository, commit 71b8bac. 2026-09-21.
  2. Colors: the foundation page (roles and measured contrast pairings; source Colors.md) RamosLabs DS repository, commit 71b8bac. 2026-09-21.
  3. AGENTS.md: accessibility floors, the hard rule, and component status RamosLabs DS repository, commit 71b8bac. 2026-09-21.
  4. WCAG 2.2: definitions of relative luminance and contrast ratio W3C. W3C Recommendation, 2024-12-12; accessed 2026-10-27.
  5. Understanding SC 1.4.3: Contrast (Minimum) W3C WAI. updated 2026-09-06; accessed 2026-10-27.
  6. Contrast ratios computed from the token hex values with the script on this page (WCAG relative-luminance and contrast-ratio formulas), rounded to two decimals RamosLabs DS. 2026-10-27.

Machine-readable: llms-full.txt, tokens.json,MCP server. © 2026 RAMOS SOLUTIONS S.A.S. MIT License.