UI Review: maula-zee-nu.vercel.app

Reviewed 2026-10-17 on the live site (Home, Projects, About, Blog) at 1280×800 and 390×844 (iPhone 12 Pro), light and dark. Values below come from computed styles in the running page, so there are no file:line references. This is a deployed site and I had no source.

Verdict: Blocked

The design is strong: good type scale, sensible dark mode, a clear identity. It is blocked on the accessibility floor. Four things break it: tap targets, secondary-text contrast, an unlabelled 14px search field, and decoration that makes real copy unreadable in light mode.

Home, desktop light


Blocking

1. The 3D scene covers real text, mostly in light mode and on mobile

Dimension: layout / contrast · emil-ui-polish, emil-color

The fixed .floating-scene (z-index -10) sits behind content, but the dark keycaps and shadow blobs are the same tone as the text laid over them.

Mobile home, key under badge/eyebrow/footer

Fix: - Keep scene objects out of text columns. Position them by breakpoint, or mask or fade them where text lives. - Raise the footer above the scene with a surface behind it: isolation: isolate plus a solid or bg-white/80 footer. - On mobile, show fewer or smaller objects.

2. Tap targets are under 44×44

Dimension: accessibility floor · emil-touch-and-accessibility

Control Size
Hero social icons (Email / GitHub / LinkedIn) 28×28
Footer social icon 34×34
Theme toggle 32×32
Mobile menu toggle 34×34
Desktop nav links 62–77 × 34
Blog filter chips 41–97 × 35
Project card title links ~83×26

The card links are probably stretched by ::after, so the whole card is hit-testable. Everything else is not.

Fix: keep the visual size and expand the hit area. Use relative before:absolute before:-inset-2.5 before:content-[''] on the icon buttons, or add padding to reach 44. The social icons are the worst offenders, at 28px and visually pale.

3. Secondary text fails contrast (2.3:1)

Dimension: accessibility floor · emil-color

Blog meta and placeholder at 2.3:1

Fix: move this token to roughly oklch(0.52 0 0) (~#6b6b6a, already the nav secondary colour at 5.1:1). Re-check dark mode.

4. Blog search field: 14px, no label, no focus style

Dimension: interaction / forms · emil-forms-and-inputs

Fix: text-base (16px), aria-label="Search articles", :focus-visible ring, type="search", autocomplete="off", spellcheck="false".


Should fix

5. Blog filter chips don't expose state

All / engineering / product have no aria-pressed (or role="tab"/aria-selected). Screen-reader users can't tell which filter is active. Fix: aria-pressed={active}.

6. Sticky header lets page text bleed through

Scrolled down on Projects, the paragraph "whatever the problem needed." shows through the glass header and collides with zee.dev.

Header bleed

Fix: raise the header's background opacity (≥ 0.85) or a bigger blur (backdrop-blur-xl) and a bottom border. Test over dense text, not just the hero.

7. Focus ring is the browser default

Tabbing works, since "Home" gets Chrome's rgb(0,95,204) auto 1px ring. There is no :focus-visible rule in the stylesheet. On a site this considered, the default blue ring clashes with the indigo accent, and it will vary across browsers.

Default focus ring

Fix: a single global :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }, with border-radius: inherit for pills.

8. Hover is not gated behind (hover: hover)

There are zero @media (hover: hover) rules. The card hover:border-* and any hover transforms will stick after a tap on touch devices. Fix: wrap hover-only styling in @media (hover: hover) and (pointer: fine). Tailwind v4 does this by default; v3 needs future.hoverOnlyWhenSupported.

9. About portrait is under-resolution

<img alt="Portrait of Zee"> has a natural size of 288px and renders at 260×326 CSS px. On a 2× display it is upscaled to ~520px of device pixels and looks soft. loading="auto". Fix: export at ≥ 560px wide (or 3× source), use next/image with sizes, and set width/height to prevent shift.

About

10. Orphaned fourth card on Projects

4 projects in a 3-column grid leaves one card alone in row two with a large empty area. Not wrong, but it reads as unfinished.

Projects

Fix: a 2-column grid at this count, or a featured first card spanning 2 columns.


Nits (optional)

Mobile menu


What's already right

Dark mode


Not verified