100vh is defined against the viewport with the browser chrome hidden. On iOS Safari the address bar is visible until the user scrolls, so a full-height hero is taller than the space actually available, and the bottom of it sits underneath the toolbar.
.hero {
min-height: 100vh; /* taller than the visible area on iOS */
}
.hero {
min-height: 100%; /* with html, body { height: 100% } */
}
There is no CSS-only fix that is correct in every state, because the viewport genuinely changes size as the toolbar collapses. Percentage height off a full-height html and body avoids the overshoot; measuring window.innerHeight and setting a custom property is the other common answer, at the cost of a resize listener. Either way, test on a real device — the simulator hides the problem.