OK, now it makes a lot more sense. It wasn't completely obvious before, but now I see that each zone has two cycles. For any given run you need to determine the end time of either the previous zone, or the previous cycle in this zone, depending on whether it's first or second.
An interesting challenge :)
Here's what I came up with.
I made a couple of changes to your table, just to make some of the calculations easier.
First, I added a new 'Zone #' column which contains just the zone number (this makes it easier to find the previous zone, without having to parse out the "Zone #1-1 Front" label each time).
I also crafted a fairly complex formula to perform filters on the table to find the previous zone/cycle/run on which to base each zone's start time. While more complex than simply relying on the previous row's data (which was my original assumption), it also makes the sheet more robust since it dynamically 'finds' the previous zone's runtime, so the zones can be in any order and the formula should still work.
Here's the table I came up with:

You can see my new column C, which uses the formula:
=LEFT(TEXTAFTER(B,"#",1),1)
in cell C2, to automatically extract the zone number from column B. It might be possible to eschew this and use the values in column A, but that's up to you.
The simple formula in the Stop column, cell I2 is:
=H2+F2+G2
which calculates each row's Stop time based on its Start time + Run time + Soak time.
The real magic happens in cell H2 with the formula:
=LET(this_zone,C2,
this_cycle,E2,
this_run,J2,
this_days,D2,
IF(this_cycle=1,
FILTER(H,(D=this_days)×(J=this_run−1),TIME(4,0,0))+FILTER(F,(D=this_days)×(J=this_run−1),0),
FILTER(I,(C=this_zone)×(E=this_cycle−1),0))
)
It uses LET() (available in Numbers 14.4 and later) to grab certain values and store them in named variables. This just makes it easier to read and follow the formula. The heavy lifting happens in the IF() statement:
IF(this_cycle=1...
Checks if this is the first cycle for this zone and chooses one of two formulas depending on the result.
If this is the first cycle for this zone, we run:
FILTER(H,(D=this_days)×(J=this_run−1),TIME(4,0,0))+FILTER(F,(D=this_days)×(J=this_run−1),0),
This runs a FILTER() against column H (Start Time) to find the matching entry where the 'Days' value matches this row's 'Days', and where the run number is the previous run. To this, it adds that row's Run time, using another FILTER().
If there is no previous run (it's the first run of the day, it defaults to 4 AM (via TIME(4,0,0))
If this isn't the first cycle, it uses a different FILTER() to find the stop time of the previous run in this cycle:
FILTER(I,(C=this_zone)×(E=this_cycle−1),0))
This simply finds the Stop time for the row that matches this row's Zone, and where the Cycle number is 1 less than this row's cycle (so, theoretically, the formula will support any number of cycles per row).
Fill this formula down the column and you should be set.
How does that look for you?