The nodes in this case are just the tiles. Maybe some people are used to thinking of them as just points, but the tiles are just an area that represents a very large point of walk-ability. Same principle with voxels for atoms/molecules/simulated particles...
What's important about height and obstacles is recording what neighbors are 'visible' for each node. So on a completely flat plane, each node will have four legitimate neighbors since there's no obstacles for walking to another node. It might help to think of the higher tiles as the lower tiles but surrounded by thin walls, and the ramp would be the open part of the wall. What a path finding algorithm would do (in the case of A*) is similar to a flood fill in paint, but the "next pixels we fill per tick" is determined by a heuristic function (distance usually). If the walk-able tiles are white pixels and the walls are black in that case, then the flood fill will wrap around the wall and eventually find the destination. It may not be efficient because the distance to a higher tile can just be one tile over realistically, but instead the algorithm will "blob up" and when the edge of the blob reaches the ramp it will snipe the destination.
So the important thing to do is keep track of a tile's neighbor's accessibility when you generate them. Since you're using a 2D system, just check the four neighbors of a tile when you generate it and compare z values to determine visibility, as a starting point. From the perspective of a regular tile, a ramp could be treated as accessible for a range of z values depending on its rotation. This means for each type of walk-able tile defined in the game, it needs a visibility determination function for every other type including itself, so maybe define this abstractly in a nice virtual function. Don't forget to update the already existing neighbors too, each tile has to consider its four neighbors and if one doesn't exist but will exist soon then it needs an update when its actually created.