3.7 KiB
3.7 KiB
Responsive Checklist
Run through every item before declaring a page done.
Viewports to verify
- 320 px (iPhone SE 1st gen, smallest practical)
- 375 px (iPhone SE 2/3, iPhone 13 mini)
- 390 px (iPhone 14/15/16 default)
- 414 px (iPhone Plus)
- 768 px (iPad portrait,
md:breakpoint) - 1024 px (iPad landscape / small laptop,
lg:breakpoint) - 1440 px (full laptop)
Global guards
body { overflow-x: hidden }inglobals.css.- No
min-w-[...]on root containers. - All decorative absolute elements live inside
relative isolate overflow-hiddenparents. max-w-*containers always paired withmx-auto px-6 md:px-10.
Header / Nav
- Logo left, menu/CTA right on mobile.
- Hamburger button is
size-10minimum (touch target). - Mobile menu drawer closes when a link is clicked.
- No sticky-nav overlap on anchored sections
scroll-mt-24 md:scroll-mt-28on<Section>. - Logo height responsive:
h-11 sm:h-14 md:h-16.
Hero
- H1 clamp:
clamp(2.4rem, 7vw, 6.4rem)never larger upper bound. leading-[1.0]on serif H1 (not0.95clips ascenders).- Top padding generous:
pt-32 sm:pt-36 md:pt-44(clears sticky nav + breathing room). - CTAs use
flex flex-wrap items-center gap-4so they stack on narrow screens. - Stats panel: collapse 1-col-tall mobile layouts to a horizontal 3-col compact row.
Cards & grids
- Mobile:
grid-cols-1. Tablet:sm:grid-cols-2. Desktop:lg:grid-cols-Nmatched to card count. - Avoid
lg:grid-cols-3for a 5-card list (leaves orphan) use 5 or 2-row layout matched to count. - Aspect-ratio used over fixed heights:
aspect-[4/3]oraspect-[3/4].
Typography
- No tracking >
0.22emon small labels. text-balanceon h1/h2.text-prettyon body paragraphs.- Long tokens (cert numbers, emails) use
break-allorbreak-wordsto wrap.
Images
next/imagewithsizesattribute matched to layout.- Hero LCP image gets
priority. object-coveronly when crop is visually intentional.object-containfor logos.- Alt text meaningful never "image" or filename.
Forms
- Field grid:
grid gap-5 sm:grid-cols-2for first/last + email/phone. - Inputs
text-base(16 px+) on mobile to prevent iOS zoom-on-focus. - Submit button respects pending state w/ spinner.
- Field errors render below field, not in a popup.
- Success/error banner renders outside button.
Motion
useReducedMotion()checked in every component using motion props.- Heavy halos / parallax skipped when reduced-motion is on.
- Marquee paused when reduced-motion is on (or replaced with grid).
External links
- All
<a target="_blank">carryrel="noopener noreferrer". - WhatsApp / Instagram / store badges have
aria-label. - App badges sized 132 px (footer) / 140-160 px (CTA).
Footer
- No duplicated link labels across columns.
- Privacy Policy only in Legal column.
- Agency credit row sits below copyright, subtle.
- Watermark contained via
overflow-hiddenon footer root.
Accessibility
- Every interactive element keyboard-reachable.
focus-visible:rings on buttons, inputs, anchors.- Modal/lightbox: scroll-locked body +
Escapecloses + arrows navigate. - Color contrast checked (
text-boneon obsidian = 16:1).
Final smoke test
npx tsc --noEmit # clean
curl -s -o NUL -w "%{http_code}" http://localhost:3000/... # 200 on every route
Grep for placeholder leaks:
grep -rn 'href="#"' src/
grep -rn 'href=""' src/
grep -rn 'href="/#' src/
Should all return zero (unless intentional same-page anchors with matching IDs).