Repository navigation
Fix the low-contrast ink opacities and pin contrast so they cannot regress #38
Description
Task
Three components use text-ink/50 and text-ink/60 for small text. Computed against the paper background, 50% is 3.30:1 — below WCAG AA for body text — and 60% is 4.54:1, which passes by 0.04. Replace them with tokens that clear the bar and add a check so the mistake cannot come back.
Context
- Tokens:
--ink: #141a17on--paper: #f6f7f5(light), flipped in dark mode (app/globals.css:15,16,24,25). app/(marketing)/page.tsx:53—text-ink/50on the numbered step labels. Composite ≈#858986→ 3.30:1, fails AA (4.5:1) for normal text.components/indexer/LagNotice.tsx:11andapp/(marketing)/page.tsx:119—text-ink/60→ composite ≈#6e7270, 4.54:1. Technically passing, one rounding from failing.- My computed numbers, for your starting point:
/75= 7.50:1,/60= 4.54:1,/50= 3.30:1. Dark mode/50≈ 4.66:1. Verify both schemes yourself — a dark-mode-only pass is not a pass. - There is no
eslint-plugin-jsx-a11yand no contrast check anywhere; lint is Biomerecommended(biome.json:6).
Before you start: mandatory context review
Kinlock moves other people's money, so the docs are binding constraints, not background reading.
They record decisions this task must not silently reopen. Read them in this order and tick each box:
-
docs/ARCHITECTURE_ESSENTIALS.md— start here, it is short (AGENTS.md§1) -
docs/ARCHITECTURE.md— only the sections named in Context above -
docs/PRD.md— if this task touches user-facing behaviour or scope -
AGENTS.md§3 (hard rules), §4 (deferred list), §8 for this repo, §12 (roadmap rule) -
ROADMAP.md— the row(s) listed under Related roadmap rows, including their Depends on
In your first PR comment, name the hard-rule numbers or doc sections that constrain this task. That
line is how we know the review happened.
Then:
- If code and docs disagree, or two docs disagree: stop and say so on this issue. Do not pick one
silently, and do not "fix" either side without approval (AGENTS.md§1). - If the task looks like it needs anything from the deferred list (§4), a change to a hard rule (§3),
or a new dependency (§2): raise it here first. Those need a human; deciding them is not your job. - If a row you are told to finish is
BLOCKEDor depends on a row that is notDONE, say so here
instead of starting.
Why we need this
AGENTS.md§8.3 treats accessibility as required, not polish, and lists contrast explicitly.- The step labels on the landing page are the first thing a prospective sender reads; if they are grey mush on a phone in sunlight, the product looks broken before it is judged.
- 4.54:1 passing by 0.04 means the next well-meaning tweak breaks it silently. Pinning it is the actual fix.
Scope
In scope
app/globals.css(a token or two that clear AA in both colour schemes)- The three call sites named in Context
- One check: a unit test computing ratios from the token values, or a documented manual checklist — see Tests
Do not touch (security-sensitive or generated; changing these needs a human first — AGENTS.md §2, docs/project_structure.md §8)
app/claim/**andlib/claim-links/**— the claim-link fragment (#r=…&s=…) must never reach a server, log or analytics tool (hard rule 5)next.config.ts,proxy.ts/middleware.ts, CSP headerslib/wallet/**and any direct contract call site — money-moving calls go through the SDK and the wallet adapter onlyapp/send/**,app/locks/**,app/payee/**action logic — release, refund and decline paths stay with maintainerspackage.json,pnpm-lock.yaml(no new dependencies without approval),.github/workflows/**- a full audit of every component (that is the rest of
M3-17)", "installing an a11y lint plugin without approval (new dependency)
Suggested implementation
- Introduce semantic tokens (e.g.
--color-mutedat a ratio that clears 4.5:1 in both light and dark) rather than sprinkling/70everywhere. Tailwind 4 with CSS variables makes this one change. - Replace all
text-ink/50andtext-ink/60usages with the token. Do not leave any behind: the check should forbid the opacity form. - Prefer a test that reads the token values and computes the ratio (WCAG relative luminance is a dozen lines, no dependency) over a screenshot tool. If you would rather use a library, ask here first.
- Do not "fix" contrast by darkening the background — the palette is a design decision; propose changes to it on the issue.
A different approach is usually welcome — post it here before building and we will answer. This is a
suggestion, not a spec.
Edge cases and traps
- Light (
--ink: #141a17on--paper: #f6f7f5) and the dark-mode flip. Passing in one scheme is not a pass; dark/50is already ~4.66:1 and light/50is 3.30:1. - Body text is a 4.5:1 bar, large text is 3:1. Label which case each token serves.
- Opacity over a tinted or image-bearing background composites differently from opacity over flat paper — compute the real result, do not eyeball it.
- The 4.54:1 case passes by 0.04: a tweak that looks harmless will break it silently, which is why the check is part of the deliverable, not a nice-to-have.
Done means
- No
text-ink/50ortext-ink/60remains inapp/orcomponents/ - Every text token used for body copy measures ≥ 4.5:1 in light and dark; large-text cases ≥ 3:1
- A test or a checked-in checklist fails if someone reintroduces an opacity below the bar
-
pnpm lint,typecheck,test,buildpass - You state in the PR the ratios you measured, per token, per scheme
Tests
Add the contrast case to the existing vitest suite (there are 15 test files, all node-environment .test.ts). A pure function over the token values needs no DOM and no dependency.
Documentation
Note the palette rule in app/globals.css beside the token so the next person does not repeat it.
Verify before you open the PR
pnpm install
pnpm lint
pnpm typecheck
pnpm test
pnpm build
Run every command above and paste the real output in the PR. We do not accept "should pass" —
AGENTS.md §6: "You actually ran the commands."
Opening the pull request
- Assignment is required before you start. Comment on this issue and wait to be assigned. Do not
open a PR against an issue someone already holds — if it has been quiet, ask us to release it first. Closes #38in the PR description, so the issue and the PR link automatically.- Branch
feat/…,fix/…,docs/…,test/…orchore/…. Commit subject example:
fix(app): raise muted ink tokens to WCAG AA in both colour schemes - Add a Changelog entry; leave
M3-17IN PROGRESS. - Follow
.github/PULL_REQUEST_TEMPLATE.md(AGENTS.md§7). In "Hard rules / invariants touched",
give numbers, not prose. - Small and focused: one logical change. Do not mix a refactor into it.
- Do not add the
security-sensitivelabel — that is the maintainer's flag for contract-logic PRs. - Do not reformat or touch files outside Scope. Unrelated diff noise costs review time and can
break the roadmap merge. - Never commit to
main; open a PR. Never force-push. - Evidence for the PR: Attach before/after screenshots of the landing-page step labels and
LagNotice, light and dark.
How we review
Two maintainers: one reviews correctness against the hard rules and the roadmap row's Done when, the
other reviews diff scope and whether the tests were actually run. Order is hard-rule correctness → tests
really executed → diff stays inside Scope → style last. First response on a PR: 2 business days.
What fails review fastest: a change outside Scope, a deleted or weakened assertion, a claim with no
command output behind it, and a ROADMAP.md with no Changelog entry (AGENTS.md §12).
For this issue, look first at the ratios you measured per token per scheme, and that the check actually fails when someone reintroduces an opacity below the bar.
Tier and effort
tier/trivial · roughly 1–2 hours. Wave complexity tag: Trivial = 100 points — the published mapping is Trivial 100 · Medium 150 · High 200
(Drips' maintainer guide); the cycle's
own values are confirmed on drips.network/wave/stellar before
the Wave opens. Kinlock's tier rules and what each tier means for review:
docs/wave-issue-format.md.
Related roadmap rows
M3-17 — Accessibility pass (keyboard, labels, contrast) (IN PROGRESS)
M3-17 is IN PROGRESS; this is one increment of it. Leave the row IN PROGRESS and name what is still outstanding in the PR.
Questions
Comment on this issue — a maintainer answers within 2 business days. Say "I'll take this" so we can flag it on
the Wave board and stop two people doing the same work. If you get half way and stall, post what you
have as a draft PR rather than disappearing; a blocked draft is more useful to us than silence.
Activity
jdjioe5-cpu commentedon Oct 17, 2026
I'll take this. I have reviewed AGENTS.md §8.3 accessibility requirements and the scope in \�pp/globals.css. Ready to introduce WCAG AA compliant semantic ink tokens across both light and dark schemes, eliminate \ ext-ink/50\ and \ ext-ink/60\ usages, and add the mathematical contrast ratio assertion test suite once assigned.
jdjioe5-cpu commentedon Oct 17, 2026
I'll take this issue. Preparing semantic tokens (--muted\ / --color-muted) with WCAG AA compliance (contrast ratio$\ge 4.5:1$ in both light and dark modes), replacing all \ ext-ink/50\ and \ ext-ink/60\ occurrences across \�pp/\ and \components/, and adding automated vitest verification.
jdjioe5-cpu commentedon Oct 17, 2026
Submitted PR #45 addressing this issue.
Summary of Delivery: