This is the DOM version of the classic "populate next right pointers" tree problem. Given a target element, find the one immediately to its right at the same depth — the next node on its level, reading left to right. The twist that makes it more than element.nextElementSibling: the neighbor might live under a different parent. The last child of one subtree's right neighbor is the first child of the next subtree at that depth.
Implement nextRightSibling(root, target). Return the element right after target on its level, or null if target is the rightmost at its depth (or is the root, or isn't found).
function nextRightSibling(root, target) {
// returns the element to the right of target at the same depth, or null
}
// <div id=r>
// <div id=p1><i id=a/><i id=b/></div>
// <div id=p2><i id=c/><i id=d/></div>
// depth-2 order: a, b, c, d
nextRightSibling(r, b); // c — crosses from p1's subtree into p2's
nextRightSibling(r, d); // null — rightmost at its depth
nextElementSibling only sees siblings; you need the next node across the whole level.target is the answer.target is the last node on its level, there's nothing to its right.