Peru Offshore Planning — Wind & Route Planner
Race navigation for TIRRENO — Beneteau First 42, Offshore Racing Congress (ORC) rating PER-120 — on Peru's central coast, from La Punta & Callao to Paracas.
What it does: it takes the two global weather models (ICON & ECMWF), keeps only honest open-sea data, corrects it nightly against six real anemometers, and bends it live toward what the instruments are reading right now. That wind then becomes a race plan: the 🎯 TARGET at 100% of the ORC polar — the benchmark to beat — with ⚡ optimized boards through the evolving breeze and 🎲 odds (P10 · P50 · P90, layline calls) you can promise a crew on.
The wind along a leg is measured, not assumed. Each mark, each land-avoidance gate, a point roughly every 20 nm down a long passage, and — on the longest hop — a point 4 nm either side of the track all carry their own corrected forecast. The plan reads that profile at the boat's real position and hour, blending by speed-weighted vectors so a light contrary breeze can never out-vote the real one. The sampling is budgeted (8 extra points per plan) because it shares the dashboard's daily forecast quota.
And it keeps score. Record a track with ● TRACKS while a plan is up and the app logs, fix by fix, what it predicted right there against what actually happened — boat speed vs the polar, and forecast wind vs the nearest real anemometer. PLAN vs REALITY appears at the top of ROUTE PLAN with the bias, the typical miss and a per-leg breakdown, and exports as CSV. A few weekends of sailing will say plainly whether the forecasting is earning its keep.
It refuses rather than guesses. If a saved route names a mark that has left the chart, the app will not plan it, will not draw it, will not export it and will not replay it — it names the mark instead. The old behaviour quietly dropped the mark, which made the course shorter than the one you picked and handed Navionics a route with a leg missing.
No waypoint you do not need. The router used to carry land-avoidance gates on legs the open water did not need — YCP → Ancón went the long way round San Lorenzo for an extra 3 nm on a 17.6 nm course, while the direct line was actually further from the rocks. Every chain is now pruned against the chart: a gate survives only if the course without it would be longer or closer in. Your own corridors and the mandatory roundings are never touched.
No manoeuvre you did not pay for. Tacks, gybes and sail changes at a mark used to be free — the router forgot which tack and which sail you finished the previous leg on, and its cost function only bills what it can remember. Your state now carries across every boundary, so a needless peel at a rounding costs the two minutes it really costs, and the plan stops proposing them.
The replay names the leg you are watching. Both ends of the current leg are pinned and labelled — your mark with its route number, or the flag when the router put a gate there — and the whole-route labels step aside while the video runs, so nothing stacks. On a course that rounds the same mark twice the return visit is numbered from its own position in the route, not from the first time you passed it. Charted hazard labels stay up: those are safety.
Which way round is now a decision. The route through the islands used to come from hand-written lists of gates, chosen by geometry. It is now searched on a graph and picked on elapsed time — so a longer way round that lets you carry the A3 can win, which is the call you have been making by eye. When a second option is genuinely live it is drawn in green, thinner, and the card tells you how much it costs, how often it wins, and at what breeze the call flips. Magenta is always whichever reaches the marks sooner. When there is no real choice the app says so rather than drawing a decorative second line.
P1 NO LONGER DETOURS INTO ANCÓN BAY (v364). The race leg is Isla Grande → YCP, and the router was sending it through ⛳ Boca Ancón — a gate the owner never asked for, 4 nm EAST into Ancón bay, on a leg whose course is 162°. It cost +5.13 nm on an 18.5 nm leg.
It was not stubbornness — it was the only legal chain. The direct line leaves the mark straight into Isla Grande's own south shore: the narrowest point sits 0.31 nm off the mark with zero clearance, and Isla Grande → ⛳ W Pescadores clips a charted islet at 28 m. With no gate on the west side, going east and doubling back was genuinely the only way through. The fault was a missing option, not a bad choice.
So the option was added rather than the symptom deleted. ⛳ SW Isla Grande (11°46.50′S 77°16.62′W) is the corner you actually sail: the race rounds Isla Grande to the north, so you come down its west side. It costs +0.70 nm against the direct line, with ≥0.33 nm clear on both hops and 0.57 nm of water at the gate. Boca Ancón now loses on distance and drops out by itself — it is not hardcoded away, and it is still chosen where it belongs, on YCP↔Ancón, which still routes ⛳ W Pescadores → ⛳ Boca Ancón as before. P1 is now 69.1 nm and reads Camotal 2 (W) → ⛳ N San Lorenzo → Las Hormigas → Isla Grande → ⛳ SW Isla Grande → YCP.
⛳ gates are not course marks. W Pescadores, Boca Ancón, SW Isla Grande and the rest are routing aids — they appear only when the search finds them faster or the water leaves no choice, never because a course demands them. That is why they carry the ⛳ prefix, and why the replay timeline gives them a hairline instead of a labelled dot.
THE SILLY TACKS ARE GONE — AND THEY WERE NOT WHERE I SAID (v355). The plan was drawing two tacks and 1.71 nm sailed to make good 0.17 nm — a 340 m gate-to-mark approach at Islotes Horadas, sailed ten times over. My first diagnosis blamed the topology search for ignoring the wind. That was wrong: the topology search scores every candidate through the same sail-aware, manoeuvre-charged simulator the plan uses, so it already optimises on wind, then sail, then the ORC targets. The fault was one line lower down.
The step was a fixed 10 minutes. The beat simulator advanced the boat by a constant RT_DT of 10 minutes — 0.83 nm at 5 kt — and while BEATING nothing bounded it. (The fetch case was clamped; the beat was not.) On a 0.17 nm hop that is five times the whole leg in a single step: the first close-hauled board blew past the tack point four times over, and the boat had to fetch all the way back. The two-board planner had the same unbounded step at 5 minutes, and the isochrone optimizer stepped the same flat clock regardless of whether the leg was 0.2 nm or 100.
FIVE constants, all written for a leg measured in miles. Fixing the step only uncovered the next one behind it, and then the next. Every one of them is the same mistake — a number that is sensible on a five-mile beat and absurd on a three-cable one — so every one now scales with the leg: ① the step ends ON the layline (found by bisection on the same wind it is already using) and otherwise gives every leg at least ten steps; ② RT_MIN_BOARD, the anti-tack-spam rule, is in HOURS (0.75 h = 45 minutes) and pinned the boat in place for longer than a short leg takes; ③ the drawn path was sampled every 0.3 nm — further than the whole leg; ④ boards under 0.35 nm were discarded as "simulator jitter", and both boards of this beat are 0.11 nm, so the real tack plan was thrown away; ⑤ the arrival tolerance was 0.08 nm — 148 m, which is 47 % of a 340 m leg, so the sim declared the mark reached half a leg short, after a single board.
What the leg does now. It sails one board on port for 0.145 nm, then fetches 0.069 nm to the mark — 0.21 nm to make good 0.165 nm, a ratio of ×1.27 against a geometric floor of ×1.33 for its 41° beat angle. Below the floor because the last stretch is a fetch, not a beat. That is the answer a navigator would give.
Measured on four routes, against physics rather than against zero. A dead-upwind leg legitimately sails ×1.33, so the test is the ratio against 1/cos(beat angle), not against the rhumb. R3, R14, R6 and R5 now have no leg worse than 25 % off its own physical floor, where before R3 and R14 carried ×10.4 and ×10.1 legs and R5 a ×2.63. R5 also got genuinely quicker — 2h45 to 2h39, six minutes found on a leg that had been sailing 1.9 nm to cover 0.7.
An inconsistency this exposed. The route's ETA was never wrong — it comes from a different simulator, and R3's total is 2h29 before and after. But the drawn track and the tack count came from the beat simulator, so the app was showing a 1.71 nm track for a leg it had timed at 2.0 minutes: a track implying 51 knots. Drawing and clock now agree — across R3's ten legs the implied speed is 5.1 to 6.9 kt on every one. That ratio is the regression test: if a track and its duration ever disagree again, this whole family of bugs is back.
NEW ORC CERTIFICATE — 27 July 2026 (v353). The app now sails the certificate issued today, ORC ref 03460004VOQ (valid to 31/03/2027, VPP 2026 1.00), replacing 03460004TLM of 19 June. Every rated boat velocity, both VMG rows, the beat angles and the gybe angles were re-read from "Rated boat velocities in knots" and dropped straight into the polar — so 🎯 TARGET, 🎲 Monte Carlo and ⚡ the isochrone optimizer are all now benchmarked against the new certificate. The single-number scoring figures on it are APH 555.2 s/nm Time-on-Distance (1.0808 Time-on-Time) and Windward/Leeward 686.9 (0.8735), CDL 9.613. Note that the APH does not set boat speed — it is the handicap the race is scored by. Boat speed comes from the VPP table, and that is what changed.
What actually moved. The new certificate is a little slower in light air and a little quicker in a breeze, and it points slightly lower: the beat angle widens by about 0.8° at 4 kt and 0.4° at 6 kt, and upwind VMG drops ~2% at the bottom of the range (2.41 → 2.36 kt at 4 kt, 3.43 → 3.38 at 6 kt). Downwind it gains: 135° at 24 kt goes 9.84 → 9.85 kt and 120° at 20 kt 9.18 → 9.19 kt, with run VMG up across the board. The gybe angles are unchanged. In practice a light-air beat rates a shade slower than it used to and a heavy-air run a shade faster — which is the direction the remeasured headsail (G1.2, remeasured 27/07/2026) would suggest.
Measured, not asserted. Both certificates were run through the planner back to back on the SAME wind and the same departure, so only the polar differed. At the speed-function level the new certificate is 0.85% slower close-hauled in 8 kt (Vmc at TWA 30° falls 5.4495 → 5.4034 kt) and marginally quicker on a beam reach (90° at 8 kt, 6.66 → 6.67 kt). Over the whole of R3 — YCP → Camotal → Horadas → YCP, 2h29, ten legs — the new certificate costs 35 seconds (2h29:10 → 2h29:45). The polar rows were also cross-checked against the certificate's own Time Allowances in secs/NM table, which is the reciprocal of the speed table: every one of the 27 sampled cells agrees to within 0.005 kt, i.e. rounding.
Sail areas are now the certificate's own. The drawn sails used First 42 class figures as placeholders; they now use the measured inventory — A2 132.77 m² ("ROJO"), A3 113.77 m² ("BLANCO"), mainsail 37.38 m², and J2 = the certificate's F1 jib at 39.34 m². J3 has no counterpart in the certificate inventory, so it keeps its class estimate. Area affects only how big the sail is drawn on the replay; speed has never come from it.
Every leg gets watchable screen time (v350). Five minutes is the replay's target running time, but no leg is ever cut below 30 seconds — you cannot study a rounding that flashes past in three. Screen time is handed out in proportion to how long each leg actually takes to sail; every leg that falls under the floor is topped up to it and the surplus is taken back, pro rata, from the legs that are over it. If the floors alone need more than five minutes — any route with more than ten legs — the video simply runs longer rather than cutting a scene short of the minimum.
The timeline (v350). The whole route lies across the top of the chart: one tap target per waypoint, gates and intermediate marks included, each labelled with its ETA. Drag the ticker to scrub, or tap a mark to jump the replay straight to it. Segment widths are screen time, so the ticker travels at a constant rate and the bar reads as the video's own clock. The knob is painted in the colour of the sail actually up at that moment — grey J2/J3, white A3, red A2 — so you can see the peel coming before you reach it.
Where is the boat? (v350) The camera used to re-frame only when the leg index changed. But a plan can be replaced underneath a running replay — the replay source is rebuilt a few seconds after a new route is planned, and the optimiser fills the sailed tracks in later still — and through both of those the leg index sits at 0, so the camera never moved. You got the new route's panel over the old route's camera, with boat, marks and track all off the screen. The camera now re-frames whenever the plan changes identity, and underneath that sits a hard safety net: wherever the camera came from, if the boat is not on the visible chart it re-frames within half a second. Verified by replaying all 25 library routes end to end and checking the boat's screen position at every sample.
Two boats, one replay. When a second route is genuinely live the Route Video sails them both: your plan in navy on the magenta track, the alternative in green on its own. The clock spans both, so whoever gets there first parks at the mark and waits while the other finishes — and the finishing order is the one the ranking decided, not an artefact of the animation. The sail colours stay true on both — J2 grey, A3 white, A2 red — because watching the A3 against the J2 is the whole reason for a second boat; you tell them apart by hull and by the track underneath. Both are painted into the same frame, so the exported video carries both with nothing extra to do.
What to steer, not just where to go. The numbers that change every second live on the chart, beside the boat, in a six-field instrument read the way a helmsman reads one: HDG · BTW (what I hold, where the mark is), TWA · TWS (the angle to the breeze, and the breeze), ORC target · DTW (what the boat should be doing, and how far to the next waypoint — the coming tack or gybe, not the far end of the leg). The type is coloured by the sail actually up — A2 red, A3 white, J2/J3 grey — so the instrument tells you the wardrobe without spending a field on it, and TWS carries the wind colour, the same scale as the bar under the chart and the streaks around the boat, so the breeze reads without parsing a number. SOG has gone: it only ever restated the polar target plus the current, and the target is the number you steer to. If HDG and BTW disagree, that gap is the current and the leeway, and it is drawn to scale on the chart.
DTW NOW MEASURES TO THE NEXT WAYPOINT, NOT TO THE END OF THE LEG (v428). The three fields that answer how far and how long — DTW, BTW and ETA WPT — all pointed at the leg's finishing mark, on every leg, always. On a long beat the box read DTW 114 nm while the tack you were sailing to was three miles away, and the field labelled ETA WPT gave the hour you would round the mark, hours later. A chartplotter that cannot tell you the range to the next manoeuvre is not a chartplotter.
Every board change is a waypoint with a name, a range and an hour. Each leg now carries an ordered waypoint list built on the track the boat actually sails — the optimised path when there is one, not the rhumb line — so a waypoint's distance is the distance through the water, not across the chart. The box locks onto the first waypoint ahead of the boat and counts down to it; when it is passed, the next one takes over. Both labels name their target, so you read DTW T3 and ETA T3 · tack rather than two numbers about somewhere else. When only the mark is left they read DTW and ETA WPT exactly as before. The yellow heading ruler shortens with them, so its ticks now measure the board you are on.
Tack, gybe or neither is decided by the wind, not by a flag. The manoeuvre at a waypoint is read from the transition between the two boards: if the breeze changes side it is a tack when both angles are inside 90° and a gybe when both are outside, and if the breeze stays on the same side the boat has only altered course — which the label says, instead of calling it a gybe. Measured on the ⛳ Islote Pelado running leg: the board change at 11.0 nm holds the wind on the same side and comes up 36°, so it reads course change, and calling it a gybe would have been wrong.
A number that was never a plan. The leg table's tack count fell back to distance ÷ 2.5 when no board list existed — a 115 nm beat advertised "46 tacks", which is not a plan, it is arithmetic. It never touched timing and the table always marked it est., but read beside the two waypoints actually drawn it looked like 44 missing ones. The real board count is the only number the chart draws from.
EVERY TACK AND GYBE IS A WAYPOINT (v429). A turn taken inside a board used to leave no mark: the FETCH branch kept its key through a whole corner and stored two boards as one, with the heading averaged between them — on R9 L4, 1.28 nm out and 0.79 nm back filed as one 2.09 nm board on a heading the boat never sailed. A turn of more than 35° now closes the board, and when the isochrone optimizer governs a leg its boards supply the waypoints instead of the layline simulator's. 22 routes, 142 legs, 267 waypoints, 125 manoeuvres, none of them unmarked.
THE MERGE CAN NO LONGER AVERAGE A BOARD INTO THE NO-GO CONE (v508). Auditing P6 the owner caught board 4-5·B — “FETCH · lays mark” — printed at HEADING 169° with the wind at 185°: TWA 15°, deep inside the certificate's ~38° cone, on a card claiming the boat lays the mark. The sailed record was honest: a 1.17 nm fetch at TWA 39°, a 7-metre luff stub across the wind at the cone edge, then 0.21 nm more of fetch. But the noise merge folded the stub in with every simulator step weighing the same, so 7 metres of luff rotated a 1.4 nm board's printed heading by 23°. A board's heading is now weighted by the distance each step actually made — a stub cannot rotate a board — and a sweep after the merge re-merges any leg whose folded board would still claim an angle inside the cone, this time refusing to fold manoeuvres (a turn is a waypoint — v429, above). Certifying that sweep exposed one more: the fold was mutating the raw record itself, so the guard that restores it after an over-merge restored a poisoned copy and double-counted the folded tail — 2.33 nm of boards for 1.99 nm sailed on the N San Gallán gate leg. The merge now works on copies; the record stays pristine. The drawn path never lied; the cards now match it.
THE SEA PARAMETER IS ON THE BUTTON NOW (v446 · favorability colours v452). The 〜 button itself reads the number the owner asked for: effective wave height, which side the sea hits (▲ head · ► beam · ▼ following), and the signed NET effect of the sea on this course — e.g. 〜 2.2m ▲ −5.2% against a head sea, 〜 0.6m ▼ +0.1% surfing a following one. The net folds together the head-sea brake, the wave-leeway cost and the Stokes-drift push projected on your heading — the same rtWaveFx numbers the isochrone charges. The colour is favorability, not severity: green the sea pushes you, blue negligible, amber it costs you, red it costs hard — severity is already the metres in the text. The tap still opens the full per-leg table, now with WAVE PUSH and NET IMPACT rows.
What the sea is doing on the whole route, not just here (v430). The 〜 SEA button now opens the leg you are on and a table of every leg ahead — wave height, shelter, whether it hits head, beam or following, and what it costs in boat speed — with the roughest leg named. The hours-sailed counter above the timeline has gone: the bar already carries distance sailed and every waypoint carries its hour.
Isla San Gallán was not on the chart (v430). The island simply was not in the cartography, so the swell model gave it no lee at all on either coast. Traced from your Navionics screenshots and anchored on your Playa El Peligro waypoint — 2.30 nm by 1.92 nm. With a 220° swell its west side and El Boquerón now read fully exposed at 1.70 m while its east side and Caleta El Viejo read sheltered at 0.54 m. Worth checking the outline back against Navionics when you have it open.
THE CAMERA HOLDS THE SHOT (v433). The replay was re-aiming the camera on every single frame. Its target came from the distance to the mark, and that distance falls continuously, so the target was never still and the easing never reached the stop condition — the camera chased a mark it could never catch. Measured on the owner's own iPhone: 6,210 camera moves in 30 seconds — 207 a second — with 147 of 150 samples showing the view in motion, the zoom creeping 0.013 every fifth of a second, and the boat wandering 104 px vertically on an 812 px screen. On the phone that reads as the scene sliding up and down without rest.
A camera operator does not do that. They frame, they hold, and they move only for a reason. There are now three reasons and no others: the leg or the waypoint being sailed to changes, the boat leaves a generous dead zone inside the safe area, or the rescue net fires. Between those, the view is motionless. The scale is frozen when the shot opens — if the waypoint fits, the whole run to it is framed and held to the end; if it does not, the shot uses the cap and the dead zone advances the camera in long deliberate steps. Quantising the old sliding zoom was tried first and was not enough: it turned one continuous slide into nine stepped shots on a single leg, so the coupling to distance was removed outright.
And it aims where the instrument points. The camera now composes for the next waypoint — the coming tack, gybe or mark — the same point DTW and ETA WPT measure to. It used to frame the far end of the leg, so on a long beat it composed for something 20 nm away while the boat sailed to a tack three miles off.
Measured after: 6,210 camera moves became 214 — a 97% cut. 90% of samples are perfectly still, there are two shots where there were nine, and the whole 36-second observation contains a single 0.8-second move. The boat was on screen in 180 of 180 samples, and across five routes scrubbed end to end it never once left the safe area.
THE BUTTONS WORK ON THE PHONE NOW (v434). The transport row ended 11 px from the bottom of the window, and the buttons are 40 px tall — so their lower half sat inside the strip iOS reserves for the home-indicator gesture, and the system ate the taps. On a desktop they worked, because that strip does not exist there. env(safe-area-inset-bottom) did not save it either: Safari reports zero for that while its own bottom toolbar is showing. The row now keeps a floor of its own and clears the bottom by 33 px.
And the replay always opens at 1×. The playback speed was being remembered in local storage, so a replay could open at 1.5× or 2× because the button had been tapped at some point weeks earlier. It starts at 1× every time; changing it during a session still works exactly as before.
WHAT ISLA GRANDE TAUGHT (v637). The P5 post-mortem (12-sep) found five things the planner did not show. The plan said port off the island; on board the crew saw the wind had not shifted yet, sailed the long board inshore and tacked on the shift — about 43 minutes better than the plan's side.
Tack with the wind, not with the plan's clock. Every beat and run shows its trigger: toward the mark the long board is starboard while the wind is more than 5° right of the rhumb and port when it is more than 5° left, given as TWD and as a magnetic heading, with the forecast time it flips. A warning appears when the chosen first tack goes against a forecast shift of 10° or more.
Shift timing. When the forecast direction moves 10° or more on a beat, both first tacks are simulated with the shift 30 and 60 minutes early and late; the laylines row gives the loss, and a warning appears if the chosen side loses more than 10 minutes when the shift is late.
Masthead wind. Models, stations and the ORC polar are 10 m winds; the Tirreno's vane is at about 17.3 m. The cards add “tope” = 10 m × 1.07 (shear exponent 0.13 from ICON's 10/80 m profile in the P5 beat). Display only: engines and targets stay at 10 m. Divide the masthead TWS by 1.07 before reading a target.
Waves along the whole leg. Each leg's sea state is seven samples along the rhumb at the hour the boat is there, each with its own land shelter, instead of the destination mark's sheltered value at departure. Hs is the root-mean-square because the drag goes with Hs². The route clock is re-run once if any leg changes by more than 0.1 m.
One clock, including the optimizer. Legs the ⚡ optimizer adopts now write their duration into the TARGET clock; the route re-chains and the cards, the leg table and the printed plan read the same numbers. An audit line under the leg table says so in grey, or lists what disagrees in red. On 12-sep the published ETA carried 28 minutes the board table did not.
THE OVERNIGHT AUDIT (v435–v441). Seven batches, every one measured before and after, from a 15-agent audit that confirmed 20 findings and refuted none.
One clock (v436). The drawn track and the displayed leg time came from different engines: the map drew rtSimBeatLeg's boards while the clock ran a land-blind rhumb march — legs read 21–26 kt on a First 42. Legs with drawn boards now adopt the record run's own physical time, re-chained down the route. Measured across all 22 routes: 143 legs, every implied speed inside 3–12 kt (four impossible ones before). The honest clock is slower where the old one was fantasy: the 115 nm beat to Paracas went from 18 h at an impossible 8.2 kt average to 29 h at a real 5.8 — treat older saved ETAs on beat legs as optimistic.
Waves charge every engine (v437–v438). The official ETAs ignored waves while the optimizer paid them. Now the deterministic clock, Monte Carlo and the board simulator all pay the same rtWaveFx drag, and each leg stores its wave cost in minutes. The 〜 SEA panel is quantitative: Hs to one decimal with a FLAT / MOD / ROUGH class, face, loss to one decimal, minutes lost per leg, and a route header — measured on Paracas → San Gallán: "waves cost ~5 min · roughest leg 7 at 2.2 m", ROUGH 2.0–2.2 m on the exposed west face, FLAT 0.4 m in the island's lee.
The camera keeps your mile (v439). The shot now guarantees the boat, at least 1 nm of water ahead toward the next waypoint, and the waypoint itself whenever it is within the frame's reach — with a 10% anticipation margin so the re-frame lands before anything is lost. And a sign bug from v385 fell out of the measurement: with the chartplotter bar on top, the whole composition sat ~135 px too high and the waypoint was buried under the bar in 100% of samples; two characters fixed it, and the film now measures 0% boat-out, 0% mile-lost, with only 1–2 s transients at leg cuts.
Wind that agrees with itself (v440). The animated field now carries the same island shelter the instruments use (worst same-time disagreement measured 5.8 kt → 1.8 kt), the wash and its badge follow the focused leg's hour, and stacked arrow labels near close marks declutter to one. The per-leg arrows still show the wind at each arrival time — that is their job — while the wash shows the field hour named on the badge.
Small honest things (v435, v441). The stale-forecast banner only appears when the saved forecast is 4 hours old or more — a shape bug made it cry wolf at "(0 min ago)". The replay always opens at 1×. The chartplotter's TGT cell now quotes 100% of the ORC polar — the same benchmark as the leg table — instead of a race-mode-inflated number, the leg name wraps to two lines instead of truncating, and the panel is ~18 px shorter on the phone.
ISLA GRANDE IS NOW THE ISLAND YOU SURVEYED (v443). The owner lifted two points off his own Navionics — the north tip at 11°45.990′S 77°15.720′W and the east cape at 11°46.474′S 77°15.360′W — and the chart's island was 0.27 nm short of one and 0.12 nm short of the other. A cap anchored exactly on those two points now closes the gap, covering the north spit, the east cape, the NE islets and the shallow channel between them (under 1 m with breakers on the owner's sonar — not water for a 2.3 m draft). Two consequences fell straight out: ⛳ E Isla Grande sat 7 metres from the surveyed east cape — the gate was on the shoreline, masked for years by the 0.12 nm not-land bubble every gate carries; it moved 0.15 nm offshore. And the route now does what the race really does: rounds the north tip, via a new ⛳ N Isla Grande — P1 reads mark → ⛳ N → ⛳ NE → YCP, six legs, all clear, 82.82 nm.
The pruner can no longer un-verify a chain. Finding that rounding exposed a router bug of a familiar family: the chain search legally chose ⛳ N → ⛳ NE, then the "gate too close to the mark" pruning stripped ⛳ N (0.19 nm away) and left a mutilated chain whose new first hop — straight across the north spit — nobody had ever checked. Pruning now re-validates: a gate is only removed if the hop that remains is still legal.
THE CHARTPLOTTER SPEAKS IN COLUMNS (v444). Per the owner's sketch: the four sail-driven numbers — SOG, TGT, TWA, AWA — now carry the sail's colour as their cell background (red A2, white A3, grey J2), so one glance says which wardrobe those numbers belong to. The bottom row regrouped by meaning: DRIFT sits under the headings, DTW / ETA WPT in the centre, TWS / AWS under the wind angles.
THE TRANSPORT ROW BEHAVES LIKE A REMOTE (v447). Hold ⏪ or ⏩ and it keeps scanning (~6 steps a second after a a third of a second); a single tap still gives one step, and the ghost click that follows a hold is swallowed. Taps on iPhone no longer fight the browser: touch-action: manipulation kills the double-tap-zoom hijack that ate rapid presses. And the row went quiet, per the owner's markup: the transport glyphs render as monochrome text (no more blue emoji arrows on iOS), the camera sits in greyscale until it is actually recording, the speed chip highlights in grey, and the LEG pill and clock are always white/grey instead of borrowing the sail colour — on an A2 leg half the header used to glow red. The only thing left that shouts is the SEA button, and that one is supposed to.
THE CAMERA PUSHES IN FOR THE ROUNDING (v448). The held-shot camera had a fixed 1.72 nm scale floor — it guaranteed the mile of water ahead, but it filmed every rounding from the same wide seat: the arrival at Ballestas N with 1.1 nm to run was still framed for the whole 7.4 nm leg, and a 0.33 nm rounding lived in a fifth of the screen under a stack of labels. The owner called it: "zoom in estable... la escala adecuada acercándose a cada tack, gybe, waypoint."
Stepped approach zoom. Crossing 1.5 / 0.8 / 0.4 / 0.2 nm to the next waypoint — tack, gybe or mark — cuts one shot closer, down to a 0.5 nm close-up at the rounding itself. Deliberate cuts, perfectly still between them: the stability rules of v433 untouched. The water-ahead guarantee scales with the approach — the full mile when far, never less than 300 m (the owner's number) when close. And the waypoint enters the frame at 2.5 nm and never leaves; beyond that the shot frames the lane and the mile rather than inflating to a 10 nm postage stamp trying to include a mark it cannot usefully show.
v449 — one step closer still, at the owner's eye. Watching P6 he asked for more: finer thresholds (2.5 and 0.1 nm joined the ladder) and, decisively, the boat drops to the lower third of the frame on approach (lead 0.30) — the dead water that sat behind the stern becomes route ahead. Every approach shot tightened ~40–50%; close-ups now reach 0.30 nm, and the Ballestas and San Gallán entries read like a helmsman's-eye framing: boat large, ruler ticking to the named mark, islets legible.
Re-audited scene by scene across the three Paracas regattas: P4, P5, P6 — 30 legs, 420 scenes, 100% compliance on all four criteria (boat visible, ≥300 m ahead, scaled water-ahead guarantee, waypoint in frame inside 2.5 nm), with close-up scales of 0.5 nm actually reached on every rounding. The Ballestas arrival and the 0.33 nm rounding now read like a director framed them — because one did.
THE BALLESTAS REGATTA ROUNDED OPEN WATER (v450). The owner spotted it watching P5: the route's "Ballestas" and "Tres Marías" marks sat in empty sea, well west of the actual islands. Measured, the cause was exact: both marks were the dashboard's wind-forecast spots, coordinate for coordinate — points deliberately placed in open-sea model cells for clean wind sampling, recycled as rounding marks. Ballestas was 0.88 nm west of its islets, Tres Marías 0.73 nm. Both are now real rounding berths — 0.2 nm off the group's NW corner and 0.26 nm off Tres Marías' west shore — with the north–south corridor between them clear of the islets. Re-planned and verified: 9 legs, every one clear of land (tightest 0.111 nm), the marks now sit ON their islands in the chart, and the close-up camera frames the roundings at 0.31–0.46 nm scale. Both positions were confirmed by the owner against Navionics on 31 Jul; Isla Blanca's berth (0.25 nm off its west shore) was already sound and is untouched.
THE CAMERA DOCTRINE (v451, owner-approved). After reviewing P6 scene by scene, the owner ratified the replay camera's rules as this app's standing doctrine: held shots that only cut for a reason · the boat and its route ahead always visible · at least 300 m of water toward the next tack, gybe or waypoint · the waypoint in frame from 2.5 nm in · stepped approach zoom at 1.5/0.8/0.4/0.2/0.1 nm down to a 0.30 nm close-up with the boat in the lower third of the frame. All five P routes are certified against it scene by scene; the remaining library inherits the same code and will be certified next.
THE ROUTE IS ON THE HEADER — AND IT IS A SWITCH (v452). The replay header now opens with a route pill (e.g. P6 ▾): it always names the route you are sailing, and tapping it opens the native picker with every P race. Pick another and the app replans it (“optimising the route…”) and reopens the replay on the new route without leaving the chartplotter — the same canonical path as the route bar, so the plan, the library and the saved state stay in sync. While the iOS wheel is open the panel refresh is frozen so the picker is never destroyed under your finger.
THE START IS ONE SHOT (v453). Race beginnings used to be the roughest scenes: on P5's start the camera cut four times in sixteen minutes, riding the whole approach ladder against the first course change 1.1 nm out (1.78 → 1.29 → 0.64 nm) and then zooming out 5.8× the moment it was rounded. Now the start is filmed the way a director films a start: one held establishing shot, anchored on the start line, first mark near the top of frame, and the boat CROSSES the frame — no re-bucketing, no chase — until the first waypoint of the race is rounded, then the standing doctrine takes over. Applies whenever the first waypoint lies within 2.5 nm of the start; distant first marks were never rough. v455 widened it to the whole opening leg: measured on R1, the shot after the start still rode the full approach ladder against a second close tack (4 cuts in 16 min) — now every close waypoint of leg 1 gets one held shot of its own, anchored where it opened, and R1's opening is 2 cuts.
A DAY OF WIND SHOULD NOT COST A DAY OF QUOTA (v456). Every route view fetches winds for its own points, and two library sweeps burned the whole daily budget before breakfast (measured: 149,960 of 150,000 units, 7,280 requests denied). The proxy now serves any repeated forecast query from cache for a full hour — the models only publish about hourly, so within that hour a re-plan, a re-view or a phone refresh costs zero quota. The chart also lost two pieces of furniture at the owner's request: the 💨 wind toggle and the “wind hh pm” badge (the field stays on; its hour is the panel clock). The ROUTE/DAY/TIME selector is a third smaller.
SEA SITS NEXT TO DRIFT NOW (v456). The wave parameter moved from the replay header into the instrument grid: the cell reads DRIFT · SEA — the current's arrow, then the 〜 pill with its favorability colour and signed net. The drift numbers are gone (the arrow says the direction; the panel behind the tap still has every figure), and the header gained back the room the leg name needed.
TRACKS THAT SURVIVE A LOCKED iPHONE (v456). The ● button is now labelled ● TRACKS and the recorded track draws in cyan — nothing else on the chart uses it. The real fix is underneath: iOS suspends Safari when the screen locks and the GPS watch died silently, which is why recording “often did not work”. Recording now takes a screen wake lock, a watchdog restarts the GPS watch if no fix arrives for 45 s, and both are re-acquired the moment the app returns to the foreground. And the replay recorder (🎥) got its two iPhone complaints fixed: the exported clip now includes the instrument panel and the timeline (rasterized text-by-text into the frame — they are HTML, invisible to the canvas), and the fixed 68-second stop that truncated long routes is replaced by the replay's real compressed duration.
THE 6 AM PLAN IS SACRED, AND THE SEA HAS NO WI-FI (v457). Two standing rules by owner's decree. One: from the daily quota reset (7 pm Lima) until 9 am, bulk work — sweeps, batch replans — leaves 40,000 units untouched on top of the interactive reserve, so no overnight job can ever again spend the morning the race is planned (it happened twice: 149,960 of 150,000 gone with 7,280 requests denied before breakfast). Two: a service worker now caches the console, the chart library, every map tile you have seen and the API responses — at sea, with no internet, the app opens and works with the last downloaded forecast, and the FORECAST NOT REFRESHED banner honestly dates it. Nothing external to set up: your own Mac serves it. Open the app once with internet (the Tailscale address), and offline mode is simply there.
P1 IS THE OFFICIAL COURSE NOW (v463). The owner delivered the official race chart of Prueba 1 · 2° Copa Federación Peruana de Vela (Campeonato Nacional Oceánico 2026, Aug 6, 83 MN) and P1 was rebuilt on its buoys, name by name and coordinate by coordinate: start off Camotal → BR (racon buoy) → BV1 · BV2 · BV3, the three virtual buoys rounding Hormigas de Afuera → Isla Grande (the certified north rounding) → BP1 · BP2, the danger buoys → finish at YCP. The straight-line course measures 82.8 nm against the official 83. The Zona de Peligro between BP1/BP2 and the Oquendo shore is a hard exclusion: the router treats it as land, it draws red on the chart like the official map, and the BP1→BP2 buoy line itself stays legal water (the seaward edge sits 0.1 nm inshore of it). Hormigas de Afuera islet is not in the cartography — the virtual buoys themselves enforce the clearance, which is exactly what they exist for.
A HIDDEN TAB SPENDS NO QUOTA (v464). The overnight burn had a second author: a desktop tab left open in the background kept running the 10-minute refresh all night — measured, 149,963 of 150,000 units in 380 calls by 8 am. The refresh cycle now skips itself entirely while the tab is hidden; the moment the tab returns to the foreground the existing visibility listener refreshes everything. Between this, the one-hour forecast cache and the 6 am bulk hold, the morning plan finally has three locks on its budget.
THE RACE CHART IS THE DOGMA (v465). The owner's ruling on P1: the official attachment commands, everything else is a complement. So the course is now exactly the official one — P (Partida, yellow buoy at Camotal W) → BR → BV1 → BV2 → BV3 → Isla Grande → LL (Llegada, yellow buoy at YCP) — with the official nomenclature on every chart label and timeline chip. BP1 and BP2 left the course: they are not waypoints, they only mark the corners of the Zona de Peligro, so they now draw as permanent red danger buoys on the zone itself and the exclusion polygon does the routing work. Buoys render in their official colours: P/LL yellow, BR and the virtual buoys red. Isla Hormigas de Afuera is on the chart now, traced from the owner's Navionics captures (light at 11°57.484′S 77°43.956′W) — the BV rounding finally reads against the island it rounds. And the Isla Grande rounding gates moved in from 0.15 to 0.13 nm — the closest the 0.12 nm safety bubble allows; the sketched inner pass between Isla Grande and Gallinazos (~100 m wide) sits below the model's standoff and stays refused.
THE ROUTE EMBRACES ISLA GRANDE — AND THE CAMERA STAYS FOR THE ROUNDING (v466). Three owner rulings in one build. One: the Isla Grande rounding is now a PERIMETER — four course waypoints (IG W · IG N · IG NE · IG E) at 0.13 nm off the traced shore, so the route surrounds the island exactly as the red sketch orders, and every corner is a measurable timeline mark. Two: the camera doctrine gained its missing clause — the exit of a rounding is a scene too. The close-up used to jump wide the instant a mark was passed (the next waypoint being 16 nm away) with the island still alongside; now the rounding shot holds until the boat is 0.45 nm clear, then cuts. Three: while paused, the chart belongs to you — pinch, zoom and pan freely with no camera fighting back; press play or move the slider and the camera takes over again. Also new: the Navionics shallow/foul Zona de Peligro wrapping Hormigas de Afuera is drawn and blocked — the official virtual buoys skirt its west face, which is exactly why they exist.
THE OWNER AUDITED THE REPLAY, AND THE DOCTRINE GREW UP (v468). Watching P1 end to end exposed three rule breaches, all measured in a 739-minute frame-by-frame audit: the full approach ladder ran against BR right at the start (8 cuts in 30 minutes), the rounding-exit hold swallowed the approved close-ups at BV2/BV3 (the Hormigas rounding played as a train of RX shots), and the exit hold fired at every tack of the final beat — 35 cuts in 139 minutes. Three rules fix it: the opening sequence covers the whole first leg up to 3.5 nm; every tack acquired within 1.5 nm anywhere in the race films as one held shot (the start-sequence idea, generalized); and RX fires only after rounding a MARK, and only when the next objective is over 0.8 nm away — close buoy trains keep their ladders. Re-audited: 59 cuts in 739 minutes, a close-up at every buoy of the Hormigas rounding, and the single remaining flag is the frame in which the boat crosses the finish line itself.
THE RECORDED MP4 IS THE WHOLE RACE, AND IT OPENS CALMLY (v475–v476). The owner's audit of the exported clip found it cut short and its opening harsh — measured causes: the capture ran at 1× while its own firewall assumed capture speed (it stopped at ~38%), and the recording began mid camera-flight. Now the capture plays at capture speed (the whole race in ~100 s), opens with a held 1.8-second start frame after a camera snap (no flying), the 10-minute refresh never replans mid-recording, and the recording ends only at the finish line — verified: 13.2 MB video/mp4, playback reaching 100% of the race, WhatsApp-friendly size and codec. Sharing got its physics fixed too: the share sheet demands a real click's activation, so the ▸ button now shares on click (recording start/stop stays on the drift-proof press) — and on a desktop browser, where no share sheet exists, the ready notice says so and carries open and discard links beside the Downloads copy. And the owner's blue line became a standing racing rule: leaving Isla Grande southbound the exit hugs the island — rule gates injected into the real chain and shielded from the distance pruner; the sailed exit now passes 0.12 nm off the corner (it used to swing 0.4 nm wide).
P5 ROUNDS ISLA BLANCA ON THE OUTSIDE (v453). The owner's instruction: the route must go OUTSIDE Isla Blanca — the optimizer was legally sneaking INSIDE, south of the island (min 0.24 nm), because open water is open water. The course now encodes the seamanship: two rounding gates derived from the owner's own island tracing — IB NE (13°43.98′S 76°18.24′W) and IB N (13°43.78′S 76°18.81′W) — take the fleet E of the island, round its N tip, and close on the owner's W mark: a full outside rounding, island always to port, every gate a measurable waypoint on the timeline. All three segments verified clear of land against the router's own coastline. Pending the owner's Navionics check of the two gate positions.
THE TRANSPORT ROW FINALLY WORKS ON THE PHONE (v454). v447's buttons still relied on iOS's synthetic click — and if the finger drifts a few pixels, Safari reclassifies the tap as a scroll gesture, fires pointercancel, and that click never arrives. That is why ⏪ ⏩ and the speed chip kept dying on the owner's iPhone while working on a desktop. Every control in the row now acts on pointerup with pointer capture and touch-action:none — no dependence on the synthetic click at all (whatever click Safari still synthesizes is swallowed). Hold-to-repeat on ⏪ ⏩ stays. The ⏭ skip button is retired at the owner's request. Also new: tap the chart to pause, tap again to resume — one clean finger, not a drag, never over controls — and a time bubble riding the yellow scrub knob (race elapsed · video seconds), because the old time read-out was hidden on phone widths.
The replay gives every leg time to be seen. It used to run at a uniform rate through the sailing hours, so screen time simply followed how long a leg takes. On YCP → Camotal → Paracas that meant the three near-shore legs — where every tactical decision lives — shared under nine seconds between them while the single 115 nm ocean crossing ate 171 of the 180. A 213-to-1 ratio, and the part worth watching went past in a blink. Each leg is now guaranteed a share of the video and the rest is handed out by sailing time: the roundings get about 25 seconds each, the long passage still reads as the long passage, and the scrub bar is video time so you can actually put a finger on a rounding.
The panel below the wind scale is gone. Everything it carried — the leg and the clock, the water (SET · DRIFT, with the leeway angle and the sea state, the reasons the boat is not simply doing its polar), SAILED, FINISH, and the ladder of remaining marks with their distances and ETAs — now sits in the box on the chart. What is left at the bottom is the scrub bar and the transport buttons, because those are things you press rather than read: 253 px of panel became 91 px of controls, and the replay is that much taller. Current comes from Open-Meteo Marine — the Humboldt runs about a knot off Callao; leeway is a model, not a measurement, and the box says so.
The boat is never allowed off the screen. A single safe rectangle — clear of the wind scale, the panel, the label strip and the map edges by the width of the boat's own halo — is checked on every frame. The camera cuts once per leg, framed so the whole leg fits inside that rectangle, which means the boat cannot wander out of it while sailing; if anything ever puts it out anyway, the camera recovers on that same frame. Measured on the P1 race course: one cut per leg, no drift within a leg, and zero frames out of 1138 with the boat outside the safe area.
The instrument box sits in open water, not on the route. Hanging it off the boat meant it covered the track, the range ticks and the laylines — the things the replay exists to show. Once per leg the chart is now searched for a spot that clears every line drawn on it, the waypoint labels and the furniture, and the box is pinned there for the whole leg. The camera does not move within a leg, so neither does the box; and because every candidate spot clears the entire leg track, the boat can never sail into it.
When there are two ways round, both are sailed. If the topology search finds a genuine second option — a different side of an island, close enough in time to be a real call — it is drawn in green and sails its own timeline beside the magenta one, so you can watch where the two part company and by how much. The camera frames both boats, not just the plan's. Verified with the boats up to 488 px apart and on different legs at the same moment: both stayed on screen for every frame of the replay.
Two lines you steer by. The replay draws your heading as a yellow dashed line running out exactly as far as you still have to sail on the leg — if it does not point at the mark, the gap is the current and the leeway, drawn to scale. And the two laylines into the mark appear at your own angle from the ORC certificate: green for starboard, red for port, the same convention as the nav lights.
Laylines upwind AND downwind (v350). They used to be drawn on a beat only. But you cannot sail dead downwind any more than you can sail dead upwind, so a run now gets its pair of gybe laylines at the certificate gybe angle (140° at 4 kt out to 164° at 20 kt), drawn in longer dashes to tell them apart from the tacking pair. On a reach neither pair appears, because there is nothing to lay. The same version also swaps the two colours back the right way round: with the wind from TWD the heading TWD−angle puts the breeze on the starboard bow, so that is the starboard layline and it must be the green one — it had been drawing that line red since laylines were introduced.
The wind colours are scaled to this coast. The field used to run to 50 kt — an offshore-gale scale — which squeezed an entire Peruvian season into the first third of the ramp, so 5 kt and 11 kt were two shades of the same blue. But the hard question here is almost never where is it blowing forty; it is where is there any wind at all. The range now tops out at 35 kt, more than this area realistically sees, and the same full spectrum is redistributed so that half of it is spent below 16 kt: nine colour stops under 16 kt instead of four, and every single knot in the racing band is a visibly different colour. A 6 kt hole and a 9 kt lane no longer look alike. Thirty-five tops out vivid magenta — deliberately far from the indigo of dead calm, so the two extremes can never be confused at a glance in sunlight.
The heading line is a ruler. It runs from the boat along the course you are steering, exactly as far as you still have to sail, and it is ticked so you can read distance straight off the chart: 0.2 nm marks inside a mile, half-mile marks inside four, one-mile marks out to twelve, coarsening from there. The distance to the next mark sits beside the boat as well as in the panel, because that is where your eye already is — offset in pixels rather than in miles, so it never lands on the hull however far you zoom.
It plans for itself. Opening the replay or exporting a GPX no longer asks you to go and plan the route first — if the plan is missing, or belongs to a route you have since changed, it optimises the selected one and then carries on. The only thing it still refuses outright is a route naming a mark that has left the chart, because no amount of planning fixes that.
It counts down to a waypoint, not to a gate. The router inserts gates to get round land — they are routing machinery, not places you are steering for. So the distance and ETA now aim at the next numbered waypoint, summing the legs through any gates on the way and naming them: TO WPT 2 · 25 nm · Las Hormigas · via ⛳ N San Lorenzo. And the replay's camera reserves the wind colour scale as well as the panel, so a mark near the bottom of a leg is never drawn underneath the bar.
The colours are keyed to TIRRENO's own thresholds. Not a generic scale — yours. 0–5 kt stays indigo and blue, because there is no race in it and it should read as nothing. 6–12 kt gets the most resolution, cyan through green, because that is the band every race here is decided in and a knot of difference is worth finding. 15 kt turns amber — the day has got serious. 20 kt is red — reef. Thirty-five tops out magenta. The colour changes where your decisions change, so the map tells you what to do rather than only what the number is.
No bald patches. The wind wash is fetched for a box around the route; pan or zoom outside it and the field used to simply stop being drawn, leaving a pale hole until the next fetch landed. The nearest edge value is now carried a short way beyond the box so the field stays continuous while it catches up — and beyond that it still stops, rather than inventing an ocean of wind nobody fetched.
One ramp, every screen. A wind number is now drawn in exactly its colour on the scale bar — on the dashboard tiles, in the replay, on the chart axes. It never used to be: every value was mixed with a third of white for legibility, so 11 kt was displayed in a pale green while the bar underneath it said something else entirely, which rather defeats the point of colouring them. The dashboard tiles were worse — they came from a separate hardcoded Beaufort palette that had only three colours across the whole 4–12 kt range. Both now read from the same ramp, and they are coloured by the number that is actually printed, so a value and the bar can never disagree. The single concession is the flat-calm end: indigo is close to invisible on a black panel, so 0–1 kt is lifted just far enough to be seen.
Every caption is legible, on every route. A frame-by-frame audit of a real screen recording — twenty frames, four independent reviewers, 237 findings — showed that the replay was quietly destroying information in every single frame: each tile's sub-line was cut off mid-word by an ellipsis, the playback clock was squeezed to a leading digit, and the scale bar printed its top value and its unit on the same pixels. On the chart, three separate label systems — hazard captions, waypoint names, waypoint numbers — were printing on top of one another, and the heading ruler's tick numbers were drawn in amber on a yellow wash at 1.5:1 contrast, sometimes past the bottom of the map and across the leg title.
All of it is fixed at the cause rather than nudged: sub-lines wrap to two lines instead of truncating, the strips that carry text are opaque instead of sitting on the moving wind wash, tick numbers get their own dark plates and are suppressed if they would leave the chart, the competing label layers stand down while the replay runs (the hazard outlines stay), and the distance flag flips above the boat when it would cover a mark's name. And the camera cuts between legs instead of panning — the one-second pan was why the boat had to be hidden at all, which left frames showing no boat, no mark and no name while the panel still quoted a distance to something you could not see. A cut has neither problem, and it is what a film would do.
Everything is verified. Every number can show its out-of-sample grade — tap any tile for its Forecast Evaluation pages, or open ROUTE PLAN · Route Model. Nothing is hand-tuned: the app re-learns from its own archive every night.
Data: Open-Meteo (ICON & ECMWF) · METAR SPJC · DHN Chucuito · WeatherLink (YCP · CRL · Paracas NW · Paracas SE) · OpenStreetMap/OpenSeaMap · the owner's Navionics charts and ORC certificate.
Built for Enrique Valdivia · La Punta, Callao. Full detail — every formula, every worked example — lives in the User Operating Manual above.