subroutine build_grounded_mask(nx, ny, nz, h_old, h_floor, mask, n_grounded)
!! ONE coalesced pass: mask(i,j,1) = 1.0 iff any layer of column (i,j)
!! is strictly below the floor; `n_grounded` counts them (explicit
!! OpenACC reduction — a `sum()` on a present-mapped array would run
!! host-side under NVHPC non-managed mode and read the stale shadow).
integer, intent(in) :: nx, ny, nz
real(wp), intent(in) :: h_old(nx, ny, nz)
real(wp), intent(in) :: h_floor
real(wp), intent(out) :: mask(nx, ny, 1)
integer, intent(out) :: n_grounded
integer :: i, j, k, n
logical :: g
n = 0
do concurrent(j=1:ny, i=1:nx) local(g, k) reduce(+:n)
g = .false.
do k = 1, nz
if (h_old(i, j, k) < h_floor) g = .true.
end do
if (g) then
mask(i, j, 1) = 1.0_wp
n = n + 1
else
mask(i, j, 1) = 0.0_wp
end if
end do
n_grounded = n
end subroutine build_grounded_mask