Skip to content

Claude/hansmartens market positioning mlt89z - #685

Merged
hansmartensdev merged 4 commits into
mainfrom
claude/hansmartens-market-positioning-mlt89z
Sep 5, 2026
Merged

hansmartensdev merged 4 commits into
mainfrom
claude/hansmartens-market-positioning-mlt89z

Conversation

@hansmartensdev

Copy link
Copy Markdown
Owner

What does this PR do?

A clear description of the change and why it was made.

Fixes # (issue number, if applicable)

Type of change

  • Bug fix
  • New feature or component
  • Documentation update
  • Refactor or code quality improvement
  • Other: ___

Checklist

  • pnpm lint passes with 0 errors
  • pnpm check passes with 0 errors
  • pnpm build completes successfully
  • I have tested this change in the browser
  • No unnecessary files are included in this PR

Screenshots (if relevant)

Add before/after screenshots for visual changes.

A cover was a flat brand-600 rect behind the artwork, the same fill in
both colour modes. It now runs a vertical gradient from a shade just off
brand-500 down to brand-900, with a faint grid over it, masked out
towards the edges so the centre carries the picture.

The fill has to be an SVG paint server: `fill` on an SVG shape takes
`url(#id)` and nothing else, so a CSS gradient cannot reach it. The def
is emitted once per cover and keyed by slug, because SVG ids are
document-global and a listing page shows several covers at once — one
shared id would paint every cover from whichever parsed first. The id
travels to the scoped stylesheet through a `--cover-bg` custom property,
which a scoped rule can read and could not otherwise interpolate.

The stops sit at 0.1296 and 0.8704 rather than 0 and 1. The artwork is
scaled 1.35 inside its frame, so the frame shows the middle slice and
never the SVG's own top or bottom edge; stops at the extremes would put
both ends of the ramp in the cropped remainder, leaving the visible
slice with neither end colour. They are computed from the same constant
as the transform. Moving the gradient vector out of range instead is
valid SVG and renders in Chromium, but not on iOS.

The grid is sized in percentages, not pixels: sixteen columns at every
width, so a cover reads the same in a card as across an article hero.
The cells come out square because every cover is 1200x630, which all 25
in `src/assets/blog/` are.

One `.bg` rule serves both modes. A flat fill for light and another for
dark would sit after it at equal specificity and win on source order,
handing light mode its flat background back.

Checked in all twelve colour themes: each resolves a distinct pair of
stops, and no cover falls back to black.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwJB1u6U3vdEZ9LrHRebST
On the first page there is no previous page, so the arrow's `href` was
left undefined. An anchor without an href is not a link: it falls back
to a generic role, and both `aria-label` and `aria-disabled` are
prohibited on that role. The blog index and its paginated pages failed
the audit for it.

The arrow that has somewhere to go stays an anchor. The one that does
not is a span, hidden from assistive technology — it offers nothing to
act on, and the live arrow still names the direction that is available.
Its appearance is unchanged; the two now share one set of base classes
so they cannot drift apart.

`pointer-events-none` goes with the anchor. A span is not interactive,
so `cursor-not-allowed` is visible on it, which it never was before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwJB1u6U3vdEZ9LrHRebST
The selected tag was white on brand-500. In the default theme that is a
contrast ratio of 3.69:1 against the 4.5:1 that 12px text needs, and it
failed on every tag archive — 47 blog tags and 7 project tags.

brand-700 is the step that clears the threshold in all twelve colour
themes. White on brand-500 fails in ten of them, as low as 2.82:1 on
teal. brand-600 still fails four — emerald, teal, cyan and sky sit
between 4.17 and 4.45. brand-700 holds from 6.03:1 on teal to 9.24:1 on
magenta, so the pill passes whichever theme a site ships with.

The border moves with the fill, and the inactive pills are untouched.
The scale is the same in both colour modes, so one value serves both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwJB1u6U3vdEZ9LrHRebST
The projects index and the seven project tag archives put these cards
directly under the page's h1 with no section heading in between, so an
h3 title skipped a level and failed the heading-order audit.

BlogCard's title is already an h2, and the blog listings pass. Matching
it fixes every affected page at once. On the home page the cards keep
sitting below that section's own h2, and a heading repeating its
predecessor's level is not a skip.

The size comes from the classes, so the level carries no visual weight
and nothing moves on the page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwJB1u6U3vdEZ9LrHRebST
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@vercel

vercel Bot commented Sep 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astro-rocket Ready Ready Preview Sep 5, 2026 8:16pm UTC

@hansmartensdev
hansmartensdev merged commit f39a32a into main Sep 5, 2026
4 checks passed
@hansmartensdev
hansmartensdev deleted the claude/hansmartens-market-positioning-mlt89z branch September 5, 2026 20:39

This branch was successfully deployed

1 active deployment
Preview — 4dcafefb Deployed Sep 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants