The Vector roster is filed a whole month at a time, against the picture it was read from.
-
Added
- Fixed: FDP Tour could show nought hours beside a pay figure, with nothing on the statement to match it. The count and the amount were written separately and fell out of step: the count fell back to the raw hours only where there was no FDPP dial at all, while the amount fell back whenever the dial could not price itself — which is every fortnight in which no tour finished, since a dial built from no tours has no rate and returns nothing rather than nought. The line then priced itself off hours flown, which is not the quantity the column is even in: the column is what is left after ten hours have come off each tour. A fortnight with 5.5 hours flown and no completed tour read "0.00" beside $1,122.00. Both FDP lines now price the same figure they count, so the multiplication on the row can be checked by eye. FDP Night was written the same way and is fixed with it.
- Fixed: the credentials screen asked "Allow Paste?" every two seconds. It watches the clipboard while it is open, so a set of credentials sent from another device is offered as it lands — and from iOS 16 every read of the clipboard's contents puts that alert up, with the answer not remembered from one read to the next. It now asks the system how many times the clipboard has changed, which is free and raises nothing, and reads the contents only when that has moved. One alert per new clipboard item instead of one per tick. A clipboard holding a picture rather than text is not read at all. Leaving the screen now also stops a read that was already on its way.
- Fixed: the money scale down the side of the duty period graph ignored the privacy setting. It is painted onto the chart's canvas rather than drawn as a widget, so nothing wrapped around the chart could reach it — and a scale still reading $0 / $150 / $300 beside a column of covered figures gives away the size of every bar under it. It is now written through the same setting as everything else, and the chart repaints when the setting changes rather than leaving the old scale on screen.
- The tutorials travel with the settings. Having been through the reconciliation notices and the "how to capture image" page once is a thing a person did, not a thing a device knows, so a second device set up from the first no longer sits you through them again. A device that has not been through them sends nothing on the subject, which leaves the other one as it was rather than telling it somebody has read something they have not. The list is the same one the Reset row works from, so a page added there travels without anybody having to remember it — a page that could be put back but not carried would be the same tutorial twice, and nobody would notice until they hit it.
- Fixed: imported settings did not appear until you opened the Profile page and closed it again. The dates and the pay selections belong to the Pay tab, which reads them once when it is built and then keeps them — and that tab lives in a stack where it stays mounted, so nothing about an import made it look again. Opening the Profile page and leaving it was the one thing that used to say they had moved. The import now says so directly, and the seat and schedule are re-read alongside the dates rather than only the dates.
- Fixed: the native macOS build wore the template's icon rather than the app's. It had never been generated — the icon settings named iOS and nothing else. This does not affect an iPhone app running on an Apple Silicon Mac, which is the iOS bundle and has had the right icon all along.
- Fixed: the bottom bar overflowed once the text was turned up. Sixty pixels was an icon over a twelve-point label at the size the app was drawn at, with a couple to spare; at 120 per cent the label grew and sixty did not, and one pixel of overflow draws a black-and-yellow stripe across the bottom of every screen in the app. The bar is now as tall as its writing. The height is measured rather than left to the layout, because a horizontal scroll view fills whatever height it is given and the Scaffold offers its bottom slot the whole screen — letting the content decide gave a navigation bar the height of the window. At the ordinary text size it is still sixty, so nothing moves for anybody who has not touched the setting.
- The text size belongs to the screen rather than to the person. A size that fixes a Mac is far too big on the phone it was copied from, and an 11-inch iPad wants neither — so a device now keeps a size per screen it has been run on, and picks the one for the screen it actually has. Screens are told apart by the display's pixel size and its density, with the two dimensions sorted so turning a phone on its side is the same screen; it is the display rather than the window, because an iPhone app on a Mac is resizable and keying on the window would mint a new screen on every drag of a corner. Sizes for other screens are still carried when settings are copied across, but only the one matching the receiving screen is used — and what that device had already set is kept rather than overwritten, so copying back the other way finds both again. A size put back to normal is stored as nothing at all, which is what a screen nobody has an opinion about is. Anybody who had already set a size keeps it: it is adopted for whichever screen the app next opens on.
- Copy credentials now copies the settings with them. Setting up a second device meant reading a long password and a base32 secret off one screen and typing them into another, and then doing the same again for a hire date, a date of birth, a seat, a schedule and everything else — none of which the app can fetch from anywhere, and the second typing is the one that gets a date wrong. Four groups travel: Profile, Pay tables, Display and Privacy. The receiving device lists the groups by name before taking anything, since the settings are written without being asked about individually and that list is the whole of the consent. What travels is what somebody set, not what the app learned: nothing you have imported is sent — the records and their pictures stay on the device that took them — and neither are the acknowledgements of the reconciliation notices, which are a person agreeing to something on a particular device. A setting never answered is not sent at all, rather than sent as a default that would overwrite a real answer on the other device. The settings ride inside the same encrypted blob, so nothing about them is readable off the clipboard, and the envelope is unchanged — a payload from a version that sent no settings still opens, and one sent from here still opens on a version that has never heard of them.
- A Display row in the settings menu, for the size of the writing. The app is laid out for a phone held at arm's length; fetched from the App Store onto an Apple Silicon Mac it runs in a window on a desk two feet further away, and everything on it reads small — which is not a fault in any one screen, it is the same app at the wrong distance. A slider from 80 to 150 per cent, set against a sample of a pay table row drawn at the size being chosen rather than the size in force, so it can be judged before the app commits to it. It is applied on top of the text size set in iOS or macOS rather than instead of it, so anybody who has already turned text up keeps what they asked the system for. The slider stops at a half again because past that the reconcile table runs out of room for its columns.
- Fixed: the app now knows when it is an iPhone app running on a Mac. It is still an iOS app and says so — Dart sees iOS, not macOS, and the only difference is the machine underneath — so the system is asked directly. Two things were wrong without it. Authentication asked for biometrics only, on a machine that in most cases has no Touch ID, which is a locked door with no key; it now lets the system fall back to the account password there, while a phone still insists on Face ID or Touch ID. And an iPhone app on a Mac is not a physical iOS device by any test available to it, which sent it down the short-circuit meant for the simulator and opened the credentials screen on a laptop with no challenge at all.
- A Reset row in the settings menu, under Privacy. Some pages are shown once and then stay out of the way, which is right almost always and wrong exactly when you want one back — showing the app to another pilot, checking what you agreed to, or filming it as it looks to somebody new. Until now there was no way back to any of them short of deleting the app and everything it holds. Two to start with: the three reconciliation notices, and the "how to capture image" page. Each row says what the page is and where it currently stands, and the button is greyed out where there is nothing to put back. Resetting asks first, because "reset" means losing your work everywhere else in software and it does not here: nothing you have imported is touched, and the app simply goes back to asking. There is a Reset all for the lot of them. Deleting records is the other thing entirely, and lives behind Import under Manage imports.
- Manage imports. Import has a fourth row, ruled off from the three places a document comes from, which opens a summary of everything the app is holding: how many ADP statements, how many OFF messages, how many Vector roster months. Underneath it, a year at a time, with the count beside each year in a blue pill. Tick a year to take all of it, or open one and take a kind at a time — a statement can be fetched again from ADP and a year of photographed OFF messages generally cannot, so clearing out the one should not cost you the other. A year is the year the record belongs to rather than the year it was imported in; a statement is filed under the year its payday falls in, which is the year printed at the top of it. Deleting takes everything a record brought with it — a month takes its codings and the picture they were read from, and a picture goes only when the last month reading it has gone. Nothing happens until a dialog has listed back exactly what will go, year by year and kind by kind; there is no copy of any of it anywhere else. The "how to capture image" page no longer comes up on the way there, having nothing to say about it, and now appears once a source has been chosen rather than before. Beside every count is what that row is taking up on the phone, and what deleting it would give back — a record is a few hundred bytes of times and stations and the screenshot it was read from is a hundred and thirty kilobytes, so the size and the count answer two different questions and it is usually the size somebody is deciding on. A roster picture that accounts for the tail of one month and the head of the next is counted once, not against both.
- Amounts can be hidden, for filming. Settings has a Privacy row with a sample amount and two sliders. Cover puts blocks over a place and everything above it, keeping the amount's shape. Shorten takes those places off altogether and leaves a left arrow, so the length gives nothing away either. A setting is a place rather than a number of digits, which is what makes it mean the same thing on every amount: hidden from the hundreds up, $999,999.00 reads $←99.00 while $14.10 beside it is left exactly as it is, having nothing in the hundreds to hide. The pennies are never touched. The two work together, shortening first. What the sample shows is what every amount in the app will look like — including the pay tables, which are a package of their own and now hand their figures through the same setting on the way out. A rate is money too, and was the one column written without a currency mark — on the reconcile table and on the statement both — so it went on showing while everything beside it was covered. Hours and units are written the same way and are not money, so they stay legible: a demo of a pay tool with its hours taken out is a demo of nothing. Press and hold a figure on the pay tables and it comes back for a few seconds, then goes again on its own; those tables are on a page that scrolls, so a hold rather than a drag, and how many seconds is a third slider. The sample on the Privacy screen holds open the same way, so the gesture can be tried on the screen that describes it, and the figures on the reconcile table hold open too. There is a switch in the title bar beside the help button — an eye, on when the amounts are hidden — for turning the whole thing on and off between takes without going back to settings and without losing the places you chose. It can be taken off the title bar from the same screen for anybody with no use for it. Flipping it leaves you exactly where you were — the pages are rebuilt rather than replaced, so the tab you were on, the fortnight you had selected and where you had scrolled to all survive it. The sample on the settings screen follows the sliders whether or not the switch is on, since otherwise the places could not be set while it was off. An hourly rate is money as well — "$204/hr" says as much about somebody's pay as the total it produces — so the rates on the flight duty pay breakdown are covered along with the figures they produce. A walkthrough of a pay tool is a walkthrough of somebody's pay, and the figures are the one thing on those screens that cannot be shown to a room. Done where the amounts are written rather than where they are drawn: there are nine ways the app writes an amount and sixty-odd places it does so, and hiding them one drawing at a time would have missed the sixty-first — including the figures painted onto a chart, which nothing wrapped around a widget can reach. The figures themselves are untouched: it changes what is written, not what is worked out, so a fortnight with its amounts hidden still reconciles.
- A help button in the title bar, left of the light switch, and the walkthrough row in the reconciliation tool's help now opens the same place: the help site, which is a catalogue of short videos by topic. Opened outside the app rather than in a webview of its own — full screen, with the phone's own player, is what somebody watching one wants. The walkthrough row lands on the reconciliation videos rather than the top of the catalogue: somebody reaching for help from in there is asking about in there. The site takes a topic in its address, by id or by name, and falls back to all of them for one it does not know. The credentials screen has one beside Save, going to the two-factor videos: a base32 secret and an authenticator app are the two things on that screen anybody is likely to be stuck on.
- Fixed: whether a duty counted as running into the next day depended on where the phone was. A record is filed by the Zulu clock the message prints, and the day boundary was being held against the reader's own instead: west of Greenwich a duty landing at 06:30Z stopped counting as running into the day it landed on, and east of it a duty that never left its day started counting as running into the next. The same record described two different fortnights depending on the time zone the phone was sitting in — which for this app is a matter of what was flown yesterday.
- "How to capture image" comes up when Import is pressed, before anything is chosen. Both readings are geometric — a roster is placed by which column and row a code sits in, an OFF message by which line a figure is on — so a picture that cuts either off produces a confident reading of half a thing. Hearing that once the pictures are already picked is hearing it too late to act on. It is still shown once and not again after the box is ticked.
- A calendar page that is red, or half red, explains itself when tapped. The page on a duty row does three jobs at once — the date, whether the photograph is on file, and whether a duty ran in from the day before — and only the first of those explains itself. A red page beside a day somebody spent at work reads as an accusation, and a half red one reads as a bug. Tapping either now opens a legend: all three bars drawn as they are drawn on the list, each with what it means, and the one this day is wearing marked. A colour is only readable against the others — knowing red means nothing is attached is half the answer, and the other half is knowing what it would look like if something were. Blue is an OFF message with its picture still on file; red is nothing attached, or a record whose picture has gone; half red and half blue is a duty that began the day before still running, on a day no duty period starts on. Where there is a duty to open, it is a button on that dialog. A blue page still opens its picture, since a page with something to see should show it rather than talk about it.
- The Files picker opens where you left it. A fortnight of screenshots lives in one folder, and the picker starting at the top of iCloud Drive every time means finding that folder again on every import. Kept as a bookmark rather than a path, since the folder is outside the app's sandbox and a path would name it without granting the right to look at it.
- A day whose record overlaps another has a yellow calendar page in the Duty Days list. A pilot cannot be on two duty periods at once, so an overlap is two readings of one duty rather than two duties: a message reissued after a change, a duty extended, or the same message imported twice. Importing one at a time asks which to keep, but a batch files what it reads and the question only comes up later — the day's figures are the sum of both until it does, which shows up as a fortnight that will not reconcile and nothing saying why. The page goes yellow and the band is left alone: it is already saying whether the photograph was kept and whether a duty ran in from the day before.
- The figures columns are stepped further apart, each one held a little further off the one before it. Set flush left in fixed columns they read as one run of numbers; the air comes out of each column's own slack, so the band and the widths it is set in have not moved.
- One Import button, with the choice of where from behind it. Photo album for screenshots of OFF messages and Vector rosters, several at once; Files for an ADP statement or an image saved somewhere other than Photos; Camera for a screen or a printed message. Three buttons on that row said three different things could be brought in, when what is true is that one thing can be brought in from three places: what a document turns out to be is worked out from what is in it, so where it came from is the only question worth asking. Files takes the paperclip the statement used to be attached with, and the button itself now carries an upload icon. Files takes as many at a time as you like, of either kind: a fortnight arrives as a folder of screenshots more often than as one, and picking them singly is the same work done six times. Statements in the batch are read first, since each asks about its fortnight and answering that with a pile of half-read pictures behind it is worse than answering it first.
- The settings menu has one Profile row where it had three. Set Hire Date, Set Date of Birth and Set Retirement Date were three ways to the same screen, each with a line under it explaining what it fed, which made the menu read as three settings and the screen behind them as a surprise.
- A help button on the reconciliation page, beside the import controls. Three ways out, and they answer different questions: it opens the message board on the Sidekick Pay Reconciliation Tool thread, where a figure that looks wrong is worth posting and the answers accumulate; it reopens the three notices, which are worth re-reading precisely when a figure is surprising; and it names the video walkthrough, greyed until there is one, so somebody looking for it finds out rather than concluding there is nothing. The board link lands on the thread itself rather than wherever the board was last left.
- The reconciliation page opens with a short CBT the first time you swipe to it. Three notices — the disclaimer, what a figure on the page is and is not, and where imported data goes — read one at a time and ticked off, with the way on closed until all three have been. The tool holds what a fortnight should have paid against what it did, and a figure taken off it without that framing reads as an amount owed, so the way in is through the notices rather than past them. Cancel at either step goes back to the pay tables; nothing is asked of anybody who only wanted those. Once read, it never appears again and the page is a page like any other.
- A day's coding can be set by hand. Tap the day on the Vector page and there is a row for it under the others. The reader is good and not perfect: it misses the odd square, and the ones it misses are the squares with least ink in them — a lone X, the asterisk that marks an extended day. Missing one is not a small error, because a blank square means a day off, so a skipped square takes a duty day out of its tour and its flying out of the fortnight that pays for it. Re-importing cannot help: the recogniser is deterministic, so a square it did not see is one it will not see next time either. What you type is kept as a correction over the reading rather than written into it, so the picture still says what it says and re-importing the month leaves your correction standing.
-
Changed
- A roster is imported a whole month at a time, or not at all. A picture framed as the guide asks shows one month centred and the edge of the two either side, and those edges used to be read too — which meant two pictures could each have something to say about the same month, and a day could be claimed twice. A month is now the unit: half of one is not a smaller record of that month but one that would have to be completed later by a second picture, which is exactly the ambiguity worth not having. A fortnight straddling a month end is covered by importing both months. Months seen only at the edge of the frame are named on the review screen rather than silently dropped, so a fortnight that has not filled in says why.
- Every day of an imported month now has a record, days off included. A day off is a coding — the roster states it by leaving the square blank — and storing it as no row at all made "the roster says this was a day off" indistinguishable from "no roster has been imported". Tours read the difference: a day the roster confirms as off is evidence about where a tour ended, and an absent row was not.
- Nothing is worked out from the geometry of the picture after import. The reading happens once, and everything downstream — tours, duty days, a fortnight's pay — reads fields.
- The picture is stored once, on the document, instead of a copy against every day of the month it covered. A month used to be the same screenshot stored thirty-odd times.
- What the scanner read is kept apart from what you correct. Corrections live against the month rather than on top of the reading, so re-importing a month replaces what was read and leaves your corrections standing — a newer picture is a better photograph of the same calendar, not a reason to lose your own judgement about it. And "what the roster actually says" survives being disagreed with, which is the whole of the chain of custody.
- A month can be marked as checked against its picture by eye, separately from whether anything on it was edited. A month read perfectly and confirmed is not the same as one nobody has looked at, and until now the record could not tell them apart.
- Deleting a roster picture now removes the month it was read from, since the two are one record. There is nowhere for a month's codings to live without the picture they came off — re-import to put it back.
- A correction to an OFF message no longer destroys the reading it corrects. The scanner's figures and yours are stored apart, so the record can show the disagreement rather than only its conclusion — which is the difference between "the message says 7.5" and "the app says 7.5", and in a pay dispute that is the whole difference. Corrections already made are recovered rather than lost: the message text was always kept, so re-reading it gives the reading back, and whatever the record says differently is what you changed.
- Improving the reader now improves old records without touching anything anybody typed. It used to have to guess, field by field, whether a stored figure was a stale reading or a correction — by recognising the shape of the previous reader's mistake. A correction that happened to look like one was overruled. Which figures are somebody's judgement is now written down, so there is nothing left to guess at.
- An ADP statement is read once, when it is filed, and the reading is kept beside it. It used to be parsed afresh every time the page was opened, which was slow — and meant a change to the reader silently changed what a statement from six months ago was taken to have said. A record of what you were paid should not do that.
- A day a duty ran into is no longer drawn as a day nothing was scanned for. A duty is filed under the day it starts, so one leaving on the 17th and landing after midnight Zulu on the 18th left the 18th with a plain red calendar page — which says "no OFF message was scanned" about a day somebody spent at work, and sends the reader looking for a message that was never going to exist. The page is now half blue from the left, the side the day before is on, and the row reads "On duty from the day before". None of that duty's figures appear on the day: they are not its figures. Tapping anywhere on the row opens the OFF message that does account for it, headed with a note saying it was carried over into the day you tapped and began on the day before — otherwise a record dated the 17th, reached from the 18th, carrying the 17th's figures reads as the wrong record having been opened.
- The Duty Days totals are broken down a tour at a time — Tour 1 with its columns, then Tour 2, then a TOTAL line under them. A fortnight is not a natural unit of flying and a tour is: the ten forgiven hours come off each tour rather than off the period, so reading the columns tour by tour is how the figures on the reconcile page are arrived at, and the TOTAL line is what that page should say. A tour's own pay is carried on its line rather than on a second one under it: it is worked out over the tour rather than over a day, but it is still money the period earned, and money is read from one column. Duty time is totalled too, and the separate FDP and grand total lines have gone — everything they said is on the lines above them.
- A tour that had not finished when the period closed is listed with a red note beside it. Its flying, night time and non-flight duty are on these days and are paid here; only the tour pay waits for the fortnight the tour ends in. Leaving it out would have made the columns add up to less than the days on the page, and counting its pay in would have claimed money the statement does not carry. The note also says what the tour is owed on the hours it has flown so far — the first ten of a tour are not paid separately, so it gives the hours flown, the hours payable after that, the rate and the sum, and says the figure grows with anything the tour flies later. Worked out on the hours actually flown rather than on the trip as the message plans it: a figure counting days nobody has flown yet would be a promise about the future dressed up as a statement of account. The note is laid at half strength over the white space before the flight time rather than set in the line, so the figure it qualifies does not shift along to make room for it — a column that moves on the one row you are being asked to look hardest at is the wrong trade. The note under the table says which tour and why, quoting 27.2(G)(3) beneath it.
- A tour line's flight time is what the tour had flown by the time the period closed. Hours flown before it opened are counted — the ten forgiven hours come off the tour rather than off the period, so a tour that began earlier brings its hours with it and they have not been paid for. Days the tour has still to fly are not: a statement cannot account for flying that has not happened. What was being read before was the trip as *planned* — the running Tour Total the message prints, which counts days still to come — so a tour four days into a period could show its whole eventual figure instead of the hours actually flown in it.
- The Duty Days totals bar carries the column names again, under the bar and over the figures they name. At the head of a collapsed fortnight they are a screen and a half away by the time you reach the totals, and a row of numbers whose columns you have to scroll up to read is a row you cannot read — scrolling up takes the totals off the screen.
- Every record can now be marked as checked against its picture by eye, separately from whether anything on it was edited. A record read perfectly and confirmed is not a record nobody has looked at, and until now the two were indistinguishable.
- The reconcile page names its two sides across the top and rules a box around each. ADP used to be a column heading a line lower, which put it in a row with Rate and Hours/Units — headings of the calculated side, which it is not one of. It now sits level with CALCULATED, and each name is centred over a rounded box drawn round the figures it belongs to — the app's rate, hours and amount on one side, what ADP printed on the other — the full depth of the block down past Monitored Gross Pay. The two boxes are held apart rather than sharing an edge, which is the whole point: boxes that touch read as one table ruled down the middle, and these are two sets of figures from different sources laid side by side to be compared. The heading column is neither side's figure, so it sits outside both, and the rule under the column headings breaks at the gap rather than tying the boxes back together. The statement's box now runs to the edge of the screen: its column carries five-figure sums and the room had to come from somewhere, so the comparison table alone gives up the page margin while everything else on the tab keeps it.
Pay reconciliation: photograph an OFF message and it files itself against the right pay period.
-
Added
- A copy button on each field of the credentials screen — email, password and 2FA secret — each saying which one it took. Three fields on one screen and a message that says only "copied" is a message you have to verify by pasting it somewhere.
- The device that exported no longer offers to import its own payload. It has the same clipboard as the device it sent to, and was prompting itself the moment it came back to the front. A payload already dealt with — exported here, or offered and turned down — stays dealt with for the session rather than coming back each time the screen is opened.
- Credentials can be sent to a second device over the clipboard, encrypted. The button under Save puts all three on the clipboard as one encrypted payload; open the same screen on the other device and, with Universal Clipboard on, it offers to import them. Setting a second device up by hand means reading a long password and a base32 secret off one screen and typing them into another, which is where mistakes come from. The receiving screen keeps watching the clipboard for as long as it is open, so the offer arrives while you are still looking at the other device rather than only when you next open the screen. There is no event to wait for — iOS raises no notification when Universal Clipboard hands a payload over, and the clipboard has to be asked — so it asks, every couple of seconds, and only while the screen is in front and the app is not in the background. iOS may put up its own "allow paste" prompt while it waits, which the screen now says in advance so it is not a surprise. What is on the clipboard is AES-GCM under a key derived from a fixed passphrase — which is protection from whatever else can read a clipboard, not from anyone holding the app, and is worth having for exactly that reason: a password sitting there in the clear is readable by everything that looks.
- Where ADP prints a rate and an amount but leaves the Hours/Units column empty — overtime among them — and the amounts disagree, the count it must have paid for is worked back out of the two figures it did print and shown in red under our own. An amount paid at a rate is a count: $659.55 at $43.97 is fifteen quarter-hours against the ten the duty records make it, and five missing increments is something you can go and look for. "Out by $219.85" is only the beginning of that question. It is offered only where the amounts are actually out, and not where it comes to the same count the app already shows — there the two parted company over the rate, and the rate column is the one saying so.
- A reconcile page on the Pay tab, one swipe to the left of the pay tables. The top half is the pay calendar — the last several fortnights, each showing what has been collected against it, so a period you have not kept up with is obvious at a glance. The bottom half is the detail for whichever period you pick.
- Scanning. Photograph your OFF messages as they come, then import the set: the duty period, the stations, the whole Duty Time Summary and the tour totals are read off each one and stored. Nothing is filed unseen — every scan is put in front of you afterwards, with its photograph and the raw scanner output one tap away.
- Pay periods are worked out rather than looked up. They run Sunday to Saturday, fourteen days each, counted from the confirmed period of 19 July to 1 August 2026, and pay day is the Friday after the period closes. There is no table to keep up to date and no year boundary to get wrong.
- Records are kept in their own database on the phone, separate from the bundled airport data so that refreshing that cannot take your own records with it. The photograph is stored on the record itself rather than in a file beside it, so the evidence travels with the record and survives a reinstall. Each one is scaled down on the way in — a fortnight of full-size camera images would be most of a gigabyte, for pictures that only ever need to be legible.
- A camera button beside the batch, for the message that has just come in rather than a stack of them. That one is shown before it is filed, which a batch cannot do without stopping at every picture.
- An import can be stopped part way. It finishes the picture it is on and leaves everything already read filed, so nothing is half-done.
- Scanning the Vector Roster calendar. The roster carries the final coding for every day of a month, settled after the OFF messages have gone out, so where the two disagree the roster is the one that counts — and the record shows both, the superseded code struck through beside the one that replaced it. Which way a day was coded before it was recoded is usually the whole substance of a pay query, so it stays on show rather than being quietly replaced.
- Reading the roster is a matter of geometry: the calendar writes no dates in its cells, so each day is worked out from which column and which row its code sits in, under which month heading. The week always runs Sunday to Saturday, so a month cropped away from the weekday headings still reads — the heading sits centred over the seven columns, which is enough to place them. A week of days off leaves no mark on the page at all, so rows are placed on a measured spacing rather than counted, and the finished reading is checked against the month it claims to describe: only one alignment puts every code on a real day.
- A duty period can be seen as well as read. Tapping one now draws it end to end, with the extra pay laid where it is earned and the clock along the bottom in both local and Zulu. Non-flight assignment duty is the least understood thing on a statement, and the reason is that the answer turns on when it happened rather than how much of it there was: the same 1:03 pays at the head of a day and pays nothing at the tail, because at the tail it lands on the minutes overtime already has and 27.2(I) pays "not more than one for the same period of time". No figure can show that. The chart draws both claims where they fall, hatches the one that lost, and shades the 2300–0559 window behind them. A bar's height is money, against a scale down the left, so a hatched block above a solid one is quite literally the amount that was owed and not paid. The time marks along the bottom carry both clocks and thin out to whatever the screen has room for — every hour, every two, every four. It fits the width at rest, because a duty period has a shape and the shape is the first thing worth seeing; a Zoom control beside the legend opens it into a scroller where the quarter of an hour that decided the money is a block rather than a hairline. Tapping the chart itself asks a different question and gets a different answer: what that stretch is, when it ran, how many increments it counts, at what rate, and what it came to — both claims where two of them want the same minutes, since that is the case the chart exists for. A chart that changed scale when you pointed at part of it could not also be asked what that part was.
- What is drawn is only what can be placed. Overtime is duty past the threshold, so it is the tail; end-of-day non-flight duty follows the last flight duty, so it is the tail too — which is exactly why they collide. Tour pay is not on the chart and cannot be: it is worked out over a whole tour on the hours past ten, so it belongs to no particular minute. Night flight pay is not there either — the message prints how many hours of it there were and not when they were flown, and a band drawn where it might have been would be a guess wearing the clothes of a measurement.
- The reconcile page carries the same idea at period scale: a column per day showing what it earned beyond salary, with anything a clause took away hatched on top. A day that gave something up under 27.2(I) otherwise looks exactly like a day that earned less. Tapping a day lays its figures over the chart at half strength — over rather than under, so the column you tapped stays in view and the shape of the period stays the context the figures are read in. Its columns are stacked by what earned the money rather than drawn as one flat "paid" block — Extended Day, FDP Night, FDP flight, NFAD, Holiday and OT each have a colour, so a column can be read without opening it. Flight duty pay belongs to no single day, being worked out over a whole tour, so it sits on the day the tour ended, which is the day it became payable; tapping that day says how many of its hours were flown before this period opened, since a payout landing on one day for flying spread across two periods is the commonest reason a statement looks larger than the days it covers.
- Fixed: non-flight duty that began before the overtime did was being dropped in full. 27.2(I) pays "the greater ... but not more than one for the same period of time", and the qualifier is the whole of it — where one claim opened before the other, the stretch before the second began was never claimed twice and is owed on its own account. 31 July 2026 is the day that showed it: 53 minutes of non-flight duty from 05:07 against overtime opening at 05:15 when the duty passed twelve hours. Three of the four increments are inside the overtime and go; the first is not, and is paid. It cost an increment a fortnight and read as an unexplained discrepancy on the reconcile page.
- Which claim is "the greater" is now settled over the contested minutes rather than over the two totals, because that is the period of time the clause is about. The winner keeps its whole entitlement rounded once, as the contract rounds it — rounding the two halves of a split claim separately would quietly make it larger, since 87 minutes of overtime is six increments but 63 and 24 apart are five and two.
- The first day worked of a tour is marked as such on the duty chart. 27.2(B)(1) changes two things at once — the threshold drops from twelve hours to nine, and duty before 0800 pays on top — so the same thirteen-hour day is a different day at the start of a tour. A dashed rule is drawn at 0800 and at the nine-hour mark with DUTY OT on the side of each that the overtime is on, and "FIRST TOUR DAY RULES APPLY" sits across the top at half strength, since a reader who has not noticed which day it is would read the nine-hour line as a mistake — it sits above the chart, underlined, and opens the clause when tapped. The DUTY OT marks sit in a strip just above the plot rather than among the bars they are not part of. An ordinary day gets one dashed rule at twelve hours. Tapping the overtime key on a first day quotes both 27.2(B) and 27.2(B)(1) — quoting only the general rule on a day the special one changed the answer would be quoting the wrong half.
- Fixed: a day's column on the pay period chart could overflow its own height. Each block has a floor so a few dollars is still visible, and on the tallest day of the period the blocks already fill the column — so the floors had to come out of the total rather than be added to it. The blocks are now scaled to fit.
- The Vector calendar draws the lead-in days of a tour that began in the month before, muted. The cells before the 1st are blank on an ordinary month; left blank on a period like 2–15 August they read as a tour that started on the 1st, when the roster plainly shows it opening in July — and those days carry flight time the period is paid for. Muted rather than full strength, because they belong to the month next door; and skipped where that month is already drawn on the page, since a day drawn twice is a day a reader has to reconcile with itself.
- A duty record is headed with the day it is for — "Wednesday 5 Aug 2026" — with that day's calendar tile beside it, rather than "Check this over". The old heading was an instruction: it said what to do and not what you were looking at. A duty record is about one day, and which day is the first thing worth knowing — particularly where a duty that ran past midnight Zulu is reached from the day after the one it is filed under. The tile is the same one the month grid draws, so the day on the sheet and the day on the calendar are recognisably the same square. A picture that could not be read has no day to name and still says so.
- Fixed: the reader was told to ignore text as small as a duty code. Vision's default is to skip anything shorter than a thirty-second of the picture's height, which is sensible for a document and exactly wrong here — a code on a Vector roster is one character in a small square, about a fifty-eighth of a phone screenshot, and the asterisk marking an extended day is half of that again. It was being asked to skip the payload, and it obliged unevenly: most squares came back and the odd one did not, which is the worst way to lose one. The V on 3 June and the X on 31 July both went that way, and the missing 31st took a duty day out of its tour and 8.2 hours of flying out of the fortnight that pays for it. Reading the same two screenshots at the corrected setting recovers both, along with the four training days on 16–19 June and the asterisk on 23 July.
- Fixed: the marker bar the roster draws under a day could be read as a duty code and wreck the reading. It comes back as a dash in a box a whole column wide, sitting between two rows — and since the row pitch is the smallest gap between rows, one of them halved it and every row below was then placed on a grid that does not exist. The June screenshot has one, under the 9th of July, and it took that month from a clean reading to "no month was completely in frame". A duty code is one or two characters inside a square and never fills it, so anything as wide as the square is not one. Both screenshots are now kept as tests, read exactly as Vision returned them.
- Fixed: re-importing a month left the picture it used to be read from stranded in the database. The month was re-pointed at the new picture and the old one was simply left where it lay — a hundred and thirty kilobytes of screenshot nothing could reach, show or delete. Four had piled up in a fortnight of ordinary use. A roster picture now exists only while some month is read from it, checked after every import, every deletion and on opening the database, so the ones already stranded go on the next launch.
- The Vector page shows the roster and nothing else. It used to fill the grid in from the OFF messages as well, which meant deleting a roster left a month's worth of duty still drawn on it — the picture went, the codings went, and the calendar carried on as though nothing had. An OFF message is not the Vector roster: it is what the company sent the day it flew, which the roster can and does supersede. A month with no roster imported is now blank and says so; a month with one fills in completely, days off included, and still shows the coding it superseded struck through beside the new one. Nothing is hidden — the days an OFF message was scanned for are still marked in the corner and still open it, and what the messages say is what the Duty Days tab is.
- Fixed: a roster could be read perfectly and placed upside down. The reader tries the picture at four rotations and keeps the best, but a half turn is the one it cannot judge — the words come out identical and every box keeps its shape, so the two passes score within a character of each other and the winner is decided by nothing at all. When the half turn won, the text was right and the grid was inside out: a June picture put June's codes on a July calendar, mirrored left to right so the G4 on the Monday came out on the Friday, and named June twice as a month it had skipped. Nothing about it looked like a failure, which is what made it worth catching. Two things on a roster run one way only and either settles it: the months go forwards down the page, and the week reads Sunday to Saturday. A picture failing either is turned back over and read again.
- The roster review screen is accepted from a button at the bottom reading "Accept this import", beside Cancel, instead of "File" in the corner of the title bar. Filing overwrites codings that pay figures are worked out from, and a word in the top corner is one to be pressed on the way past — the calendar underneath has not been looked at yet when your thumb is up there.
- Reading a picture holds the page under a dimmed cover with the progress on it, rather than a line of text at the bottom of a page that still works. Left live it invited a second import on top of the first, or a change of fortnight that the reading then landed in the middle of. A quarter opaque, so the fortnight stays legible behind it: the point is to say the app is busy, not to hide what it is busy with. A batch keeps its Stop, which finishes the picture in hand and leaves everything already filed.
- The roster review screen names the month it is filing, first and in colour. A picture framed as the guide asks holds one month whole and the edges of the two either side, so every good photograph produces two month names — one filed and one left alone. Until now the only coloured notice on the page was the one naming the month that had not been filed, so importing a June picture that also showed the top of July read as though the app had decided the picture was July. It now opens with what is being filed, names the month in the title bar, and says that the blank squares are filed as days off rather than missed — a month with seventeen codes in it still files thirty days. The message after filing names both months too, instead of counting them.
- The grey band on the duty chart is named NFP and says what was flown in it. It marks 2300 to 0559 on the local clock, which is the window 27.2(H) pays night flying in — and unnamed it read as scenery, or worse as somewhere the night flight pay had been quietly bundled. Tapping the band gives the hours the OFF message says were flown at night; tapping the key quotes 27.2(H). Both say plainly why it is a band and not a bar: the message prints how many hours were flown between those times and never when they were flown, so the window is as precise as the record gets. Everything else on the chart is drawn where it happened, and this could not be. On a day that flew nothing in the window the band stays unnamed and inert — then it is only a fact about the clock.
- An increment of non-flight duty that reaches into overtime is contested whole. 27.2(I) pays "not more than one for the same period of time", and non-flight duty is paid in quarter hours — which cannot be halved. On 31 July there are 53 minutes of it from 05:07 and overtime from 05:30: four increments, of which only the first finishes before the overtime opens. The second runs 05:22 to 05:37 and so covers seven minutes the overtime is paid for, which is one for the same period of time, so it goes with the two after it. The clear part used to be rounded up, which paid that second increment and made the fortnight one unit too many; it now counts whole increments only. The fortnight from 19 July claims 11 and is paid 8.
- The duty chart draws the increments and hatches the ones that were taken. The entitlement is one bar in its own colour end to end — drawing the taken part as a bar of its own made it look like a different entitlement — with red hatching over the increments another clause had first, and the quarter hours ruled in when the chart is zoomed. So 31 July reads as four blocks of non-flight duty with the last three hatched, and the overtime sitting on top of exactly those three: what opened first is drawn underneath, so the claim that took the increments rests on the ones it took. The legend carries the entitlement twice, once plain and once hatched, and tapping the hatched key says what the hatching means before quoting the clause. Tapping either part of the bar shows both, since "three of your four increments went" is only half an answer, and the other half is the half that resolves the discrepancy on the statement.
- Closing a reading on the duty chart leaves the chart where it was. Zoomed in, the stretch under discussion is somewhere off in the middle of a chart several screens wide, and the panel closing threw it back to the start of the day.
- Fixed: a square the roster reading came back empty on no longer deletes a duty day. The roster leaves a day off blank, and a reading that missed the letter in a square leaves it blank too — nothing in the record tells the two apart. 31 July 2026 is coded X on the picture and came back empty, and the blank went on to discard a day the crewmember has an OFF message for, split its tour in two at the month boundary and leave 8.2 hours of flying belonging to no tour at all. A blank square is now nobody saying anything, and an OFF message is the company saying the day was worked; where those two meet the message stands. A square the roster really did code — the "2" after an extended day, a leave code — still settles it, as it always did.
- The lead-in days of a tour are drawn with their coding, and every day of the tour is marked rather than only the photographed ones. The Vector tab used to load the months it draws and nothing more, so the days before the 1st that a period pays for came out as grey squares saying nothing — and a tour whose middle days were never photographed was drawn with holes in it. A day with no message behind it carries no flying figure, because nothing has been read that says what it flew.
- The duty chart's money scale stays put. Zoomed in the plot is wider than the window and scrolls; drawn on it the scale scrolled away with the bars and left them measured against nothing. It has a column of its own beside the chart now, outside anything that moves.
- The reconcile chart no longer marks what was owed and not paid. Where a claim went is a fact about one duty period, and the duty period chart is where it is drawn, at the minute it happened and against the claim that took it. On a column of days it was a red block with nowhere to point.
- Overtime is called Duty OT on the reconcile chart and in the pay lines as well as on the duty chart. It is duty time over a threshold rather than extra flying, and the two are different things to query.
- Fixed: reading a block while zoomed in opened the panel off to the side. It was laid over the chart, and zoomed the chart is wider than the window with its middle wherever the scroll happens to be — so a tap read as a tap that did nothing. It is laid over what is on screen now.
- A duty record already on file offers to Cancel rather than Discard. Nothing is thrown away by leaving one, and the word said otherwise; a scan not yet filed still says Discard, where it is the right word.
- Non-flight duty is called NFAD wherever it appears, on the charts and in the pay lines both. It is what the OFF message calls it, what ADP calls it, and what a pay query would be about; spelling it out in one place and abbreviating it in another made them look like two different things.
- A day's coding is named rather than quoted. "Coded *" tells a reader which character was in the cell, which the roster already showed them; the line now reads "Extended Day (*)", "After Midnight Return (2)", "Voluntary Additional Work Day (R)". The code stays in brackets so the line can still be tied back to the day it came off.
- "Owed, not paid" names which entitlement lost. It is not always non-flight duty: 27.2(I) pays whichever of the two competing claims is worth more, and it is the overtime that loses on a day the non-flight duty ran longer. A reader who assumed the commoner case would be wrong on the day it mattered. Tapping the key explains the term and quotes the rule behind it.
- Tapping a legend on either chart opens the contract's own wording for that entitlement — 27.2(B) and 27.2(B)(1) for overtime, 27.2(C) for the extended day, 27.2(D) for holidays, 27.2(G), 27.2(H) and 27.2(I). A colour on a chart is a claim about somebody's money, and the question it prompts is always the same one: says who. Quoted, never paraphrased. The duty chart names non-flight duty NFAD rather than spelling it out, since that is what the OFF message calls it, what ADP calls it, and what a pay query would be about.
- Both charts say what "owed, not paid" means where any of it appears: hours two parts of the contract both cover, of which 27.2(I) pays the greater and not both. It is not missing pay — it is the same hours claimed twice and settled once — and unexplained on a mark about somebody's money it reads as exactly the opposite.
- The note on the reconcile page now says how many increments of non-flight duty the messages carry against how many are paid, and which days account for the difference — the gap between those two numbers is the whole of the confusion, and nothing on either page used to say they were different questions.
- Fixed: a bad reading could not be corrected by importing over it. An import wrote the days it found codes on and left everything else exactly as it was — but a roster codes a day off by leaving the square blank, so the days a picture is most certainly right about are the ones it says nothing on. A mis-parsed picture that filed the weekday strip as a week of duty codes therefore survived being re-imported over, on whichever of those days happened to be days off: the good reading overwrote the worked days and could not touch the rest. An import now says what stretches of calendar it covered, not just what it read, and clears them before writing — so a day the new reading found empty goes back to being empty.
- Where two pictures claim the same day, the one that held the whole month wins. The fringe of a neighbouring month is a week seen through the edge of a frame; a month held whole was read against its own length and checked by it. A part-month reaches no further than the days it actually read, so the first week of July off a June picture cannot wipe the rest of July with an absence.
- The V on a pay period card now says how many roster pictures are behind it. A fortnight straddling a month end is read off two screenshots, and a small superscript 2 beside the V says so from the list — having to open the viewer to find out whether the second one ever got imported was the wrong way round. Nothing is written for one picture: a superscript 1 on every other row is noise, and the thing worth pointing at is the fortnight that needed two.
- Fixed: the V went on offering to open pictures that had been deleted. It was drawn from whether the fortnight had roster coding, which is a different question — the coding is the roster and stays whatever happens to the photographs. It still stays, because "a roster covers this fortnight" is worth knowing on its own, but it only looks like a control while there is something to open: ringed and pressable with pictures behind it, plain and quiet without, where pressing it could do nothing but apologise.
- "Tap to see the Vector roster image" now opens every picture the fortnight was read from, not just the most recent one, on a screen of its own. A fortnight that straddles a month end comes off two screenshots — one for the days before the boundary and one for the days after — and showing only the newer answered half the question, since the coding in doubt is usually the one at the join and lived on the picture that was not shown. What is being looked at is evidence for a pay period rather than a photograph, so the screen is headed with the fortnight it belongs to, the picture is inset and bordered instead of taking the display over, and each one is captioned with the days it accounts for: "Covers 21–30 June". Pinch or double tap still magnifies it in place, and each keeps its own zoom.
- A strip of thumbnails along the bottom of the roster viewer, the one on screen picked out, tap to jump. Dots would say how many there are and which this is; thumbnails say that and also what the others look like, which is the thing worth knowing when two screenshots of the same calendar are being told apart. It is left off when there is only one picture, there being nothing to choose between.
- A roster picture can be deleted from the viewer. It asks first, and says plainly what survives: the codings read from it stay on the calendar — what goes is the evidence, not the roster, and deleting a photograph is not a claim that the days were coded differently. The picture is removed from every day its import filed rather than only the fortnight on screen, which would otherwise leave the months either side offering a picture the record no longer has. Deleting the last one closes the viewer and brings the calendar's marker back into line.
- The tail of a month whose own heading has scrolled off the top is now placed by measurement or not at all. It is the riskiest band on the picture: a week of codes from the end of a month can be fitted at almost any offset without contradicting itself, so "several offsets fit" is not evidence of anything and leaning towards one of them was a guess dressed up as a reading. The distance from one month heading to the next settles it instead — that distance is the gap above a grid, plus the rows the month between them needs, plus the gap below, and every term but the last is known. Where only one heading is in frame there is no second grid to reason from, so the tail is left alone and named rather than guessed at.
- Fixed: the weekday strip could still be read as a week of duty codes when OCR ran two of its letters together. It was only recognised as the strip if all seven were found separately, and they are a row of single characters, so a missed one dropped it back into the grid — where it became a phantom week filed against the month above, which is how an August picture came back reporting fifteen days of July. Five letters in the right order are now enough to know it for what it is, and anything above it is treated as the app around the calendar rather than the calendar: a lone letter of chrome reads as a duty code just as readily as a real one does. All seven are still wanted before it is trusted to say where the columns are — five letters place five columns, and the grid is the better guide to the other two.
- Every month in frame is read, whole or in part. A picture framed as the guide asks — one month centred, a week either side — has a part-month at each end by design, and those weeks are real roster: a pay period straddling a month boundary needs exactly them. They used to be thrown away, on the grounds that a half-visible grid cannot be placed safely. It can, so long as its position is worked out rather than guessed: a band sitting under its own month heading starts at the top of that month, and a band above the next month's heading finishes at the bottom of its own. The review screen names each part-month with the dates it actually yielded — "June 2026, the 21st to the 30th" — so you can see at a glance whether the fortnight you care about is covered. A month whose codes cannot be laid on the grid at all is still filed for nothing and named, since a reading that does not add up is worse than none.
- Which grid row a month starts on is now measured instead of tried. A month opening on a week of days off leaves no text in its first row, so the first thing under the heading is the second week — read as the first, it shifts the whole month by seven days into codes that are all perfectly plausible. How far the heading sits above the first row says which it is, and that distance is a property of how the calendar is drawn rather than of any month, so one month with something written in its first week settles it for every month on the picture.
- Fixed: the "S M T W T F S" strip was being read as a row of duty codes. Its letters are the same shape as codes — a bare "S" or "T" is indistinguishable from a cell — so it became a row of its own, sitting a fraction of a row above the first week. Since the row spacing is taken as the smallest gap between rows, that fraction became the spacing, and from the fourth week down every row landed where it did not belong. More often the arithmetic simply stopped adding up and a properly framed picture came back as "could not place any duty codes on it". The strip is now recognised by the company it keeps — seven letters on one row spelling the week — and kept out of the grid, while still being used for what it is good for, which is saying exactly where the seven columns are.
- No month can put its codes in another month. Every date is built from the month whose band it was read from and rejected unless it falls inside it, so a reading that drifts can lose a code but never file one under the month next door. The reading is shown back as a calendar in the same shape as the picture, so a week out of place is obvious rather than buried.
- Two duty periods can no longer overlap. A pilot is not on two at once, so an overlap is two readings of one duty rather than two duties — a reissued message, or the same one photographed twice. Scanning one that clashes lays both out in full, with their dates and times, what they totalled and where they ran between, and asks which is right. Nothing is discarded on the assumption that the newer scan wins. A batch cannot stop and ask fourteen times, so it files what it read and points at the clashes in its results, where they can be sorted out one at a time. Overlaps are compared by the hours a duty covers rather than by its date, which is what catches a duty running past midnight against the next morning's.
- The duty code table now leads with the codes that pay something on top of salary, and the rest follow in the published document's own order — reordering a reference table makes it harder to check against the paper one.
- An arrow beside the tabs pulls the panel up over the pay calendar to use the whole screen, and puts it back. The ADP statement and the Vector calendar are both worth more than half a phone.
- The earnings table now fits the width of the screen instead of being dragged sideways to reach the year-to-date column. The five columns share the width, long labels wrap, and any figure too wide for its column shrinks rather than breaking across two lines — a number split over two lines is unreadable, the same number a point smaller is not. Pinching zooms in, which is the answer to the small type that fitting five columns onto a phone inevitably produces; zoomed in it scrolls sideways, and a Fit button puts it back.
- Tap any duty code, anywhere it appears, for what it means. All 65 codes are searchable by code or by description, and a code the table does not list is flagged as the likely misread it is. The codes that pay a multiple of the daily rate — extended day, after midnight, VAWD — carry a blue pill showing what a day coded that way is worth at your Pay tab selection. Only those: ordinary duty, training and leave sit inside the salary, and putting a figure against one of them would be inventing something about your pay.
- A Vector tab that draws the calendar as the app understands it, in the roster's own colours. Scan a fortnight of OFF messages and it fills in with what they said; scan the roster over the top and it redraws with the final coding, so what changed is what moved. A day still resting on an OFF message alone is marked as provisional, a day nobody has scanned is drawn unlike a day off — the two are quite different claims — and where the roster overrode a message the old code stays in the corner with a line through it. A small grey OFF in the top right marks a day an OFF message was scanned for. Tapping a day offers what that day has to offer: the picture the OFF message was read from, what its duty code means and what it pays, and the pay period it belongs to. A day with no message behind it does not suggest opening one, and a day with no coding does not offer to explain it — but every day opens, because every day belongs to a pay period whether or not anything has been scanned for it.
- The ADP pay statement can be kept with the fortnight it paid. AirDrop the PDF at Sidekick, or share it in from Mail or Files, and it reads the statement's own header to work out which pay period it belongs to — so attaching it is a confirmation rather than a hunt through a list of dates. It can also be picked from Files by holding a pay period on the calendar. The document is stored on the record itself, so it opens whether or not the file that arrived is still on the phone, and a statement attached to a fortnight it does not claim to pay says so when opened.
- An imported statement is read before it is accepted, and checked on three things: the employer it is drawn on, the name and address it is made out to, and the fortnight it pays. The first one is always put in front of you to confirm, and what you confirm is remembered so the next one can be measured against it. After that it only interrupts when something is off — a different employer, a different name or address, a page it could not read, or a statement it cannot place in a fortnight. The three checks are shown either way, because a check nobody ever sees is one nobody trusts.
- The Duty Days list shows the hours off between one duty period and the next, on the line that separates them — measured from when duty actually finished, so a duty ending after midnight is not credited with rest it did not have. Past a day it is written as "1 day + 10:15 OFF" rather than "34:15", because hours on their own have to be divided before they answer the question actually being asked. Each row now carries the date as a page off a calendar rather than two lines of small text.
- The pay period still running carries a countdown to its pay day beside the "in progress" mark.
- Every pay period of the year is listed, not just the last handful, and each carries its statement number — the fortnight running 21 December to 3 January is the new year's first, because payroll counts by the day it pays rather than by the days worked. A bar of years above the calendar goes back five of them, matching the tab bar below so the calendar between the two reads as the thing they are both selecting.
- Statements open from two places: hold a pay period on the calendar, or tap any day of that fortnight on the Vector tab. A period with one attached is marked on the calendar.
- A paperclip beside the camera attaches a statement without having to pick the fortnight first — the document says which one it pays. Each pay period on the calendar carries two markers in fixed places, so they line up down the column: a V where a Vector roster has been scanned over the fortnight, and a paperclip where an ADP statement is attached. Either opens what it stands for. The ADP tab also carries a bar pinned under its tabs, since that page is a working of the statement and is meant to be read against it, and the Vector tab carries the same bar for the roster screenshot its calendar was read from.
- Tapping a Vector day also offers the photograph on its own, full screen, as well as what was read from it.
- The Vector tab now sits before ADP.
- The tabs are named for what they hold rather than for whichever fortnight is selected — that is on the calendar above them, and repeating it only made a tab's width jump about as the selection changed. They read Duty Days, Vector, ADP and Reconcile, and sit on a solid indigo bar: the one fixed thing on a screen where everything under it changes.
- An ADP tab that lays the pay period out the way the earnings statement does — the same headings in the same order, with Rate, Hours/Units, This Period and Year-to-Date — so the two can be read straight across from each other. Tour, night and non-flight pay come from the scanned duty records; the rates come from whatever you have chosen on the Pay tab, so changing your seat or schedule there changes the figures here. Anything that cannot be worked out is left blank with the reason beside it rather than filled with a zero, and the total is labelled for what it is: the lines the records can account for, not gross pay.
- Scanning is done a batch at a time. Pick the set of photographs and they are read one after another, each one filed the moment it is read — so the pay calendar above fills in as the batch runs rather than everything appearing at the end. When it finishes, every scan is listed for checking, and anything wrong can be corrected or removed from there. Anything unreadable is named along with why, and two pictures of the same duty period are called out rather than quietly collapsing into one record.
- Tapping a photograph opens it on its own, fitted whole to the screen, with pinch or double tap to zoom in far enough to read a station ident the scanner was unsure about. A tap anywhere closes it again.
- On an iPad the photograph sits beside what was read from it, in the review, and while correcting a record — so a figure and the message it came from can be read straight across.
- Extended day pay now shows on the ADP tab once a roster has been scanned. An OFF message never says a day was extended and the roster does, so the line stays empty until there is a roster to read it from. It is paid at the VAWD rate, two and a half times daily — not the one and a half times the pay tables list under a similar name, which is a different thing. An extended day running past midnight is coded with a star on the day it began and a 2 on the day it finished, and that pair counts as two extended days; a 2 on its own is an ordinary after-midnight return and counts as none. X6 is left out on purpose — the duty code table calls it an extended day not eligible for additional pay.
- The FDPP ring, as it is drawn in the other app. Planned trip time on the pay calendar was a bare number; it is now ringed, and the ring answers the question actually being asked — not how many hours, but how far past the ten that pay starts at. The first lap round is the climb to 10.0, and every lap after it is a thousand dollars earned, with the same nine colour bands. What those hours have earned is printed under it, with the ten hours taken off before the multiplication rather than after.
- Tapping a ring opens what it is made of, laid out as the other app lays it out: flight time at the top, the flight earnings under it split into tour based and night flight with the hours each was worked out from, and the non-flight assignment duty day by day — a figure you disagree with is a day you can point at. The figure under the ring is the two halves together rather than the tour alone, and the ring counts its laps of that same total. Night hours earn from the first one: the ten-hour threshold belongs to the tour, not to the night, so a night flown on a short tour is still paid. The question mark on any block opens what went into that figure.
- A duty day now shows its flying leg by leg, under Flight time summary between the duty period and the duty time summary — the order the message itself puts them in. The company has always broken the day out: "Tour Based Flight Time=(1.5+1.7+0.6=3.8 Day Total)" is three flights, and nothing was showing them. Where the message says how much of a leg was at night, that is noted against it; NA is kept as no night flying rather than as a zero, because a leg flown in daylight and a leg not yet read are different things.
- The duty list said "flight" and showed the duty day. The summary's Flight figure is one of the categories a duty day divides into — flight, reserve, travel and the rest — so on a day that was nothing but flying it comes to the whole duty period and says nothing the line has not already said. 21 July read "duty 9:27 · flight 9:27" when 3.8 hours of it was in the air. The list now shows the tour-based flight time, and the summary's own Flight row carries a note saying what it is, because that label is the one in the list that gets read as something it is not.
- The duty list reads as a table. The coding leads each row, the city pair follows it and the clock times close it, marked L for local because the message prints two clocks for every duty period and telling them apart is what this screen is for. Underneath, the day's figures sit on a dark band in named columns — Duty, Flight, Night NFAD and OT — under a heading in the same dark, so the band and what names it read as one thing. NFAD and OT each show the time worked and the increments it draws, and what the day earned on top of salary goes on a line of its own beneath. The clock times carry both readings, local and Zulu, each said to be what it is: the message prints two for every duty period and they routinely fall on different days.
- Overtime is worked out under 27.2(B), which needs to know where a day sits in its tour. Any day pays for duty over twelve hours; the first day worked of a tour pays for duty over nine, and for all duty before 0800 on top of it. The same thirteen-hour day draws one hour of overtime in the middle of a tour and four at the start of one. Quarter-hour increments throughout, any fraction counting as a whole one, at the annual base over 2,184 hours times one and a half.
- Which day of the tour a duty day is now sits under its calendar page — "6/9" — and the first day of a tour is picked out, because that is the day the overtime rules change on. The tour it counts against is the roster's: a roster codes every day of the month, days off included, where an OFF message only exists for a day both worked and photographed. The tour that ran 15 to 23 July is nine days long, and only the roster knows it — three of those days were never photographed, and the OFF messages alone had the tour starting on the 17th. Where the roster has coded both days the running tour total is not consulted: 24 July opens a fresh total having flown nothing yet, and it is the tenth day of that tour rather than the first of a new one. A "2" counts as worked despite the roster tinting it like a day off — it is the second of a pair of extended days.
- The duty list now has a line for every day the roster knows about, not only the days an OFF message was scanned for. The roster is the fortnight's other half — it knows the days no message was ever sent for, the days off around them and the coding the company settled on — and a list of only what happened to be photographed left all of that out. A day with no message shows its coding, a red calendar page and a row of dashes where its figures would be. A worked day says plainly that nothing was scanned, because that is a day whose figures nobody can verify and whose pay nobody can query; a day off says so quietly, since it is not missing anything — it is the shape of the fortnight around the days that are. The empty message is left for a period with neither a roster nor a single message behind it.
- A collapse button to the left of the column headings takes the list down to the figures alone: a date and six columns, and a fortnight of them on one screen. Collapsed there is a column the expanded list has no need of — "Extra $", what the day earned on top of salary, which expanded sits on a line of its own under the figures. A table of hours with no money in it answers half the question. It is set flush right, to the dollar and wide enough for five figures: the pennies are noise in a column read down, and the sheet behind the row has the exact amount with the working beside it. Its width is fixed while overtime beside it flexes, because a truncated time can still be read and a truncated amount cannot. The coding, the route, the clocks and the money all belong to reading a single day; comparing fourteen of them is a different job, and it was a scroll. Tapping a row still opens the whole record.
- The ten designated holidays of 27.2(D)(1) are in the app, and a duty day that falls on one wears its date in a red pill. Only three of the ten fall on a date — the rest are counted off a weekday of a month, and Good Friday and Easter Sunday move with Easter, which is worked out rather than tabulated so the app does not quietly stop knowing about them in a few years' time. The date rather than the band above it: the band is already saying whether the photograph was kept, and a second meaning on the same paint would take both down with it.
- Working a designated holiday pays a premium of one and a half days under 27.2(D) — the extended day rate of 27.2(C)(1), "in addition to all other compensation earned on the holiday" — and it now leads the day's extra pay with the sum written out. It is the largest single thing a duty day can draw and it does not depend on how the day went.
- Where the day's coding pays a multiple of its own — an extended day, a voluntary additional work day, an after-midnight return — that is listed in the day's extra pay too, at the multiple the code carries. Codings that pay nothing in their own right are left alone: ordinary duty, training and leave are inside the salary, and quoting a figure against one of them would be inventing a fact about someone's pay.
- Every filed duty day now carries the extra pay section, including one that earned nothing beyond salary — which says so, and says why tour pay is not part of it. A section that came and went left you wondering which day it was you had seen it on.
- Sidekick now opens images as well as PDFs. Send it a JPEG, PNG or HEIC — AirDropped, opened from Files, shared out of Photos — and it reads the picture, works out whether it is an OFF message or a Vector Roster calendar, and puts it through the same review the camera does. Which of the two it is comes from the text on the picture rather than from a dialog: the two read nothing alike, one being prose with labelled figures and the other a grid of one- and two-character cells under a month heading, and asking would be asking a question the picture already answers. It is scored rather than decided on a single marker, so a roster whose month heading was misread is still plainly a roster, and one stray month name in a message's footer does not carry the decision. A picture that is neither is said to be neither rather than filed as a guess.
- The reconcile page's earnings block is now the statement's own block: the same columns in the same order — Earnings, Rate, Hours/Units, This Period — set in a typewriter face, under the word CALCULATED, with one column added on the right for what ADP actually printed. Held against the paper it is a reconciliation you can do with a finger; laid out any other way it was two documents to read at once. Every heading the statement prints is there, including the ones that paid nothing this fortnight, because a reader checking one against the other counts down the list and a list with the blank lines taken out cannot be counted down.
- A guide before the first import, with a worked example of each picture. A Vector calendar wants one month centred with a week of the month either side in view — a month is only taken when its whole grid has clear space above and below it, and the neighbouring weeks cost nothing and prove it. An OFF message wants the top of the message through to the Non-Flight Assignment Duty line, which is the last line that matters. It also says that either can be AirDropped straight to the phone and shared to Sidekick without being saved first, an ADP statement PDF included. A checkbox at the foot puts it away for good, and that choice survives the app being closed; without ticking it the guide comes back next time, because continuing is not the same as understanding.
- Holiday Crew is worked out rather than left open. The ten designated holidays are a fixed list and a duty record is what says one was worked, so the line pays one and a half daily rates for each under 27.2(D) — and reads nought where none was worked, which is an answer rather than a gap.
- Where a fortnight's non-flight duty went to overtime in its entirety, the line shows the rate and the increments ruled through in red against an amount of nought. A bare nought there says the time was never worked; it was worked, and paid under another heading. The note marks are red discs now rather than numbers in brackets.
- 27.2(I)'s "greater of" is applied. Where a day's non-flight duty falls in the same hours as its overtime, only the larger is paid — which is what the OFF message says in its own footer: the NFAD it prints "includes all possible NFAD time ... some possible NFAD time may not result in NFAD pay". The clause turns on the same period of time, and that is what decides it: end-of-day pay under 27.2(I)(1) is the tail of the duty and so are the hours past twelve, but night duty pay under 27.2(I)(2) is between 2300 and 0559 — on a duty that begins in those hours it sits at the head of the day, often on the other side of midnight from the overtime, and both are paid. Checked against two statements: a 13:27 duty from 15:01 local lost all five of its non-flight increments to six of overtime, and a 13:50 duty from 00:20 local at Tokyo kept both.
- Numbered notes under the comparison, marked against the lines they belong to. They exist for one question — why an hour plainly on the duty list is not on the statement — and they name the day and quote the clause, because the answer is a paragraph of contract rather than a figure. Only the notes that actually apply to the fortnight are shown. The duty list says the same thing on the day itself: the line stays, with the increments it drew and why they were not paid.
- A month the roster reader put aside now says so — on the review screen and in the message after filing, by name. A month is only taken when its whole grid is in frame with clear space above and below, and until now one that was not simply vanished: the only clue was a fortnight that never filled in.
- A record files under the day its own message dates its start at, rather than under the local day at the departure station. The two differ whenever a duty starts late enough in the Zulu day: a duty leaving Tokyo at 15:20Z is 00:20 the next morning in Japan, and its record was landing on the 20th where the message, the roster and the pilot all called it the 19th. Worse, it then sat on top of the duty that really did start on the 20th, which the app refused as an overlap. The message's own date is the company's word for which duty day it is, and the roster codes the same days. Records already filed are moved on the next open.
- A day can carry two duty periods, and now shows both. One that starts early and finishes quickly leaves room for another the same day, and the company sends an OFF message for each — so the day gets two lines, earliest first, and no tour break is drawn between them.
- The rounding is no longer carried into the totals. Where the app and the statement agree to within the tolerance, the statement's pennies are the ones that stand — the app's rates are derived by compounding and land a cent either side, and a cent on each of three lines was the difference between the discrepancy quoted at the top of the page and the one footing it. The Gross Pay line is read off the column above it too, so a total that does not add up is one less thing to wonder about.
- Collapsed, the duty list heads the table with the days from before the fortnight whose flying it nonetheless pays for — the early days of a tour that finished inside it, every day of it rather than only the photographed ones, each numbered in its tour as every other row is. They are shown at half strength and carry flight time and nothing else, because the FDP figure cannot be checked without them and none of the other columns are this fortnight's to claim: the duty, the night flying and the non-flight time all belong to the period the day fell in. A dashed rule separates them from the fortnight proper, dashed rather than solid because it is not the same kind of boundary as a tour break. Those days carry the same blue page as everywhere else where the photograph is on file, and tapping one opens it: a day borrowed from the previous fortnight is still a day with an OFF message behind it, and it was drawing red and inert whether or not there was one.
- Under the totals, a line for each tour the fortnight pays: FDP, the hours left after the ten-hour threshold comes off, and what they came to. One line per tour because the threshold is met per tour and not per fortnight — two nine-hour tours pay nothing between them where one eighteen-hour tour pays eight hours, and a single pooled figure cannot show that. The flight time totalled above is the whole of the flying; these are the hours the money is worked out on, and the two being different numbers is the point.
- Below those, the pay period grand total: every day's extra pay and every finished tour's FDP. Salary is not in it — it is the same every fortnight, and is not what this table is read for.
- A boxed figure on the reconcile page now carries the difference rather than a second copy of ADP's own — signed, so plus is the app claiming more than was paid and minus is the statement paying less. The ADP column was already saying what ADP said; what the box is for is the arithmetic between the two, which was being left to the reader. The figure footing the block is signed the same way.
- Collapsed, the duty list is footed with totals. A solid blue bar across the width the tour breaks are drawn on, with TOTALS on it, and under it the fortnight's flight time, night flight, non-flight duty, overtime and extra pay in the columns they were read down. Duty is deliberately not totalled: fourteen duty days added together is a number nothing pays on, and a figure that looks like a total but answers no question is worse than a gap. The increments are counted a day at a time and rounded up on each, as the contract pays them — totalling the minutes and rounding once gives a different and smaller answer.
- The discrepancy at the top of the page and the one footing the block are now the same figure. The verdict summed only the lines flagged as out, and the footer took the whole difference against the monitored gross — which left the two a few cents apart, both called a discrepancy. Every calculated line is also rounded to the cent now, as a statement line is: an unrounded product carried into a total drifts against the sum of its own rows.
- The duty list remembers whether it was collapsed when you look at another tab and come back. The setting was held by the list, and the tab bar throws a tab away the moment you leave it.
- The headings the app does not work out — the gross-ups, Late Brief, Longevty BNS and the per-diem pair — are dimmed to a quarter strength. They are still on the page, because they are still on the statement, but a column of blanks beside a column of figures reads as a discrepancy and none of them is one.
- Two rows now foot the block. Total Unmonitored is what the statement paid under those dimmed headings, and Monitored Gross Pay is its gross with them taken off — the part of the fortnight this page is actually checking, and the figure the calculated total should equal. Where the two are more than a dollar apart the difference is boxed in red under the calculated figure. Per diem is dimmed but not subtracted: the statement prints it among the earnings and leaves it out of Gross Pay, being a reimbursement rather than pay, and taking it off a second time would put the remainder out by exactly its own amount.
- A heading the statement prints twice keeps both lines. "Gross up res" appears once with only a year-to-date figure and again with the fortnight's, and the repeat was being dropped — which threw away whichever of the two carried the amount, and left the fortnight's 135.32 out of the reckoning entirely. Both lines stay now, and only the first takes the app's figure so nothing is claimed twice.
- Overtime is worked out rather than left blank. It follows from the duty records under 27.2(B) — everything over twelve hours in a duty period, or over nine on the first day of a tour with the duty before 0800 on top — counted a day at a time and rounded up on each, because any fraction of a quarter hour counts as a whole one. Summing the minutes and rounding once would quietly lose an increment every other day. Against the statement for 19 July to 1 August 2026 it lands exactly: 13:50 on the 20th is 110 minutes over twelve hours and so eight increments, 12:30 on the 31st is thirty minutes over and two, and ten increments at 43.97 is the 439.70 the statement pays. With nothing scanned the line stays blank — a zero there would say the fortnight worked no overtime, which is a claim rather than a gap.
- The longevity bonus is no longer quoted at all, not even a rate. What it comes to depends on the schedules flown across the whole year, and the app sees a fortnight of roster — so any figure would have been a guess dressed as a calculation.
- The duty totals below the comparison now count the days the roster worked that no OFF message has been scanned for. It is the most useful number on the page when a figure is out: an hour on an unscanned day is an hour the app cannot see, and one of them will account for a difference more often than any error in the arithmetic — a single quarter-hour of non-flight duty on a day nobody photographed is a line that disagrees by thirteen dollars for no visible reason.
- Where a figure is out, the statement's own is set beneath it in red inside a box, and the line is given room for it. Each column has the tolerance that suits it: a dollar on an amount, a cent on a rate, a hundredth on a count of hours. The rate and the hours are worth checking apart from the amount because they say why — almost every discrepancy is one rate against another or one count of hours against another, and an amount that is out with both agreeing is arithmetic rather than a question. Gross Pay is shown but not compared: several headings cannot be derived at all, so the app's total is short by whatever they came to rather than wrong by it.
- Under a dollar between the two sides is close enough, and counts as agreement — shown green, and marked as a rounding difference rather than as a match. The two sides round in different places, and colouring eighty cents red buried the lines that were really out. The verdict at the top of the page counts the same way.
- An extended day that ran past midnight now pays three daily rates rather than two and a half. The roster codes it * on the day it began and 2 on the day it finished; the 2 is the marker that says it ran over rather than a promise of a duty period of its own, and what it changes is the multiple on the star. With the day it ran into still paid at the ordinary extended day rate, the line now reproduces the statement for 19 July to 1 August 2026 exactly — a star on the 23rd with a 2 on the 24th and a second star on the 29th come to 3.0 + 2.5 + 2.5 = 8.0 daily rates, and 8.0 × 1,231.10 is the 9,848.77 the statement prints. The line is quoted against the daily rate now, with the number of daily rates as its units, because the days are no longer all worth the same multiple of one — a rate and a count that do not multiply out to the amount beside them are worse than none.
- The pay tables' night rate is corrected at source as well, so the PAY tab quotes the same figure the reconcile page does.
- The current 2FA code is recomputed when the app comes back to the front. The ticker behind it does not run while the app is asleep, so the code on screen was whatever it had been when the phone was put down — which after thirty seconds is simply wrong, and looks right.
- The FDP Night rate is now read off 27.2(H) rather than taken from the pay tables, which had it a step behind. The clause states it outright — fifty dollars, rising 2% compounding every 1 January from 2024 — so 2024 is 51.00, 2025 is 52.02 and 2026 is 53.06, which is what a 2026 statement prints. The tables compounded up to but not including the year asked for and stopped at 52.02, a dollar an hour short, and it showed up as the app disagreeing with the statement about a rate the contract spells out.
- The Pay tab's reconcile page keeps its place when you swipe over to the pay tables and back. A page swiped away from is thrown away unless it says otherwise, and it was taking the selected fortnight, the chosen tab and every scroll position with it — a swipe that costs more than it saves.
- Night flight pay was reading as zero on the reconcile page for a fortnight the duty list plainly had hours in. The fortnight's night flying was never being handed to the figure the page is built from — 27.2(H) pays it by the hour flown, so it belongs to the period the duty day falls in rather than to the period its tour was paid in, and the period's own total was the one thing not being passed. The year-to-date column had the same hole.
- One import button for both: "Import OFF/Vector" takes a stack of pictures and works out what each one is as it reads it — messages are filed as they go, and a roster stops to be confirmed the way it always did. The separate Vector Roster button is gone, along with having to know which button a picture belonged to before you pressed it. The paperclip still takes a PDF statement, which is a different kind of thing and does not go through OCR at all.
- The figures band is set in a fixed-width face, headings and all. The band is read down its columns rather than along its lines, and tabular figures alone were not enough — they even up the digits and leave the punctuation to fall where it may. Duty, NFAD and OT are written as four digits throughout: "09:27" rather than "9:27", since an hour that drops its leading zero shifts every digit in the column one place left.
- The quarter-hour counts on NFAD and OT now sit in a blue pill beside the time rather than running on from it as text. They are a different kind of number from the time they follow — one is how long it lasted, the other is how many increments it draws, which is what it is actually paid by — and set as plain text the two read as one figure. The pill carries the count alone; being a pill is what says it is not more of the time beside it.
- The tour position under the calendar page is the day alone now, "6" rather than "6/9". The double blue rule already says where the tour ends, so the length was being stated twice on every row of it.
- Collapsed, the row is built as a table line rather than as a record with a heading. The calendar page comes down to the height of the figures band beside it — losing the white space under the number, with the day of the month at half the size — so the date and its figures read as one line rather than as a picture with numbers next to it. The position in the tour moves out to the left of the page, into the margin the row gives up: a table has no use for a left margin when a fortnight has to fit on a screen. It is still drawn as a calendar page, because the shape is what makes a date readable without being read.
- The calendar page beside a duty day is blue where the photograph is still on file and red where it is not. A day whose figures can be held up against the message they came from is a day a pay query can actually be made about, and which days those are was previously one tap at a time. The list reads it without carrying the pictures: a fortnight of photographs is most of a gigabyte, so the row asks the database for the single bit rather than the image.
- Opening a duty day from the list now fetches its photograph, which it had not been doing — records store the picture on the record itself, the list leaves it behind, and the sheet was showing the day as though no evidence had been kept for it.
- A duty day now opens with a way straight to the photograph — "Tap to open the attached OFF message" — worded, coloured and placed as the ADP tab and the Vector calendar word theirs. All three pages are a reading of a document, and the way back to that document should be the same offer in the same place on each. The three strips are now one piece of code rather than three copies of it.
- Opening a duty day now shows how its extra pay was arrived at, directly under that strip and above the figures it was worked out from — the money is what the sheet is opened for, and the summary is what gets checked when the money looks wrong. A line at a time: the hours, the rate, the paragraph it is paid under and what the two multiply to — "2.6 hours × $53.06/hr · 27.2(H)", "1:45 worked, 7 quarter hours × $13.27 · 27.2(I)(1)" — totalled at the bottom. A figure queried with the company is queried by its working rather than by its answer, and the row in the list only ever had room for the answer. Overtime on the first day worked of a tour names both halves of what it drew, the duty before 0800 and the duty over nine hours, because they are two separate claims that happen to be paid together. Where a rate is not known the time is still listed and the money is left blank rather than counted as zero, and the total says it is short. Tour pay is stated as absent, since its ten-hour threshold is met once per tour and no part of it belongs to a single day. The list and the breakdown are worked out by the same code, so the total on the row and the sum behind it cannot drift apart.
- Where the duty list crosses from one tour into the next, the line between the two days is drawn as two blue rules rather than as the hairline that separates one duty day from another — a double line reads as the end of a group, where a heavier single one only reads as a heavier line. The two gaps are not the same kind of thing: the ten-hour threshold comes off once per tour and none of the money is payable until the tour closes, so where a tour ends is worth seeing rather than counting up to. A day the app could work no tour out for draws no line at all — a missing roster should not look like a boundary.
- Contract wording for night flight pay, 27.2(H), is in the app. Along with it, the limit worth stating: the figure is the company's and the app cannot check it. Night flight is counted between 2300 and 0559 by local departure time, and an OFF message prints no departure times at all — only when the duty day began and ended. A night total that looks short against the hour a duty day started is a question for the company, not something the app can settle.
- The edit and delete buttons are gone from every row. Editing is what opening a record is for, and deleting is a swipe — a list read down a fortnight of duty does not need two destructive-looking targets on every line of it. The tour pay is deliberately not in it: the ten-hour threshold is met once per tour, so no part of that money belongs to any one day of the tour.
- Tapping a Vector day opens the day itself, drawn large, and the sheet pages left and right through the calendar. A cell in a seven-column month is a few millimetres across and every marker on it is smaller than that; blown up it says what it has been saying all along. The action taken applies to the day left on screen rather than the one first tapped. A day with nothing on it now reads the same paged through as it does in the month: green, and saying "NO DUTY" in words. Only a day still owed a scan is drawn dark with a dash, and an OFF message whose coding could not be read counts as owed — the day was worked, and calling it a day off would be inventing a fact the picture never carried.
- The sheet keeps its full height as it is paged. Every choice is always listed, and one with nothing behind it is greyed and says so — "No OFF message available", "No image available" — rather than being dropped. Swiping from a duty day to an empty one used to shorten the sheet under the finger, which is distracting to read and easy to mis-tap. "View the picture" is now "View the image".
- A copy button on what the scanner read. That text is what gets pasted into a pay query, and selecting a screenful of it with a fingertip is a fiddle.
- FDP is worked out per tour, which is what it is. Nothing pays until a tour is finished, and the ten-hour threshold is met once per tour rather than once per fortnight — two nine-hour tours earn nothing between them however the hours add up. A fortnight is credited the tours that finished inside it, so a tour begun before the period opened is paid by the period it ended in. Nothing in an OFF message names a tour; the running Tour Total gives the boundaries away, because it only ever climbs within one and starts again from near nothing when the next begins.
- A small FDP on a Vector day says the day is part of what the selected fortnight pays, with the word in the bottom left and the day's own flying in a dark notch cut into the bottom right corner of the tile — so a fortnight's figure can be read back to the days that made it. The code a roster superseded moves to the other corner rather than sharing one with it. The point is the days it marks outside the fortnight: a tour is paid by the period it finished in, so the first days of one routinely fall before the period opened, and a calendar is the only place that is visible. The legend says so.
- The pay calendar shows one ring for everything a fortnight was paid. Tapping it opens a ring for each tour behind that figure, with the dates it ran between, so a fortnight paid two tours shows two rings and a figure that looks wrong can be traced to the tour it came from rather than to the two weeks it landed in.
- A ring that earned nothing now says $0. A blank under it read as a figure still being worked out, where $0 reads as a fortnight that did not earn — which is a fact worth stating.
- Each of the three figures opens its own workings. Flight time lists the duty days that made it up with their city pairs; night flight draws each day as a block with the night part of it in red and the hours printed on the red; non-flight assignment duty lists what it is, quotes the OFF message's own warning that NFAD time only pays where it beats the overtime for the same hours, and prices each day. Non-flight rows now carry the money beside the hours, at a quarter of the night rate — which began as an inference and is confirmed by a statement printing 53.06 at night and 13.27 for FDP Non-Flt.
- The workings under each half of the flight earnings say what was actually multiplied — "16.9 @ $204/hr" rather than a count of hours flown — so the ten that does not pay is visibly off the books before the rate is applied.
- Contract wording is quoted, never written. Each of the three sheets ends with what the contract says, read verbatim out of assets/contract_language.json; until that is filled in the sheet says so rather than paraphrasing. A summary would read with the authority of the document while being somebody's account of it, and would be quoted back in a pay query as though it were the wording. A figure can be governed by more than one subsection, so a sheet can quote several — non-flight duty carries both 27.2(I)(1), End-of-Day (10+ Hour) Pay, and 27.2(I)(2), Night Duty Pay, in full.
- NFAD has a card of its own beside the two flying figures, priced at the 27.2(I) factor. The sheet behind it opens on that rate — by the hour and by the quarter hour, as the statement prints it — then the table of days, then the contract wording. The rate is what a non-flight duty figure is queried against and it moves every year, so it leads rather than sitting under the hours it produced; the caveats follow the table, where there is something to apply them to. It is deliberately not counted in the flight earnings above it, because non-flight duty is not flying — but it is counted in the ring, which is everything the fortnight earned. The two are counted over different spans on purpose: FDP is earned per tour and paid when the tour ends, where 27.2(I) pays non-flight duty on the pay period, so the ring pools the tours that finished in the fortnight with the fortnight's own non-flight hours.
- Non-flight duty is not split between the two subsections that pay it, because an OFF message reports one figure and does not say how much was End-of-Day and how much was Night Duty. It makes no difference to the money — both pay the same factor — and the sheet says as much rather than inventing a split. Where it does matter is eligibility, which is why both sections are quoted.
- Any line on Reconcile opens its workings. A red row says there is a discrepancy but not why, and "out by $2,040.00" is the start of the question rather than the answer. Tapping one lays the two sides side by side — rate, hours and what they came to — and says where they parted company: a rate that differs is out for every period and worth settling once, where hours that differ usually mean an OFF message or a roster not yet imported. Where neither side prints a rate to compare, it says that rather than inventing a reason.
- The ADP tab now shows what the statement says, not what the app worked out. The earnings table is read off the attached PDF — heading, rate, units, this period and year-to-date — along with gross and net pay. A column the statement leaves blank is left blank: a zero under This Period would be a claim the document does not make. The table is fitted to the width of the screen and can be pinched larger, with a way back to the fitted size.
- Reconcile now does the reconciling. Each heading carries the app's own figure with ADP's in brackets after it: green where they agree to the cent, red where they do not, with how much it is out by. A heading the app cannot work out is grey rather than red — a gap is not a discrepancy, and colouring it as one would cry wolf on every statement. Above it, one line: how many categories disagree and the discrepancy in dollars, with which way round it falls. Netted rather than added up in absolute terms, because two categories out by the same amount in opposite directions is a clerical swap rather than money missing, and a count on its own cannot tell those apart; the duty totals stay underneath, because a figure that is out is explained by a missing OFF message more often than by anything else.
- Each pay period carries a card on the left: the statement number printed across a blue header, and under it the white the V and the paperclip sit on — one for a roster that has been scanned, one for an ADP statement that has been filed. The number is how a pay query is referred to, and the two markers say what you already have to hand for it, so the three read together instead of sitting at opposite ends of the row. The card is the same size on every row whether or not either marker is there, so the column stays lined up. The V is ringed, because the paperclip beside it already looks like something to press and a bare letter did not.
- Filling the screen with a pay period no longer loses track of which one. The years stay across the top and the chosen fortnight sits under them, so the stack reads years, period, tabs, figures. The period there is the row from the calendar, so the V and the paperclip are still to hand; tapping it brings the calendar back. Picking a different year drops back to the calendar too — asking for a year is asking to see its fortnights, not to land inside one of them.
- The calendar page beside each duty opens the OFF message it was read from. The row itself already opens the record; the photograph is the one thing a record cannot show you about itself, and it is what you reach for when a figure looks wrong.
- Correcting a record by hand. Every figure the scanner reads can be typed over — the dates and times especially, since those decide which pay period the duty is filed under. Correct a date and the record moves to the right fortnight, and the page follows it rather than leaving you looking at a list it has just dropped out of. Corrected records are marked, because a figure you typed and a figure the company's own message printed do not carry the same weight in a pay query.
-
Fixed
- A multi-leg day was recorded at the length of its first flight. The message prints the day as "(1.5+1.7+0.6=3.8 Day Total)" and the reading took the first decimal after the heading, so a three-flight day went into the record as 1.5 hours instead of 3.8. Night flying was read the same way and lost the same way. Both now take the figure after the last equals sign, which is the total wherever there is one.
- Records already scanned are put right on their own. The columns are a cache of what the parser made of the message, and the message is kept verbatim precisely so a better reading can be applied without anything being photographed again — so it now is, every time the database opens. A record showed the contradiction plainly: it listed its three legs as 1.5, 1.7 and 0.6 and called the day 1.5 hours, because the legs were re-read and the total was not. Records corrected by hand keep every figure that was typed, with one exception — a day total that is exactly the first leg of a day whose total is printed in the same bracket. Nobody types that; it is the old reading, and it is put right.
- Night flying was being counted over the wrong span. It followed the tour, as the tour pay does, and it does not: the statement paid on 7 August pays 7.50 night hours for 19 July to 1 August, which is 2.6 hours on the 20th plus 4.9 on the 31st — and the 31st belongs to a tour that did not finish until 5 August. Only the tour pay waits for its tour to end. Night flying and non-flight duty are counted on the pay period, and with that the fortnight reconciles on both lines: 204.00 x 16.90 is the 3,447.60 the statement printed, and 53.06 x 7.50 is its 397.95.
- FDP Tour on the Reconcile page was working the fortnight out again instead of reading the figure the ring already had, and getting both halves of it wrong: it counted the duty days that fell inside the fortnight rather than the tours that finished in it, and it never took the ten-hour threshold off before applying the rate. On a single tour that is over two thousand dollars. The tour and night lines now come straight from the ring, so the page that checks the figure and the calendar that shows it cannot disagree. Non-flight duty keeps its own line, as the statement gives it its own column.
- The non-flight rate is rounded to the cent before it is multiplied, because that is what the statement does — it prints 13.27 and pays eight of them as $106.16, where the unrounded 13.2651 gives $106.12. Four cents is not worth arguing about; a line flagged red over four cents is.
- Non-flight duty was being counted in hours where the statement counts it in quarter-hour increments. A fortnight of 1 hour 43 minutes went in as 1.72 against a rate quoted per quarter hour, which is two different units multiplied together. It is now counted the statement's way — one duty assignment at a time, rounded up, because an increment part-used is an increment — and each day shows how many increments it came to. The figures reconcile: two hours is eight increments at $13.27, which is the $106.16 the statement paid on that very line.
- Non-flight assignment duty was priced at a quarter of what it pays. The statement prints the End-of-Day factor twice — "FDP Night 53.06" by the hour and "FDP Non-Flt 13.27" by the quarter hour — and the quarter had been read as the rate, so every hour of it came out four times short. It is now taken from the contract itself: section 27.2(I)(1) puts the factor at $50.00 rising two per cent compounding every 1 January from 2024, which gives 53.06 for 2026 and matches the statement to the cent. The pay tables have this a year behind at 52.02, which is the 2025 figure.
- Picking a pay period left the ADP tab showing the fortnight before it. Selecting a period re-read its records and its calendar but not its statement, so the figures on screen belonged to whichever period had been open when the app last did a full load. The statement is now re-read with everything else, and dropped while it is being read — one period's pay shown under another's heading is worse than showing none.
- Nothing scanned or attached showed up on the pay calendar until something else redrew it. Each path refreshed only its own corner — the roster scan the letters, the statement the clips — so whatever a path forgot stayed stale on screen. They now all go through one refresh that re-reads everything the calendar draws. There is no version of the old arrangement that is right by construction, which is why it has gone rather than been patched.
- The V did nothing when pressed. It was wired to bring the Vector tab forward rather than to open the roster, which is not what the marker promises — and it did not manage that either, because the tabs are built below the calendar and the code looking for them from above found nothing at all. It now opens the roster picture the coding was read from, which is the same bargain as the paperclip.
- Half a route. A duty out of Denver into Amsterdam was listed as "KDEN" with nothing after it. The scanner reads the M in EHAM as a Cyrillic letter — the same glyph on screen, and not one the station pattern would match — so that end of the route was dropped, and with it the local clock, which then fell back to Zulu and made the duty look as though it ran backwards through the night. Letters that share a glyph with a Latin one are now put back before anything is read. Letters that do not, such as a Greek delta, are left alone rather than guessed at.
- Total duty read as zero. Zero is a legitimate figure everywhere else in the Duty Time Summary, so a line the scanner lost looked like a fact rather than a failure. Total duty is the one figure an OFF message states twice — once in the summary and once as the two timestamps at the top — so where the summary line is missing it is now taken from the timestamps. What the message does say is never overwritten: a stated total that disagrees with the clocks is still flagged, which is what this page is for. Nothing else in the summary is inferred, because nothing else is stated twice.
- The Scan OFF messages button was still the theme's purple. It is the screen's blue now, like the tab bar and the year bar above it — it was the last thing on the page wearing the old colour.
- A PDF sent to the app threw an error about a missing route. Flutter treats an incoming URL as a deep link and pushes it as a named route, and a file path is not a route. Deep linking is now off, and a document the app has claimed is no longer passed on.
- A duty code that is not a letter was thrown away. The extended day is a star, a day turned off is a slash, and half the table is a letter with a digit after it — and only a single letter was ever read. Such a day was filed with no coding at all: nothing on the Vector calendar, nothing in the duty list, and no extended-day pay counted for it. The code is now taken from between the brackets the message prints it in, whatever it is made of.
- The employer read off a statement came back as gibberish. The label AVI is three letters of the employer's own name, so without a required colon the reading landed inside "NetJets Aviation, Inc." and returned everything after it. Beyond that, the extractor sometimes strips the spaces out of the page altogether, which defeated every rule that assumed a space meant anything. Values are now cut where the next printed label begins, spaces are optional throughout, and names are compared with the punctuation and spacing thrown away — so "NetJetsAviation,Inc." is recognised as the same employer as "NetJets Aviation, Inc.", and shown as the latter, since that is how it is written.
- The name on the statement was dropped altogether. The address block comes off the page as one unbroken run of characters, so there was no line for any of it to be found on. It is now matched as a whole shape — a name, a numbered street, then a town with a comma, a state and a postal code — which needs no line breaks at all. The comma is what keeps the company's own address out of it. Where the page prints the name more than once and one copy kept its spaces, the legible copy is the one shown.
- The statement is now read word by word rather than as one lump of text. A PDF holds no spaces — it holds glyphs at positions — so asking for the text of a page leaves it to guess where the gaps were, and on this document it guessed badly enough to run a name into the routing code printed beside it. Every word carries its own bounds, so joining them puts back exactly the spacing the page has.
- The address is no longer checked or kept. It is not what identifies a statement, and moving house is no reason to question your pay.
- Dates on the attach sheet are written the way the statement writes them — 07/19/2026 - 08/01/2026 — so checking one against the other is a matter of looking rather than converting.
- Importing a statement now says outright whether a pay period was found for it, in green with the fortnight named, or in red when none matched. The list of fortnights only appears when there is something to choose — offered unasked it read as a question, when the answer was already known.
- A PDF sent to the app did nothing at all. Two reasons, both silent. The app runs on scenes, and in a scene-based app iOS never calls the handler the document was being waited for on — it delivers to the scene instead. And the screen that files statements is the second page of a tab, which is not built until somebody swipes to it, so even a document that did arrive had nothing listening. Documents are now collected when the app starts, held until something can act on them, and the app brings the Pay tab and its reconcile page forward to meet them.
- Summary figures could be read as zero when they were nothing of the kind — a scan reported no travel time against a message that plainly showed 2:29. Each figure was being looked for at the start of its own line, which is not a promise the scanner keeps: a speck of dust read as a character in front of the label, or two short entries run together onto one line, and the figure was missed. Because zero is a perfectly ordinary value everywhere in this message, nothing looked wrong.
- The summary is now read the way a person reads it: find the times, then see what each one is called. Nine ways the scanner was seen to break up the same message are covered by tests, all of which failed before.
- The summary is also listed in the message's own order and its own words — Meals Received, Duty coding, Flight, Reserve, Travel, Training, Admin, Standby, Total Duty, Tour Based Flight Time, Tour Total, Night Flight Time, Non-Flight Assignment Duty — so checking a record against the message on screen is a matter of reading straight down both. The review, the editor and the comparison all take that list from one place and so cannot drift apart.
- What was called elapsed time is now duty time, which is what an OFF message calls it. Where it disagrees with the Total Duty the message states, that is now said rather than left for the reader to notice.
- A long field no longer ran off the right-hand edge of the review on a narrow phone.
- Closing a photograph without zooming into it first no longer crashes the app.
-
Worth knowing
- A duty period is filed by the local day it began on, not the Zulu day the message prints. The two differ more often than not — the sample this was built from runs 22:22 on the 5th to 00:51 on the 6th in Zulu and looks like it crosses midnight, when it is a single afternoon in California. The local day is the one the pay period counts.
- The scanner reads the message however the phone in the photograph is held, upright or on its side, and does not mind the picture being taken at an angle.
- Photographing the same message twice corrects the first scan rather than adding a second record, so a picture that came out badly can simply be retaken.
- Scanning needs an iPhone or iPad. It uses Apple's own text recognition, which reads a photograph of a screen far better than anything that would have to be bundled with the app, and adds nothing to its size.
Clears an App Store warning about the location permission.
-
Fixed
- Added the second location purpose string Apple asks for. The location library refers to the always-on location API even though this app never uses it, and Apple requires a description for anything the code can reach.
- What the app asks for is unchanged: permission is still requested only for while the app is open, and the prompt you see is the same.
The catch-up rules explained, with the band you are in marked.
-
Added
- A catch-up section in the 401(k) help covering all four bands, with the one you are currently bound by outlined and labelled.
- It makes the point that the 60 to 63 super catch-up is a window rather than a step up: it is higher instead of the ordinary catch-up, not as well as it, and it drops back at 64.
- Also noted: the company matches catch-up, the catch-up you pay in is not counted against the ceiling but the match on it is, and recent law requires catch-up to be Roth for higher earners, which is worth confirming with the plan.
- Letter of Agreement 29-001, signed 6 January 2026, is noted alongside it: super catch-up contributions only became available here from 1 February 2026, even though the tax rule allowed them from 2025.
-
Fixed
- Dates set in the menu now take effect on the Pay tab straight away. The Pay tab stays loaded behind the menu, so it was still showing whatever it had read when the app started, and only closing and reopening the app picked up the change.
-
Fixed
- Catch-up eligibility now follows the age you reach at any point in the calendar year, which is what the rule actually says, rather than your age on the day. Someone turning 50 in December was being shown the under-50 limit for the whole of that year, when they were entitled to the catch-up from the January before.
How much premium pay goes into the 401(k), and when it stops.
-
Added
- Section 27.2(J) is now in the 401(k) help, quoted in full: a third of your combined Tour-Based, Night Flight and Non-Flight Assignment pay is paid into the plan rather than in cash, and none of it is matched.
- Worked out beneath it: how much room the everything-in ceiling leaves for that contribution, and the amount of combined premium pay that uses it up. Past that point nothing more is pulled and it is all paid in cash.
-
Note
- The clause works the room out as if you had contributed the maximum and taken the full match, whether or not you did. So the answer does not change with your own contribution rate: someone contributing nothing has exactly the same room as someone maxed out. That is surprising enough that the help says it plainly.
- The sums now follow your catch-up bracket. The catch-up you pay in is not counted against the ceiling, but the company match paid on it is, so being in a catch-up band leaves less room for the premium-pay contribution, not more.
- The box also gives the most that can reach the account in a year: the ceiling plus your catch-up, which sits outside it. Nothing about the order you contribute in changes that total.
The match schedule now says which rate you are actually on.
-
Added
- The match schedule in the 401(k) help marks the rate in force and carries a pill showing the contract year in effect.
- Between January and April it explains itself: contract years run 1 May to 30 April, so the pay tables shown are the previous year's until 30 April. Without that, a 2025 label in March 2026 looks like a mistake.
-
Changed
- The airport dot on the map now grows as you zoom: 3 pixels looking at the whole globe, 5 by the time you are down to the 50-mile view, and no larger closer in. It no longer follows the text size slider, which had been making it a blob at large settings and invisible at small ones.
-
Note
- The match increases are dated 1 January while contract years turn over on 1 May, so for those four months the two genuinely disagree. The help says both: which contract year the tables come from, and which match rate is actually in force today.
-
Fixed
- The everything-in note was overstating what can be paid in. It took 20% of base as the contribution, which on a higher salary is far more than anyone is permitted to defer, so it reported a total nobody could reach. It now caps the contribution at the legal limit first and works the match out from that.
- That note now quotes the same percentage the table marks, so the two read as one answer rather than two unrelated ones, and it adds that catch-up money does not count against the ceiling.
The 401(k) help now works out the number you actually need.
-
Added
- The 401(k) help now opens from the contribution card as well as the 401k Match card. They are two views of one subject, so sending them to different pages would mean reading both to get the whole answer.
- It shows what percentage of base reaches the limit across 26 paychecks, and what that is per paycheck. Getting this wrong either leaves match on the table or hits the limit early and stops the match for the rest of the year.
- A table of contribution rates showing what you put in, what the company adds and the total into retirement at each. The row that maxes you out is marked. The company column stops climbing after 20% of pay, which is the argument for where to set your own rate.
- The everything-in limit, which was missing: a separate and much less well known ceiling covering your contributions and the company's together, with how close 20% of base gets to it.
-
Note
- The figures are for the year, seat, fleet and schedule on screen, not a general example, and the catch-up is included once your date of birth calls for one. Without a date of birth it assumes none, which is the limit that applies to everybody.
- With ALL on, an airport holding nothing but hidden aircraft is now drawn faint, the same as their tail numbers, whether it shows as a code or as a dot. A field with even one aircraft you selected stays solid.
Tell the app your dates once and the Pay tab keeps itself right.
-
Added
- Hire date, date of birth and retirement in the menu, at the top, each saved on this device.
- Automatically adjust years of service in pay tab. With it on, the Pay tab works out your year from the hire date every time it is drawn, so an anniversary moves you up a step on the day without anyone touching anything. The year you are in counts as year one, so six years in reads as year 7.
- A planned retirement age. Choose one and the retirement date follows from your date of birth, so it stays right if the birth date is ever corrected. The list shows the date each age works out to, so you can see what you are choosing. Retirement stays greyed out until a date of birth is set, since it is worked out from it.
- Automatically highlight 401k rules that apply to your age in pay tab, and a 401(k) contribution limit card at the foot of the Pay tab. It shows the standard limit and every catch-up band, with the one that applies to you outlined and labelled. The band for ages 60 to 63 is higher than the one at 50 and drops back at 64, which is easy to miss.
-
Note
- Both switches stay off until the date they need has been entered, so nothing on the Pay tab changes until you have asked for it.
- The menu shows the conclusion, not just the setting: it prints the year it would select and the age it would use, so a mistyped date is caught where it was entered rather than as a wrong figure elsewhere.
- While years of service is automatic, the row still shows the step in force but no longer responds to a tap, since the next redraw would overrule it. Setting a retirement age likewise makes the date read-only; clear the age to pick a date directly again.
- The contribution figures come from the IRS and change most years. The card prints the year its numbers belong to.
- The dates stay on this device.
- The 401(k) card sits at the foot of the Pay tab, below the pay figures, and uses the same blue as the bar along the top rather than the purple the framework picks by default.
- The Pay tab title no longer runs off the right-hand edge on a narrow phone. It now shrinks to fit, so the year, seat, fleet and schedule all stay readable.
Punctuation tidy-up.
-
Changed
- Long dashes removed from every piece of text the app displays, rewritten as full stops or commas where that read better.
- The Pay tab info page now lists every chip that answers to a long press, and says that the list is complete, so a long press that does nothing reads as expected rather than broken.
The Fleet tab explains itself.
-
Added
- An info button beside Deselect all, covering what a row means: the (12/38) counts — how many of that type have flight data against how many are on the roster — the green pill showing how many are in the air, and what ticking a box actually changes.
- It also says why the counts are taken over the whole roster rather than over what is currently shown: a number that collapsed to zero the moment you unticked it would be missing exactly when you are reading it to decide whether ticking it is worth anything.
- A matching info button on the Company tab, covering the aircraft count beside each operator, what the tick changes, and — most usefully — why most of the list is greyed out: those operators are known, but their positions are not available to show.
-
Changed
- PAY and Downloads are no longer locked when the app is run from a simulator or a development build. The lock needs a recent message board login, which there often is not while developing — leaving the two tabs most worth working on the two that could not be opened. Installed builds are unchanged.
- An info button beside the Pay tab's title. It explains what the title is telling you, what each selector along the top changes, and — the part that was not discoverable at all — that the figures below explain themselves on a tap while the chips along the top do so on a long press.
The map's info page now matches the map.
-
Changed
- Colours are explained on a tail pill rather than on an aeroplane symbol. The symbol only ever appears on an aircraft that is actually flying, so using it to explain four states it does not apply to was showing something the map never draws.
- The same tail number is shown in each colour and shade, so the only thing changing down the list is the thing being explained — including the red of a selected airport and the faded look of a stale position or an unused field.
- Every button down the right-hand side is now listed and described, drawn as it appears on the sidebar.
- The green aeroplane symbol is shown with the airborne tail, since that is the one place it appears on the map — an aircraft in the air is drawn as the symbol at its estimated position with its tail beneath.
- The section on flights whose landing never arrives has been removed.
-
Changed
- The map panel's Options tab has moved to the end. It is set once and left alone, where the tabs beside it are read constantly.
-
Fixed
- Framing everything on the globe while map imagery was on left the plain map faded with nothing behind it — a washed-out map and no imagery. Any change of view now drops the imagery once you are zoomed too far out for it, and the map returns to full strength. Zooming back in brings it back.
Real map detail under the globe when you are zoomed in close.
-
Added
- A map imagery button on the map sidebar. Switched on, OpenStreetMap is drawn underneath everything else and the plain coloured map fades back to a quarter, so roads, towns and coastlines show through with the aircraft and airports still over the top. It carries its attribution, as the licence requires.
- Offered only when you are zoomed in far enough for it to mean something. At a whole-globe view it would be an unreadable smear and a great many downloads.
-
Changed
- Choosing an airport now turns the globe to it without changing your zoom. Use the zoom button when you want to go in — picking an airport to read about should not throw away the view you had set up.
- The chosen airport always shows its identifier, in red, whether or not the ICAO button is on. It is the answer to what you just asked for.
Looking an airport up now takes the map there.
-
Added
- Choosing an airport turns the globe to it and puts it in the middle, drawn in red with its own 50-mile ring and every neighbouring airport filled in — the same treatment the location button gives your own position. Both rings can be on screen at once.
- Zoom in and zoom out buttons on the airport page. Zoom out returns to the view you had before the first zoom rather than stepping blindly outwards.
-
Fixed
- Opening an airport now starts at the top of its page. Reading down through one airport's runways and then opening another used to leave you halfway into the new one.
Every airport in the database is now a page you can look at, and tapping one on the map opens it.
-
Added
- An Airports tab. Search by identifier, name or town — KJFK, Heathrow, Aspen — and get what the database holds: ICAO, IATA and local codes, position, elevation, whether it has scheduled service, every runway with length, width, surface and lighting, and the published frequencies.
- Links to the airport's Wikipedia article and its own website, opening in the browser. The address is shown under each link, because the data is crowd-sourced and a fair number are stale — being able to see where a link goes before following it is the difference between a reference and a guess.
- Airports live on the map page itself, as a tab beside Details, rather than at the bottom of the app. Tapping any airport on the map opens it there — a field the fleet is using or one that just happens to be near you — and opens the panel if it was collapsed.
- The position marker pulses: a halo expands out of it and fades on the same cycle as the ring, like a sweep leaving the aircraft. The dot underneath holds its size and colour, so there is always a definite point being indicated.
- The ring is now labelled 50 miles, written just outside it at the one-thirty position.
-
Changed
- Airports inside the ring with nothing standing on them are drawn at a quarter strength, so they read as somewhere you could go rather than somewhere in use. A field with aircraft on it is unchanged.
The location button now shows you what is around you, not just where you are.
-
Added
- Pressing the location button draws a pulsing blue ring at 50 miles around you — dashed, a single pixel wide, breathing slowly — with a faint wash inside it so it reads as an area rather than a line.
- Every airport inside that ring now appears, whether or not anything is parked there. They behave like any other airport on the map: a code when ICAO is on, a plain dot when it is off.
- A field with aircraft on it keeps its usual marker — the nearby ones fill in the gaps rather than replacing anything.
-
Note
- Heliports, seaplane bases and closed fields are left out. Within fifty miles of anywhere busy they outnumber the runways several times over, and the question the ring answers is where an aircraft could go.
- The ring is drawn as a true circle on the ground, so it stays honest near the edge of the globe where the view flattens it into an ellipse.
Jump the map to where you are, and see the rest of the fleet without letting it take over.
-
Added
- A location button on the map sidebar. One press centres the map on you at roughly a 50-mile view. The framing is worked out from the map itself, so 50 miles is 50 miles on a phone and on a tablet alike.
- A ghost button above it. Turned on, every aircraft your filters have hidden still appears — just its tail number, in faint white — so you can see the whole fleet as background without it competing with the aircraft you actually picked.
- Ghosts give way to everything else. Where there is no room beside a real label, the ghost is simply dropped rather than allowed to sit on top of something you asked to see, and they are never tappable.
- Searching for a tail number no longer empties the map: with ghosts on, the rest of the fleet stays visible as context around the one you looked up.
-
Note
- The location button asks permission the first time. If it is refused, or location is switched off, it says so rather than doing nothing.
- The ghost setting is remembered between launches, like the N and ICAO buttons.
- Ghost tail numbers are dark on the light map and light on the dark one. A single fixed colour disappeared into one of the two — the land is drawn white on the light map and almost black on the dark one.
- Ghosts now sit in the same pill as every other label, and can be tapped to open the aircraft — so one the filters hid can be looked at without going back and changing the filters to find it.
- The button is labelled ALL.
- With ALL on, the airports the ghosted aircraft are parked at are drawn too — as a code or a plain dot, whichever the ICAO button is set to. A ghosted tail number sitting over empty ocean with no field named under it looked like a mistake rather than context. A field shared with an aircraft you selected is still drawn once.
- Anything drawn in black now turns white in night mode: landed aircraft, aircraft yet to depart, airport codes and the routes belonging to them. On the dark map those were black on an almost black background, which did not read as subtle so much as missing.
The map remembers whether you wanted tail numbers shown.
-
Fixed
- The N button on the map sidebar now stays as you left it. Turning tail numbers off and closing the app brought them back on the next launch, every time.
- The ICAO button was already being remembered and is unchanged. Both are now stored the same way, so neither can be forgotten while the other is kept.
Aircraft whose landing never gets reported no longer drift across the map forever, and crowded ramps are readable. Needs flight_radar 1.6.0.
-
Changed
- An aircraft in flight is now green rather than blue.
- An aircraft more than an hour past its estimated arrival with no landing reported is now drawn at its destination instead of somewhere along its route. The estimate ignores winds, routing and taxi, so it runs early far more often than an aircraft runs late — after an hour the destination is right almost every time, and wrong in a way you can see. The route line still draws.
- Where several aircraft sit on top of each other — a ramp full of them — their tail numbers now stack into a readable column instead of printing over one another. This deliberately does not happen when the map is showing airport codes instead of tails: ten aircraft at one field all carry the same code, so spreading them would turn one clear answer into ten copies of it.
- The label pill itself is now tappable, not just the aircraft icon — so in a stacked column you can tap the tail you can actually read and get that aircraft's details.
- An aircraft on the ground is now drawn as its airport code in a pill with no aeroplane symbol. On a ramp holding a dozen of them the symbols stacked into an unreadable smear, and what you want from a stationary aircraft is where it is — which the code already says.
- Green now means genuinely airborne: the leg is open and a takeoff time has been posted that has passed. Flightradar24 opens a leg as soon as a flight is filed, so an "estimated" flight with no takeoff time was being painted green while still sitting on a ramp. Those now read orange — expected, not flying.
-
Added
- The Details tab now says what is happening to a flight whose landing never arrived — "No landing reported. Checked 1 of 4 times; next check in 58m." — and, once the service gives up, "Never confirmed. Presumed landed at destination after 4 checks; no longer checking." The row only appears on flights that need it.
Fewer controls, and the map can no longer ask about one snapshot while showing another.
-
Fixed
- The map could show one time in its corner while telling the server it held a different one. The stamp came from inside the downloaded file and the number came from a reply header — two sources for one fact, which drift apart whenever the server is restarted. The number is now worked out from the stamp itself, so what the map displays and what it claims to hold are the same arithmetic on the same value and cannot disagree.
-
Added
- The globe settings panel — the globe icon on the map's toolbar — has a Proposed switch under a new ROUTES heading. Turning it off hides the dashed legs, the ones with no recorded takeoff time, which on a full fleet is most of them and enough to hide the aircraft underneath. The aircraft all stay exactly where they are; only the speculative lines go. The setting is remembered.
- The globe settings popout now closes when you tap anywhere outside it, rather than only on the globe icon that opened it.
-
Changed
- Only NetJets can be selected on the Company tab. The other operators are still listed, greyed out — the server only prepares a fleet file for NetJets, and the rest would have produced a map of aircraft with no flight data behind them.
- The Paid flight data option is gone; the map always uses the subscription feed. It existed so the two feeds could be compared, and the prepared fleet file settled it — turning it off now would mean giving up the whole-fleet download and the one-minute refresh in exchange for a shallower map.
The map keeps itself current every minute, and says on its face how old it is. Needs flight_radar 1.4.2 on the server.
-
Changed
- The map now checks for new data every minute rather than every two. Each check sends back the number of the fleet file it already holds; if the server has the same one, the reply is empty and costs nothing. Only when the number differs does anything come down — so five checks between collections cost about as much as one.
- The countdown restarts from whenever the map last fetched, so tapping Update Map does not leave an automatic check due seconds later.
-
Added
- The date and time the map's data was collected now sits under the UTC
clock in the top-left corner —
MAP 06AUG26 15:24Z. Read against the live clock above it, the gap between the two is how current the map is, without opening the panel to find out. - The Update Map button carries a countdown ring showing when the next automatic check is due, and spins while one is running. The button is now for asking early rather than the only way to get fresh data, and the ring is what says so.
- The date and time the map's data was collected now sits under the UTC
clock in the top-left corner —
Two taps out to a live map, and no more aircraft drawn where they might not be.
-
Added
- Flightradar24 and FlightAware pills beside the tail number on the Details tab. Tap either to open that aircraft in the app if you have it installed, or in the browser if you do not. Flightradar24 goes straight to the flight while it is in the air and to the aircraft's own page otherwise; FlightAware always goes by tail, so the link still works once the leg has ended.
-
Fixed
- An aircraft whose leg has no takeoff time is now drawn at the airport it left, not part-way along its route. Its position was being worked out from the moment the flight was first spotted, which is not a departure time — so a jet could be painted over the middle of the Atlantic on the strength of a number that never meant that. The route still draws, dashed, and the Details tab no longer claims a percentage complete or an estimated landing for those flights.
The map keeps itself up to date, and the filters stop asking the server.
-
Changed
- The prepared fleet file is now what the map runs on rather than a shortcut it sometimes took. The whole roster comes down once — all 878 NetJets aircraft, every type, every country — and the Fleet, U.S.-only and Reg # filters narrow what is already on the phone. Ticking a type is instant and uses no data.
- The map refreshes itself every two minutes instead of waiting to be told. The server rebuilds the file after each five-minute collection, so between collections the refresh is answered with "nothing has changed" and transfers nothing. Update Map is now for asking early, not for keeping current.
- Refreshing no longer swings the globe back to fit every aircraft or covers the map with a spinner — it happens quietly under whatever you were looking at, and the Details tab follows the aircraft it is showing into its new flight.
- Polling stops while the app is in the background and catches up when you come back to it.
- The Fleet tab's
(tracked/total)counts now cover the whole roster, so a type you have unchecked still says how many of it are flying — which is what you wanted to know before checking it.
-
Added
- A line above Update Map saying how much of the fleet is on screen and
how old the data is —
168 of 878 aircraft · data 3m ago— so a map frozen by a dead connection cannot pass for a current one.
- A line above Update Map saying how much of the fleet is on screen and
how old the data is —
-
Fixed
- A route line is now solid only when the feed actually gave a takeoff time and that time has passed; without one it is dashed. Most NetJets legs arrive with no takeoff time at all — the position is worked out from when the flight was first spotted — so those lines were drawn solid while the Details tab showed their takeoff as a dash. Expect far more dashed lines than before: that is the map agreeing with what it knows.
- Selecting an operator the server has no prepared file for alongside one it does no longer hides the first operator's aircraft. Each is now fetched whichever way suits it and the two are shown together.
- Operators with no prepared file are asked for up to 500 aircraft instead of the server's default of 100.
The map now downloads a small prepared file instead of making the server look everything up each time.
-
Changed
- Aircraft positions arrive as a single compressed file that the server prepares once every time it collects new data, rather than the server searching its records afresh for every phone that asks. For the whole NetJets fleet that is 19 KB instead of 265 KB, and it carries all 875 aircraft where the old request stopped at 500.
- Tapping Update Map between collections costs nothing: the app asks whether anything has changed, and is told no in an empty reply. The file is only downloaded again once there is genuinely new data.
- Because the file holds the whole fleet, changing the type or U.S.-only filters no longer needs another download — the app narrows what it already has.
- If the server has no prepared file for an operator, the app quietly falls back to asking the old way, so nothing stops working.
A Zulu clock on the map.
-
Added
- The current UTC date and time run in the top-left corner of the map —
04AUG26 12:34:56Z— so the departure and arrival times can be read against the clock they are quoted in without working out the offset in your head.
- The current UTC date and time run in the top-left corner of the map —
One button to ask the map where everything is.
-
Changed
- The ICAO button now does two jobs. As well as labelling each end of a route, it relabels every parked aircraft with the airport it is standing at — so one tap turns the map from "which aircraft" into "what is where". Aircraft in the air keep their tail number, since the route already names both their airports.
- The days since an aircraft last flew now appear next to the
registration at the top of the Details tab —
N178QS +3d— rather than partway down the list. How stale a position is changes how you read everything below it, so it belongs where the eye lands first.
Stale positions now fade back instead of shouting as loudly as current traffic.
-
Changed
- A landed aircraft is drawn black rather than green. Black now means "on the ground" throughout — both an aircraft that has arrived and one whose departure time has not yet come. The route line tells them apart: only an aircraft yet to leave has one.
- Aircraft fade with age. Two days since the last activity draws them half transparent, three days or more a quarter opaque, so a week-old position no longer competes with an aircraft that flew this morning.
- The day count no longer trails the registration on the map. It is a Last activity line in the Details tab instead, and the fading carries the same information at a glance.
The map now distinguishes a flight that has gone from one that is merely due.
-
Changed
- The route line is solid once the departure time has passed and the aircraft is genuinely away, and stays dashed while the flight is still only expected. At a glance you can tell which aircraft have actually gone.
- The aeroplane symbol turns to face the way it is going, following the curve of the route as drawn rather than a straight compass heading. An aircraft under way is centred on its position; one sitting at an airport still stands on it like a pin.
- Airports on the route are marked by a small dot with their identifier above it, in the colour of the route line. The text is larger than before and sits on a faint wash rather than a solid box, so it stays readable over a coastline without blocking what is underneath.
- The route line itself is thinner and half transparent, so a screen full of aircraft reads as tracks rather than clutter.
- The registration under each aircraft sits on the same faint wash instead of a solid white tag. A busy map used to disappear behind a field of white labels; the globe now shows through them.
- NetJets tails are labelled by their fleet number alone —
N178QSis drawn as178. Every one of them starts N and ends QS, so those four characters told you nothing. Searching and the aircraft list still use the full registration. - An aircraft that is due out but whose departure time has not yet come is drawn black, with its route dashed, so it is distinct from one already under way.
- The button that shows and hides those identifiers is now labelled ICAO rather than carrying a second aeroplane symbol.
- Takeoff and Landing are always listed in the Details tab, showing a dash where the time is not known. Previously the row disappeared, which moved everything below it and left you unsure whether the time was missing or you were looking in the wrong place.
Departure and arrival times, airports on the map, and two new map buttons.
-
Added
- Takeoff and Landing in the Details
tab, in Zulu —
04AUG 0615Z. Where only a planned time is known it says (sched), and for an aircraft still in the air the arrival is worked out from the distance still to run and marked (est). What actually happened is always preferred over what was planned. - The airports at each end of a flight in progress are drawn as a small ring with the ICAO code beside it, so you can see where a flight started and where it is going without opening the details.
- A button on the map's right-hand toolbar to show or hide those airports.
- A second button to switch aircraft between the aeroplane symbol and a plain coloured dot — easier to read when a lot of aircraft are close together. Both settings are remembered between launches.
- Takeoff and Landing in the Details
tab, in Zulu —
-
Fixed
- Flight times are read from the feed's numeric timestamps rather than its text ones. The free data writes times in whatever zone the server is in without saying so, which the app would otherwise have read as local time and shown hours out.
Aircraft in the air are now shown in the air, on the route they are flying.
-
Added
- An aircraft still in the air is drawn blue, with a blue dashed curve along the route it is flying, from the airport it left to the one it is heading for. A landed aircraft stays green and has no curve.
- Rather than sitting on top of an airport, an aircraft in flight is placed along that curve, at roughly where it should have got to given how long it has been airborne. The Details tab reports the same figure — "~58% of route" — and says it is an estimate at 500 mph, because the position is worked out from the departure time and the distance, not reported by the aircraft.
- An aircraft that has been airborne longer than the trip should take is held at its destination rather than drawn sailing past it.
- The From and To airports in the Details tab now name the country as well — "Gimpo International Airport, Seoul, South Korea".
Airport names in the aircraft details.
-
Added
- The Details tab now names both airports underneath the route, as
From and To — so
KPDK → KBKLalso reads "DeKalb Peachtree Airport, Atlanta" and "Burke Lakefront Airport, Cleveland". - The town is added only when the airport's own name does not already contain it, so you get "Van Nuys Airport" rather than "Van Nuys Airport, Van Nuys".
- Names come from the airport database already carried inside the app, so they appear instantly and work with no signal. An airport the database does not recognise is simply left off rather than shown blank.
- The Details tab now names both airports underneath the route, as
From and To — so
Tidier map: the text size slider moved off the map itself.
-
Changed
- The text size slider no longer floats across the top of the map, where it sat over the globe and took up room. It now lives in the globe settings panel on the right — tap the globe button — under a Text heading, below the existing grid controls.
- The chosen text size is now remembered between launches, the same way the grid settings already were. Previously it reset to normal every time the app started.
- The settings panel scrolls if the map area is too short to show all of it, which can happen in landscape with the filter panel open.
The map now runs on the paid Flightradar24 data.
-
Added
- The map draws its aircraft from the paid Flightradar24 data, which tracks flights still in the air and knows where a flight actually ended up when it diverts, rather than only where it was headed.
- A Paid flight data switch on the map's Options tab. It is on to begin with. Turning it off puts the map back on the free data, which reaches further back in time. The choice is remembered between launches, and the map redraws as soon as it is changed.
-
Fixed
- The "days since" figure beside an aircraft was out by however many hours separate the server's clock from UTC, because the free data gives times without saying which zone they are in. The paid data states UTC, so the figure is now right.
Earlier releases; changes were not recorded at the time.