The Long Way Around
The long
way around
Compare a quiet spring, the Ever Given blockage and the Red Sea disruption. The counts show container ships passing measured chokepoints, making it possible to see the difference between a temporary stop and a sustained detour around Africa.
On March 23, 2021 a 400-meter container ship wedged itself across the Suez Canal. Transits fall to near zero for six days while ships stack up in the Red Sea — then a 36-ship convoy bursts through the day after she floats free.
Traffic picks a lane, and the lanes trade places
Each ribbon is three days of real container-ship transits recorded at the downstream gate. Hover or click a ribbon to isolate its corridor.
Three corridors, nine measured gates
Leg width is the trailing 7-day average of real daily container transits at the gate each leg crosses; particles indicate direction.
Track accumulated shortfall at the selected gate
Daily bars are real transits minus this scenario's own pre-event pace at the watched gate, so the running level reads as accumulated shortfall. Selecting a corridor moves the gauge to its gate.
Compare daily traffic across all three periods
Each dot is one real day measured at Suez, Bab el-Mandeb, the Cape of Good Hope, and Panama. The quiet spring forms the reference cluster. The Ever Given period departs mainly along the Suez axis, while the Red Sea period shifts traffic from Bab el-Mandeb toward the Cape as Panama also runs below its reference pace. Select a dot to open that day in the replay.
- Suez / day
- 2 – 36
- Bab el-Mandeb / day
- 2 – 32
- Cape / day
- 1 – 24
- Panama / day
- 2 – 12
One replay, four views
The map shows routes, the flow chart follows traffic through chokepoints, and the daily bars compare it with the earlier pace. The matrix puts all three periods side by side. Select a corridor or a day to carry the same comparison across views.
// Three IMF PortWatch periods share one replay shell. const [scenarioId, setScenarioId] = useState("everGiven") const [cursor, setCursor] = useState(scenarioDays(scenarioId)) const currentTime = replayTimeForCursor(scenarioId, cursor) // Declaratively derived snapshots of the selected scenario. <FlowMap nodes={locations} flows={flowsAtTime(scenarioId, currentTime, selectedCorridor)} areas="land-110m" /> <ProcessSankey nodes={gates} edges={processEdgesAtTime(scenarioId, currentTime, selectedCorridor)} domain={domainFor(scenarioId)} pairing="temporal" /> // Deviation-from-pace bars mirrored through the imperative changeset API. useSyncedPushData(waterfallRef, visibleDeviationRows, { id: "id", resetKey: `${scenarioId}:${watchedGate}`, }) // The matrix holds every day of all three scenarios at once — // clicking any point jumps the replay to that scenario and date. <ScatterplotMatrix data={PORT_MATRIX_ROWS} fields={["suez", "babElMandeb", "capeOfGoodHope", "panama"]} colorBy="scenario" onClick={(row) => { setScenarioId(row.scenarioId) setCursor(row.dayIndex + 1) }} />