From Grade F to Grade A: A Before/After Case Study
A real walkthrough of taking an AI-generated landing page from a DNA score of 84 (Grade F) down to 18 (Grade A) with specific, measurable changes.
Let's take a real AI-generated landing page and transform it. Not in theory. In practice, with before/after code, scores, and explanations for every change. 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's what it produced, and the Sailop scan results:
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 paddingEvery single dimension is deep in AI territory. For an explanation of what each dimension means, see what is AI slop: the 7 dimensions of generic design. Let's fix them one by one.
Step 1: Fix Color (92 to 24)
The original used bg-blue-500 for the primary color and bg-white for the background. Here's the transformation:
/* 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-secondary: #2e7d6f; /* complementary teal */
--c-border: #ddd7ce; /* hue-shifted border */Key changes:
- Primary hue moved from 217 (blue) to 16 (burnt sienna) -- outside the AI band
- Background changed from pure white to a warm off-white with hue 28
- Text color changed from pure black to a warm off-black
- Added 4 hierarchy levels for text color (fg, fg-body, fg-muted, fg-faint)
- Added a complementary secondary color
- Borders are now hue-shifted, not generic gray
New color score: 24. From 92 to 24 in one step.
Step 2: Fix Typography (78 to 15)
The original used font-sans (which resolves to Inter/system-ui). Let's add real typography:
/* 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:
- Display font is a serif (Bitter) -- AI never picks serif for headings (see why Inter is killing your brand for 10 tested pairings)
- Body font is a humanist sans-serif (Karla) -- not Inter
- Monospace font is specified for code blocks
- Letter-spacing is negative on headings (AI defaults to 0)
- Line-height varies: 1.15 for headings, 1.62 for body (AI uses 1.5 for everything)
- text-wrap: balance on headings, pretty on paragraphs
New typography score: 15. Down 63 points.
Step 3: Fix Layout (82 to 22)
The original had a centered hero with symmetric padding and a repeat(3, 1fr) features grid. Restructuring:
/* 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 uses asymmetric 5fr/3fr grid instead of centered text
- Features grid uses reversed 3fr/5fr instead of repeat(3, 1fr)
- Max-width is 980px (specific) instead of 1280px (Tailwind default)
- Each section has different padding (148px, 92px, 68px, 56px)
- Gap uses 22px instead of 24px (off-grid)
New layout score: 22. Down 60 points.
Step 4: Fix Animation (95 to 12)
This was the worst dimension. The original used transition-all duration-300 ease-in-out on virtually every interactive element:
/* 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-- always specific properties - Custom cubic-bezier curves instead of ease-in-out
- Different durations for different elements (200ms for buttons, 280ms for cards, 700ms for theme transitions)
- prefers-reduced-motion media query included
- Bouncy easing (0.34, 1.56, 0.64, 1) for interactive transforms
New animation score: 12. The biggest single improvement, down 83 points.
Step 5: Fix Components (80 to 20)
The original used rounded-lg and shadow-md on every card. Introducing variety:
/* 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 instead of shadow */
}
.button { border-radius: var(--r-btn); }
.container { border-radius: var(--r-container); }Key changes:
- Three different border-radius values (4px, 7px, 1px) instead of one
- Cards use border instead of shadow for elevation
- Buttons are tighter (4px) than cards (7px)
- Containers are nearly square (1px)
New component score: 20.
Step 6: Fix Spacing (89 to 18)
The original used Tailwind's strict 4px spacing grid:
/* 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:
- Values like 5px, 14px, 22px are NOT multiples of 4
- Hero padding (148px) is distinct from section padding
- Three different section paddings instead of one
- Small values (3px, 5px) for micro-adjustments
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. From a grade F to a solid Grade A.
The Takeaway
None of these changes made the code more complex. The page has the same sections, the same content, the same functionality. What changed is the design vocabulary. Every default was replaced with an intentional choice. For the full catalog of defaults to replace, see our definitive list of 90+ AI design patterns to avoid.
This is what Sailop automates. Run sailop fix ./src --apply and it performs these transformations based on your project's generated design system. Or use sailop as a Claude Code skill to generate code this way from the start. To enforce these standards on every commit, set up CI/CD for design.
Start scanning at sailop.com/scan and see your own before/after scores.
Try Sailop
Scan your frontend for AI patterns. Generate a unique design system. Ship code that looks intentional.