Building the village tileset for Oakheart Exteriors, the part that took the most iterations was not the cottages — it was getting grass to meet dirt, cobblestone and water without the join reading as a drawn line. Three things fixed it, in case they are useful to anyone else doing 16x16 terrain.
1. Nine pieces, not four. The set is tl / t / tr / l / c / r / bl / b / br, keyed by which sides show the base material. Four corners alone means you can never draw a patch narrower than two tiles, and every path in a village is one tile wide somewhere.
2. Jitter the straight runs. The first pass cut each edge at a fixed 4px inset, so every tile in a row lined up perfectly — which is exactly what makes a seam read as a ruler instead of a shoreline. Pulling the edge in by 1px on every third row down the left side and every fourth down the right broke it up. Each piece is seeded off its own key, so it still re-renders identically every build.
3. Vary the inset per material. Cobble sits at a 3px inset, dirt and water at 4. Cobble already carries its own visual noise from the 1px mortar gaps between stones, and giving it the same wide organic border as dirt made the patch edge fight the stone pattern underneath it.
Full sheet below — 98 tiles at 16x16, with three of those transition sets (grass to dirt, grass to cobble, grass to water), plus three roof sets, walls, fences, market stalls and props.

Pack and a free 19-tile sample here: https://z3er1n.itch.io/oakheart-exteriors — worth saying plainly that the sprites come out of a Python generator I wrote with AI assistance rather than being drawn by hand in an editor, so the pages carry itch's AI-assisted (graphics) disclosure.