Ask an agent to “make the pricing card feel tighter” and you often get a className novel: spacing, colors, type scale, shadows, and a responsive grid rewrite in one PR. Reviewers can’t tell which change fixed the density problem and which ones were drive-by taste.

I’ve started capping agent Tailwind work to one utility family per PR. Spacing or color or typography or layout — not all four because the model felt creative.

What counts as a “family”

Group the way reviewers actually skim class strings:

  • Spacing — p-*, m-*, gap-*, space-*, and related inset padding/margin
  • Sizing — w-*, h-*, min-*, max-*, size-*
  • Color — bg-*, text-*, border-*-* (color), ring-*, fill-*, stroke-*, opacity modifiers on those
  • Typography — text-* sizes/weights (text-sm, font-medium), leading-*, tracking-*, font-* families
  • Layout — flex, grid, items-*, justify-*, col-span-*, order / place utilities
  • Effects — shadow-*, opacity-*, blur-*, transitions / animations

Pick one family as in-scope. Neighbor families stay frozen unless a single class is required for the spacing change to compile (rare — call it out).

Tailwind v3 and v4 both expose these families; v4’s dynamic spacing (mt-17, etc.) makes it easier for agents to invent one-off values. A family cap still applies — “any spacing utility” is still one family, not a license to restyle the card.

Prompt that keeps the diff narrow

Tighten vertical density on PricingCard. Only Tailwind spacing utilities may change. Constraints: - Utility family allowlist: spacing only (`p/m/gap/space` and directional variants) - Do not change color, typography, shadow, or flex/grid structure - Prefer existing scale steps already used in neighboring cards — no arbitrary values `[…]` unless you explain why the scale fails - Touch only `PricingCard.tsx` (and its story if classNames are demonstrated there) - Summarize the spacing before → after in the PR body If density cannot improve without a layout change, stop and propose a follow-up PR — do not expand scope here. 

The stop condition matters. Agents that hit a wall tend to “just fix the flex” mid-PR. You want a written proposal, not scope creep.

Example of an in-family diff

Ask: tighten vertical density.

- <div className="flex flex-col gap-6 py-8 px-6 shadow-md bg-white"> + <div className="flex flex-col gap-4 py-5 px-6 shadow-md bg-white"> 

Spacing changed (gap, py). Layout (flex flex-col), color (bg-white), and effects (shadow-md) stayed put. That’s a reviewable family-scoped change. If shadow-md became shadow-lg and bg-white became bg-slate-50 in the same breath, the PR stopped being about density.

How to review the className soup

Before reading JSX logic, diff the class strings:

  1. List every added/removed utility
  2. Bucket them into families
  3. If two or more families moved for a one-line ask, send it back

A tiny checklist in the PR template helps:

## Tailwind scope - Family in this PR: spacing | sizing | color | type | layout | effects - Other families unchanged: yes / no (explain exceptions) 

Reject / send back

Reject

  • Spacing + palette + type rewrite for “make it tighter”
  • New arbitrary values (p-[13px]) when the scale already has a neighbor
  • Responsive variant explosion (sm/md/lg full restyle) inside a spacing-only ask
  • Swapping space-y-* for a flex+gap refactor “for performance” without that being the ticket (layout family — separate PR)
  • Editing @theme / tailwind.config shared scales inside a component polish PR

Accept

  • One family, clearly named in the PR
  • Class changes that mirror neighbors on the same page
  • A short before/after note (“py-6 gap-4 → py-4 gap-3”)
  • Deferred proposals for layout or token work

Why one family beats “small diff”

Line count lies. Fifty class churn lines in one family are reviewable. Twelve lines that mix color and grid are not — they hide accidental contrast regressions next to a harmless padding tweak.

This pairs with diff budgets and token freezes elsewhere in the series: blast radius is about kind of change, not only file count.

Tiny habit

Next time an agent returns a rainbow className diff, don’t argue taste token-by-token. Reply with the family cap: spacing only (or whichever family matched the ask), restore the other utilities, and ask for a follow-up if layout is truly required. Reviewers should be able to say what changed in one breath.