Polish: the last 5%

None of these survive an A/B test alone. Together, they're why users say 'premium'.

Users can't name what's wrong, but they stop trusting the product. ## Image outlines on white backgrounds White-edged images bleed into near-white backgrounds. ```css img { outline: 1px solid rgba(0, 0, 0, 0.1); outline-offset: -1px; } ``` `outline` instead of `border` because outlines don't take up layout space. `outline-offset: -1px` pulls it inside the image edge. In dark mode, flip the colour: ```css :root { --image-outline: rgba(0, 0, 0, 0.1); } [data-theme="dark"] { --image-outline: rgba(255, 255, 255, 0.1); } img { outline: 1px solid var(--image-outline); outline-offset: -1px; } ``` Skip for full-bleed heroes, images with dark borders, and decorative illustrations. ## Shadow refinement Two layers: a tight contact shadow and a wider ambient shadow: ```css .card { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 4px 12px rgba(0, 0, 0, 0.04); } ``` For hover elevation: ```css .card:hover { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 8px 24px rgba(0, 0, 0, 0.06); } ``` Dark mode shadows need different treatment. `rgba(0,0,0,x)` shadows are invisible on dark backgrounds. Use border-based elevation or subtle ambient glow (`rgba(255,255,255,0.03)`). Most borders shouldn't exist. ## The separator audit Every border should justify itself. Could spacing or a background tint replace it? Where borders earn their keep: - Between unrelated regions (sidebar / main content). - On clickable cards, so the user sees boundaries. - On input fields. Where borders are noise: - **Card with shadow.** The shadow already separates it. - **Grouped, indented list items.** Per-item dividers fragment the grouping. - **Header with a coloured background.** The colour _is_ the separator. - **Stacked dividers.** Two separators at similar contrast read as a tangle. ## Navigation chrome hierarchy Primary navigation is visually strongest. Secondary chrome (breadcrumbs, local tabs) recedes. Fix with contrast reduction: lighter text, thinner borders, less padding on secondary chrome. ## Common mistakes - **`border` instead of `outline` for image anchoring.** Layout shifts. - **Heavy outlines** (`rgba(0,0,0,0.3)+`). Reads as a frame, not an anchor. - **Single-layer shadows with high spread.** Looks like a grey box. - **Top and bottom border on every section.** Doubles thickness at boundaries. - **High-contrast borders by default.** Use `rgba(0,0,0,0.08)`, not `#000`. - **Borders that vanish in dark mode.** Pair with a light-on-dark token.