jasonstockman/warm-technologies
Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.
7 files reviewed·July 26, 2026
Low
Design risk in this codebase.
Verdict
The visual system is more disciplined than most: variants are cleanly separated, decorative images are correctly hidden from assistive tech, and the oklch derivation chain keeps the palette coherent once you're past the raw hex seeds. The real risk sits in a handful of specifics: the hero's mid-sentence typeface swap muddies the one line that should carry the whole message, the button and card primitives carry an accessibility gap (heading semantics, touch target size) that will surface repeatedly since they're shared components, and a chunk of the CSS setup (smooth scroll, unused Inter import) is either unguarded or dead weight.
Files Rams reviewed
src/components/ui/button.tsx
src/components/ui/card.tsx
src/components/ui/shader-background.tsx
src/App.tsx
src/index.css
src/main.tsx
index.html
Accessibility
src/components/ui/button.tsx:21
Icon-only button size falls below the 44px minimum touch target
The `icon` size variant sets `size-10`, rendering icon-only buttons at 40x40px. There is no larger icon size option in the variant map (`default`, `sm`, `lg`, `icon`).
Why it matters
Below 44x44px, tap accuracy drops for users with motor impairments and on touchscreens generally, increasing mis-taps on icon-only controls that carry no text label to fall back on.
Fix
Set icon-only button dimensions to at least 44x44px to meet the minimum touch target guideline.
icon: 'size-10',icon: 'size-11',Typography
src/App.tsx:45
Hero headline splits across two typefaces mid-sentence for no functional reason
The h1 "Making frontier technology more warm and human." runs in the default sans weight until the last three words, which switch to `font-display italic tracking-[-0.035em]` in a `<span>`. The rest of the page (nav label "Warm Technologies", body copy, section titles) never uses font-display again, so this is the only place two typefaces meet inside one sentence.
Why it matters
A typeface swap mid-headline reads as an accidental style leak rather than a designed emphasis, since nothing else on the page pairs these two fonts. It also weakens the actual hierarchy: readers spend a beat parsing why "warm and human" looks different instead of registering it as the emphasized idea.
Fix
Use weight or color shift within the same typeface for in-line emphasis rather than swapping fonts, unless the display face is established as a recurring brand element elsewhere on the page.
Making frontier technology more{' '}
<span className="font-display italic tracking-[-0.035em]">warm and human.</span>Making frontier technology more{' '}
<span className="font-semibold text-foreground">warm and human.</span>Get this score on every PR.
Rams reviews each pull request on your repo and posts inline one-click fixes — about a minute per review.
Install Rams freeColor
src/index.css:40
Base brand colors are raw hex while every derived token uses oklch
`--brand-primary: #85807a`, `--brand-accent: #7e7a8a`, and `--brand-neutral: #837f7c` are defined as plain hex, then every semantic token below them (`--foreground`, `--card`, `--primary`, `--muted`, etc.) is derived with `oklch(from var(--brand-*) ...)`.
Why it matters
Mixing hex and oklch in the same three lines means adjusting the base palette requires converting mentally between two color spaces, and any tool or teammate scanning the file for the source-of-truth hue has to hunt for the one spot where the space changes.
Fix
Define the base brand tokens in oklch directly so the entire palette lives in one color space end to end.
--brand-primary: #85807a;
--brand-accent: #7e7a8a;
--brand-neutral: #837f7c;--brand-primary: oklch(0.56 0.006 90);
--brand-accent: oklch(0.55 0.012 300);
--brand-neutral: oklch(0.56 0.005 80);Spacing
src/App.tsx:62
Services grid hardcodes a bespoke five-track layout instead of a reusable pattern
The services section uses `sm:grid-cols-[1fr_auto_1fr_auto_1fr]` to interleave three `SimpleCard` items with two `ServiceDivider` elements in one arbitrary column template.
Why it matters
A one-off grid template tied to exactly three cards and two dividers breaks the moment a fourth service gets added or a divider is removed, forcing whoever edits it next to recompute the fr/auto sequence by hand instead of relying on a documented pattern.
Fix
Replace the bespoke column template with a standard flex or auto-fit grid plus divider styling that doesn't depend on a fixed item count.
<section className="grid gap-6 pb-10 text-center sm:grid-cols-[1fr_auto_1fr_auto_1fr] sm:items-stretch sm:gap-8 sm:text-center"><section className="flex flex-col divide-y divide-border gap-6 pb-10 text-center sm:flex-row sm:divide-x sm:divide-y-0 sm:items-stretch sm:gap-8 sm:text-center">Motion
src/index.css:77
Global smooth scroll ships with no prefers-reduced-motion guard
`html { scroll-behavior: smooth; }` applies unconditionally to every anchor jump and scroll-into-view on the page, with no `@media (prefers-reduced-motion: reduce)` override anywhere in the stylesheet.
Why it matters
Users with vestibular disorders who set prefers-reduced-motion at the OS level still get animated scrolling on every internal link, since nothing in this file respects that setting, which can trigger dizziness or nausea for that group.
Fix
Wrap scroll-behavior: smooth in a prefers-reduced-motion media query so it only applies when the user hasn't opted out of motion.
html {
scroll-behavior: smooth;
background: var(--background);
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}html {
background: var(--background);
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}Craft
src/index.css:1
Inter variable font files download but are never referenced by any token
`@import '@fontsource-variable/inter'` and its italic companion load the full variable-font weight axis, but `--font-sans`, `--font-heading`, `--font-serif`, and `--font-display` all resolve to `Arial, 'Helvetica Neue', Helvetica, sans-serif`. Inter never appears in any font-family value in this file.
Why it matters
Every visitor pays the download cost of a variable font file that never renders a single character, which is wasted bandwidth and slows first paint for no visual benefit.
Fix
Remove unused font imports, or wire the font token to actually reference the imported font family.
@import '@fontsource-variable/inter';
@import '@fontsource-variable/inter/wght-italic.css';/* Inter import removed: no --font-* token currently references it. Re-add only if a token is updated to use Inter. */Components
UX
Working well
- Deriving --background, --foreground, --card, and the rest via oklch(from var(--brand-*) ...) keeps every semantic token locked to the same hue family while only lightness and chroma shift, which is exactly how a coherent tonal system should be built once the base tokens themselves are fixed.
- Button variants (default, secondary, outline, ghost) are cleanly separated through cva, each pairing background, text, and hover state consistently rather than forking styles per instance, which keeps the primitive predictable as new call sites get added.
- The mailto CTA correctly pairs aria-label="Email Warm Technologies" on the anchor with aria-hidden on the obfuscated email span, giving screen reader users a clean accessible name while keeping the anti-scrape trick invisible to assistive tech.
Scored July 26, 2026 with Rams Engine v0.0.3 · Engine changelog
Score your own repo.
Free on public repos, no account. The same engine that scored this page reads your UI code and mints a score page like this one.
Public repos only. The full engine reviews the UI code and mints a public score page — we email you the link too. Already-scored repos open instantly.