From Grade F to Grade A: A Before/After Case Study
An AI wrote a project-management landing page that scored 84/100 (Grade F) on every slop dimension. Here is the line-by-line CSS that dropped it to 18 — burnt sienna instead of blue-500, Bitter instead of Inter, 5px gaps instead of the 4px grid.
A real AI-generated landing page, scanned, scored, and rebuilt line by line. Every change ships with before/after CSS and the score it moved. Starting DNA score: 84 (Grade F). Target: under 25 (Grade A).
The Starting Point
We asked an AI coding assistant to "build a SaaS landing page for a project management tool." Here is exactly what it produced, run through a Sailop scan:
DNA Score: 84/100 (Grade F)
Color: 92 - blue-500 primary, pure #fff background
Typography: 78 - Inter only, uniform weights
Layout: 82 - centered hero, grid-cols-3 features
Animation: 95 - transition-all duration-300 on everything
Components: 80 - rounded-lg shadow-md everywhere
Structure: 72 - standard section ordering
Spacing: 89 - strict 4px grid, uniform paddingSeven dimensions, seven failures. Not one of them is a judgment call — each is a measurable default the model reached for because every other model reaches for it too. (For what each dimension measures, see the 7 dimensions of generic design.) We fix them one at a time, worst-cause first.
Step 1: Fix Color (92 to 24)
The original used bg-blue-500 on the primary and bg-white on the background — the exact pairing flagged in why blue-and-purple gradients are an AI signature. Here is the swap:
/* BEFORE */
--primary: #3b82f6; /* blue-500 */
--background: #ffffff; /* pure white */
--foreground: #000000; /* pure black */
/* AFTER */
--c-accent: #c2592e; /* hue 16, burnt sienna */
--c-bg: #f5f0eb; /* HSL(28, 12%, 95%), warm off-white */
--c-fg: #1c1714; /* warm off-black */
--c-fg-body: #4d443a; /* body text, lighter than heading */
--c-fg-muted: #8a7e72; /* muted text */
--c-faint: #b5a89a; /* hints, placeholders */
--c-secondary: #2e7d6f; /* complementary teal */
--c-border: #ddd7ce; /* hue-shifted border */Key changes:
- Primary hue moved from 217 (blue) to 16 (burnt sienna) — outside the 200-280 band where 80% of AI output lands
- Background went from pure white to a warm off-white at hue 28; foreground from
#000to a warm off-black - Four hierarchy levels for text (fg, fg-body, fg-muted, faint) instead of one black-on-white pair
- A complementary teal secondary, and a border that carries the warm hue instead of
gray-200
New color score: 24. From 92 to 24 in one step.
Step 2: Fix Typography (78 to 15)
The original set font-family: ui-sans-serif, system-ui, sans-serif — which resolves to Inter on most machines, and Inter is the giveaway. Real type:
/* BEFORE */
font-family: ui-sans-serif, system-ui, sans-serif;
/* AFTER */
--f-display: 'Bitter', Georgia, serif;
--f-body: 'Karla', system-ui, sans-serif;
--f-mono: 'JetBrains Mono', monospace;
h1 {
font-family: var(--f-display);
font-weight: 800;
letter-spacing: -0.03em;
line-height: 1.15;
text-wrap: balance;
}
h2 {
font-family: var(--f-display);
font-weight: 700;
letter-spacing: -0.02em;
}
body {
font-family: var(--f-body);
line-height: 1.62;
}
p { text-wrap: pretty; }Key changes:
- A serif display face (Bitter) — AI almost never reaches for a serif headline (why Inter is killing your brand covers 10 tested pairings)
- A humanist sans for body (Karla), not Inter; a real mono for code
- Negative tracking on headings (-0.03em / -0.02em) where AI defaults to 0
- Line-height splits: 1.15 on headings, 1.62 on body, instead of a flat 1.5 everywhere
text-wrap: balanceon headings,prettyon paragraphs
New typography score: 15. Down 63 points.
Step 3: Fix Layout (82 to 22)
A centered hero with symmetric padding and a repeat(3, 1fr) feature grid — the default that turns three features into three identical cards. Restructure it:
/* BEFORE */
.hero { text-align: center; padding: 80px 0; }
.features { grid-template-columns: repeat(3, 1fr); gap: 24px; }
.container { max-width: 1280px; }
/* AFTER */
.hero {
display: grid;
grid-template-columns: 5fr 3fr; /* asymmetric */
padding-top: 148px; /* unique hero padding */
padding-bottom: 92px;
}
.features {
grid-template-columns: 3fr 5fr; /* reversed asymmetry */
gap: 22px; /* off-grid gap */
}
.container { max-width: 980px; } /* specific, not 1280 */Key changes:
- Hero is an asymmetric 5fr/3fr grid, not centered text
- Feature grid reverses to 3fr/5fr instead of three equal columns
- Max-width is 980px, not the Tailwind-default 1280px
- Each section gets its own padding (148 / 92 / 68 / 56px); the gap is 22px, off the 4px grid
New layout score: 22. Down 60 points.
Step 4: Fix Animation (95 to 12)
The 95 came from one line: transition-all duration-300 ease-in-out on practically every interactive element — the fade-in-up motion slop baked into Tailwind muscle memory.
/* BEFORE */
* { transition: all 0.3s ease-in-out; }
/* AFTER */
body {
transition: background-color 700ms cubic-bezier(0.22, 1, 0.36, 1),
color 700ms cubic-bezier(0.22, 1, 0.36, 1);
}
button {
transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1),
background-color 200ms ease;
}
.card {
transition: transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1),
box-shadow 280ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}Key changes:
- Never
transition: all— name the property every time - Custom cubic-beziers, not
ease-in-out; a bouncy(0.34, 1.56, 0.64, 1)for interactive transforms - Durations differ by element: 200ms buttons, 280ms cards, 700ms theme swaps
prefers-reduced-motionhonored
New animation score: 12. The single biggest drop — 83 points.
Step 5: Fix Components (80 to 20)
rounded-lg (8px) plus shadow-md on every card, button, and container. One radius, one shadow, everywhere. Break the uniformity:
/* BEFORE */
.card { border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
.button { border-radius: 8px; }
.container { border-radius: 8px; }
/* AFTER */
:root {
--r-btn: 4px;
--r-card: 7px;
--r-container: 1px;
}
.card {
border-radius: var(--r-card);
border: 1px solid var(--c-border); /* border, not shadow, for elevation */
}
.button { border-radius: var(--r-btn); }
.container { border-radius: var(--r-container); }Key changes:
- Three radii (4px, 7px, 1px) instead of one
- Cards elevate with a hue-shifted 1px border, not a generic drop shadow
- Buttons sit tighter (4px) than cards (7px); containers are nearly square
New component score: 20.
Step 6: Fix Structure (72 to 18)
The 72 is the easiest to miss because nothing on screen looks broken — it is the *order* that gives it away. The AI shipped the canonical stack: hero, logo cloud, three-up features, testimonial, pricing, FAQ, CTA. That sequence is a fingerprint. Reorder around the actual argument:
<!-- BEFORE: the template order -->
<Hero /> <LogoCloud /> <Features /> <Testimonial /> <Pricing /> <FAQ /> <CTA />
<!-- AFTER: lead with the problem, prove, then price -->
<Hero /> <!-- one specific claim, no "trusted by" -->
<ProblemStatement />
<Features /> <!-- asymmetric, see Step 3 -->
<InlineProof /> <!-- one named customer + a real metric, not a carousel -->
<Pricing />
<CTA />Key changes:
- Dropped the logo cloud — a generic "trusted by" strip nobody believes
- Added a problem section before features, so the page argues before it sells
- Folded the testimonial into one inline proof with a real number, not a sliding carousel
- Cut the boilerplate FAQ that restated the features
New structure score: 18. Down 54 points.
Step 7: Fix Spacing (89 to 18)
The 89 is Tailwind's 4px grid taken literally — every value a multiple of 4, every section the same height.
/* BEFORE: all multiples of 4 */
padding: 16px; gap: 24px; margin-top: 32px;
/* AFTER: intentional off-grid values */
--s-3: 3px;
--s-5: 5px;
--s-8: 8px;
--s-14: 14px;
--s-18: 18px;
--s-22: 22px;
--s-32: 32px;
--s-48: 48px;
/* Section padding varies */
--s-hero: 148px;
--s-section-a: 92px;
--s-section-b: 68px;
--s-section-c: 56px;Key changes:
- 5px, 14px, 22px — deliberately not multiples of 4
- Hero padding (148px) is distinct from body sections
- Three section paddings instead of one repeated value
- 3px/5px micro-adjustments for optical tuning
New spacing score: 18.
Final Results
DNA Score: 18/100 (Grade A) [was 84/100 Grade F]
Color: 24 (was 92) -68 points
Typography: 15 (was 78) -63 points
Layout: 22 (was 82) -60 points
Animation: 12 (was 95) -83 points
Components: 20 (was 80) -60 points
Structure: 18 (was 72) -54 points
Spacing: 18 (was 89) -71 pointsTotal improvement: 66 points. Grade F to a solid Grade A.
The Takeaway
None of this made the code more complex. Same sections, same copy, same functionality — the diff is almost entirely values. What changed is the design vocabulary: #3b82f6 became #c2592e, Inter became Bitter, the 24px gap became 22px, the logo cloud disappeared. Every default was traded for an intentional choice. For the full catalog of defaults worth replacing, see the definitive list of 90+ AI design patterns to avoid.
This is what Sailop automates. Run sailop fix ./src --apply and it performs these transformations against your project's generated design system. Or wire it in as a Claude Code skill so the code starts this way, and add CI/CD for design so it never regresses.
Start scanning at sailop.com/scan and see your own before/after.
SHIP CODE THAT LOOKS INTENTIONAL
Scan your frontend for AI patterns. Generate a unique design system. Stop shipping the same blue gradient as everyone else.