avios-cli 0.4.3__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {avios_cli-0.4.3 → avios_cli-0.5.0}/CHANGELOG.md +49 -0
  2. {avios_cli-0.4.3 → avios_cli-0.5.0}/PKG-INFO +19 -13
  3. {avios_cli-0.4.3 → avios_cli-0.5.0}/README.md +17 -11
  4. avios_cli-0.5.0/docs/dashboard.svg +216 -0
  5. {avios_cli-0.4.3 → avios_cli-0.5.0}/docs/reward-flights.svg +107 -106
  6. {avios_cli-0.4.3 → avios_cli-0.5.0}/scripts/screenshot.py +9 -3
  7. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/__init__.py +1 -1
  8. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/cli.py +72 -23
  9. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/client.py +27 -4
  10. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/config.py +3 -1
  11. avios_cli-0.5.0/src/avios/rewards.py +1396 -0
  12. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/session.py +19 -0
  13. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/tui/rewards.py +46 -22
  14. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/conftest.py +3 -0
  15. avios_cli-0.5.0/tests/fixtures/reward_search.rsc +6 -0
  16. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_cli.py +160 -69
  17. avios_cli-0.5.0/tests/test_rewards.py +711 -0
  18. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_tui.py +80 -21
  19. avios_cli-0.4.3/docs/dashboard.svg +0 -216
  20. avios_cli-0.4.3/src/avios/rewards.py +0 -530
  21. avios_cli-0.4.3/tests/fixtures/reward_search.rsc +0 -3
  22. avios_cli-0.4.3/tests/test_rewards.py +0 -324
  23. {avios_cli-0.4.3 → avios_cli-0.5.0}/.editorconfig +0 -0
  24. {avios_cli-0.4.3 → avios_cli-0.5.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  25. {avios_cli-0.4.3 → avios_cli-0.5.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  26. {avios_cli-0.4.3 → avios_cli-0.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  27. {avios_cli-0.4.3 → avios_cli-0.5.0}/.github/dependabot.yml +0 -0
  28. {avios_cli-0.4.3 → avios_cli-0.5.0}/.github/workflows/ci.yml +0 -0
  29. {avios_cli-0.4.3 → avios_cli-0.5.0}/.github/workflows/publish.yml +0 -0
  30. {avios_cli-0.4.3 → avios_cli-0.5.0}/.gitignore +0 -0
  31. {avios_cli-0.4.3 → avios_cli-0.5.0}/.pre-commit-config.yaml +0 -0
  32. {avios_cli-0.4.3 → avios_cli-0.5.0}/.python-version +0 -0
  33. {avios_cli-0.4.3 → avios_cli-0.5.0}/CONTRIBUTING.md +0 -0
  34. {avios_cli-0.4.3 → avios_cli-0.5.0}/LICENSE +0 -0
  35. {avios_cli-0.4.3 → avios_cli-0.5.0}/SECURITY.md +0 -0
  36. {avios_cli-0.4.3 → avios_cli-0.5.0}/pyproject.toml +0 -0
  37. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/accounts.py +0 -0
  38. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/aggregate.py +0 -0
  39. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/auth.py +0 -0
  40. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/endpoints.py +0 -0
  41. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/finnair.py +0 -0
  42. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/models.py +0 -0
  43. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/programmes.py +0 -0
  44. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/tui/__init__.py +0 -0
  45. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/tui/app.py +0 -0
  46. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/tui/art.py +0 -0
  47. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/tui/styles.tcss +0 -0
  48. {avios_cli-0.4.3 → avios_cli-0.5.0}/src/avios/tui/widgets.py +0 -0
  49. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/fixtures/balance.json +0 -0
  50. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/fixtures/transactions.json +0 -0
  51. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_accounts.py +0 -0
  52. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_aggregate.py +0 -0
  53. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_auth.py +0 -0
  54. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_client.py +0 -0
  55. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_finnair.py +0 -0
  56. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_models.py +0 -0
  57. {avios_cli-0.4.3 → avios_cli-0.5.0}/tests/test_session.py +0 -0
  58. {avios_cli-0.4.3 → avios_cli-0.5.0}/uv.lock +0 -0
@@ -6,6 +6,55 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.5.0] - 2026-08-11
10
+
11
+ ### Fixed
12
+ - **BA reward-flight search returned nothing after British Airways rebuilt the
13
+ flight finder.** The new Next.js app moved each day's flights one level deeper
14
+ (`departureJourneys.<date>.journeys[].flights[]` instead of
15
+ `departureJourneys.<date>.flights[]`), so every day parsed as empty. Availability
16
+ parsing now follows the new shape, and the old flat shape still parses if BA
17
+ rolls back.
18
+ - **Business-class seats were always reported as zero.** BA's availability rows use
19
+ cabin code `J`; the client only looked for `C`. Both are now recognised, matching
20
+ the site's own `cabinClassCodeMap`.
21
+ - The request contract was re-derived from a live capture and is now reproduced
22
+ byte for byte — query parameters, both `next-router-state-tree` variants, `rsc`,
23
+ `next-url`, `accept`, and the full browser header set. A user-agent that
24
+ disagreed with the `sec-ch-ua` client hints (Chrome 126 vs 148) is fixed, since
25
+ the mismatch is itself a bot signal.
26
+
27
+ ### Added
28
+ - **Avios prices.** Searching an exact `--date` now calls the finder's
29
+ `fetchPricingAction` server action and shows the Avios cost per cabin for your
30
+ party, in both the CLI table and the TUI. Calendar (month) searches stay
31
+ seats-only so they remain one request per leg.
32
+ - Exact-date searches also re-read that date through
33
+ `getFlightResultsForSingleJourneyAction`, exactly as the website does when you
34
+ click a day, so seat counts are fresh rather than served from the month cache.
35
+ - Seats that only sell against a BA companion voucher (Business `rbd: I`) are
36
+ marked `†` instead of being counted as general availability.
37
+ - `AviosClient.search_reward_legs()` searches every leg of a trip over **one**
38
+ browser session, and reports failures per leg so one bad leg does not lose the
39
+ other. The CLI and TUI both use it.
40
+ - Akamai denials are now distinguished from an expired session: a bot-manager 403
41
+ or a 429 raises `RewardSearchBlockedError` telling you to wait and switch
42
+ network, rather than sending you to log in again.
43
+
44
+ ### Changed
45
+ - **Reward searches make far fewer requests.** Previously each leg launched its own
46
+ Chrome, navigated to the finder, and drove the search form. A search now warms
47
+ one browser navigation and issues in-page `fetch()` calls for everything after
48
+ it — a return trip costs one navigation and two fetches — with pacing between
49
+ requests. British Airways blocks by IP address, and page loads were what
50
+ triggered it.
51
+ - One availability request now returns the whole 13-month booking window, so an
52
+ out-of-range month reports the window BA actually offers.
53
+ - Dates beyond BA's rolling booking horizon are recognised (`availabilityLevel: 3`)
54
+ and no longer render as "no reward seats".
55
+ - `flights --json` reports days as `journeys[].flights[]`, following the upstream
56
+ shape, and includes the `price` attached to each cabin.
57
+
9
58
  ## [0.4.3] - 2026-07-27
10
59
 
11
60
  ### Changed
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: avios-cli
3
- Version: 0.4.3
3
+ Version: 0.5.0
4
4
  Summary: A CLI and TUI for Avios balances, transactions, and BA reward-flight availability.
5
5
  Project-URL: Homepage, https://github.com/alexechoi/avios-cli
6
6
  Project-URL: Repository, https://github.com/alexechoi/avios-cli
@@ -130,10 +130,12 @@ Each programme session is stored at `~/.config/avios/accounts/<programme>.json`
130
130
  `avios logout <programme>` for one account or `avios logout` for all accounts.
131
131
  For BA, browser-assisted login also opens the separate reward-flight application.
132
132
  British Airways may show a second login prompt; keep the browser open until the
133
- CLI confirms success. Reward searches drive the site's own form in a background
134
- Chrome window because the flight-search route rejects plain HTTP and automated
135
- headless requests, so the `login` extra remains required when running
136
- `avios flights` or the Reward Flights TUI tab.
133
+ CLI confirms success. Reward searches run inside a background Chrome window: the
134
+ flight finder is behind Akamai Bot Manager, which rejects plain HTTP clients and
135
+ **blocks by IP address** — a handful of ordinary page loads from a shared office
136
+ network is enough to earn a site-wide 403. Every leg of a search is therefore
137
+ batched through a single browser navigation, paced, and served by in-page
138
+ `fetch()` calls. If you do get blocked, wait a few minutes and switch network.
137
139
 
138
140
  ## Usage
139
141
 
@@ -150,9 +152,9 @@ avios overview # dashboard summary
150
152
  avios whoami # name, tier, membership, email
151
153
  avios raw /shell/api/users/current/accounts # hit any endpoint directly
152
154
 
153
- # Direct British Airways reward-seat availability:
154
- avios flights LON ABZ --date 2026-11-05
155
- avios flights LON ABZ --date 2026-11-05 --return-date 2026-11-12
155
+ # Direct British Airways reward-seat availability (--date also prices in Avios):
156
+ avios flights LON HKG --date 2027-01-05
157
+ avios flights LON HKG --date 2027-01-05 --return-date 2027-01-12
156
158
  avios flights LON ABZ --month 2026-11 --cabin economy --cabin business
157
159
  avios flights LON ABZ --month 2026-11 --return-month 2026-12 --json
158
160
  ```
@@ -176,10 +178,13 @@ A tabbed full-screen application:
176
178
  Press `r` to refresh the dashboard and `q` to quit. Reward searches run only when
177
179
  you press Search or Enter.
178
180
 
179
- Reward search is an unofficial, availability-only view. It currently supports
180
- direct BA flights, three-letter airport/city codes, and seat counts by cabin. It
181
- does not price, book, or show taxes/fees or connecting flights. Return journeys
182
- are two independent one-way searches.
181
+ Reward search is an unofficial view of BA's own flight finder. It supports direct
182
+ BA flights, three-letter airport/city codes, and seat counts by cabin. Searching
183
+ an exact `--date` also fetches the Avios price per cabin for your party; calendar
184
+ (month) searches show seats only, which keeps them to one request per leg. Seats
185
+ that need a BA companion voucher are marked `†`. It does not book, and it does
186
+ not show taxes/fees or connecting flights. Return journeys are two reverse-route
187
+ one-way searches sharing one browser session.
183
188
 
184
189
  ## Roadmap
185
190
 
@@ -191,6 +196,7 @@ are two independent one-way searches.
191
196
  - [x] Textual TUI dashboard
192
197
  - [x] Multiple accounts (BA, Iberia, Aer Lingus, Finnair) with combined views
193
198
  - [x] British Airways reward-flight **availability** search (CLI + TUI)
199
+ - [x] Avios pricing per cabin for an exact date
194
200
 
195
201
  ## Development
196
202
 
@@ -95,10 +95,12 @@ Each programme session is stored at `~/.config/avios/accounts/<programme>.json`
95
95
  `avios logout <programme>` for one account or `avios logout` for all accounts.
96
96
  For BA, browser-assisted login also opens the separate reward-flight application.
97
97
  British Airways may show a second login prompt; keep the browser open until the
98
- CLI confirms success. Reward searches drive the site's own form in a background
99
- Chrome window because the flight-search route rejects plain HTTP and automated
100
- headless requests, so the `login` extra remains required when running
101
- `avios flights` or the Reward Flights TUI tab.
98
+ CLI confirms success. Reward searches run inside a background Chrome window: the
99
+ flight finder is behind Akamai Bot Manager, which rejects plain HTTP clients and
100
+ **blocks by IP address** — a handful of ordinary page loads from a shared office
101
+ network is enough to earn a site-wide 403. Every leg of a search is therefore
102
+ batched through a single browser navigation, paced, and served by in-page
103
+ `fetch()` calls. If you do get blocked, wait a few minutes and switch network.
102
104
 
103
105
  ## Usage
104
106
 
@@ -115,9 +117,9 @@ avios overview # dashboard summary
115
117
  avios whoami # name, tier, membership, email
116
118
  avios raw /shell/api/users/current/accounts # hit any endpoint directly
117
119
 
118
- # Direct British Airways reward-seat availability:
119
- avios flights LON ABZ --date 2026-11-05
120
- avios flights LON ABZ --date 2026-11-05 --return-date 2026-11-12
120
+ # Direct British Airways reward-seat availability (--date also prices in Avios):
121
+ avios flights LON HKG --date 2027-01-05
122
+ avios flights LON HKG --date 2027-01-05 --return-date 2027-01-12
121
123
  avios flights LON ABZ --month 2026-11 --cabin economy --cabin business
122
124
  avios flights LON ABZ --month 2026-11 --return-month 2026-12 --json
123
125
  ```
@@ -141,10 +143,13 @@ A tabbed full-screen application:
141
143
  Press `r` to refresh the dashboard and `q` to quit. Reward searches run only when
142
144
  you press Search or Enter.
143
145
 
144
- Reward search is an unofficial, availability-only view. It currently supports
145
- direct BA flights, three-letter airport/city codes, and seat counts by cabin. It
146
- does not price, book, or show taxes/fees or connecting flights. Return journeys
147
- are two independent one-way searches.
146
+ Reward search is an unofficial view of BA's own flight finder. It supports direct
147
+ BA flights, three-letter airport/city codes, and seat counts by cabin. Searching
148
+ an exact `--date` also fetches the Avios price per cabin for your party; calendar
149
+ (month) searches show seats only, which keeps them to one request per leg. Seats
150
+ that need a BA companion voucher are marked `†`. It does not book, and it does
151
+ not show taxes/fees or connecting flights. Return journeys are two reverse-route
152
+ one-way searches sharing one browser session.
148
153
 
149
154
  ## Roadmap
150
155
 
@@ -156,6 +161,7 @@ are two independent one-way searches.
156
161
  - [x] Textual TUI dashboard
157
162
  - [x] Multiple accounts (BA, Iberia, Aer Lingus, Finnair) with combined views
158
163
  - [x] British Airways reward-flight **availability** search (CLI + TUI)
164
+ - [x] Avios pricing per cabin for an exact date
159
165
 
160
166
  ## Development
161
167
 
@@ -0,0 +1,216 @@
1
+ <svg class="rich-terminal" viewBox="0 0 1190 928.4" xmlns="http://www.w3.org/2000/svg">
2
+ <!-- Generated with Rich https://www.textualize.io -->
3
+ <style>
4
+
5
+ @font-face {
6
+ font-family: "Fira Code";
7
+ src: local("FiraCode-Regular"),
8
+ url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
9
+ url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
10
+ font-style: normal;
11
+ font-weight: 400;
12
+ }
13
+ @font-face {
14
+ font-family: "Fira Code";
15
+ src: local("FiraCode-Bold"),
16
+ url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
17
+ url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
18
+ font-style: bold;
19
+ font-weight: 700;
20
+ }
21
+
22
+ .terminal-3444994516-matrix {
23
+ font-family: Fira Code, monospace;
24
+ font-size: 20px;
25
+ line-height: 24.4px;
26
+ font-variant-east-asian: full-width;
27
+ }
28
+
29
+ .terminal-3444994516-title {
30
+ font-size: 18px;
31
+ font-weight: bold;
32
+ font-family: arial;
33
+ }
34
+
35
+ .terminal-3444994516-r1 { fill: #c5c8c6 }
36
+ .terminal-3444994516-r2 { fill: #e0e0e0 }
37
+ .terminal-3444994516-r3 { fill: #a0a3a6 }
38
+ .terminal-3444994516-r4 { fill: #c5c6c7 }
39
+ .terminal-3444994516-r5 { fill: #00d7af;font-weight: bold }
40
+ .terminal-3444994516-r6 { fill: #00d7d7;font-weight: bold }
41
+ .terminal-3444994516-r7 { fill: #00afd7;font-weight: bold }
42
+ .terminal-3444994516-r8 { fill: #0087d7;font-weight: bold }
43
+ .terminal-3444994516-r9 { fill: #005fd7;font-weight: bold }
44
+ .terminal-3444994516-r10 { fill: #5f5fd7;font-weight: bold }
45
+ .terminal-3444994516-r11 { fill: #9e9e9e;font-style: italic; }
46
+ .terminal-3444994516-r12 { fill: #ddedf9;font-weight: bold }
47
+ .terminal-3444994516-r13 { fill: #7f7f7f }
48
+ .terminal-3444994516-r14 { fill: #585858 }
49
+ .terminal-3444994516-r15 { fill: #0178d4 }
50
+ .terminal-3444994516-r16 { fill: #e0e0e0;font-weight: bold }
51
+ .terminal-3444994516-r17 { fill: #58d1eb;font-weight: bold }
52
+ .terminal-3444994516-r18 { fill: #9e9e9e }
53
+ .terminal-3444994516-r19 { fill: #ffa62b;font-weight: bold }
54
+ .terminal-3444994516-r20 { fill: #495259 }
55
+ </style>
56
+
57
+ <defs>
58
+ <clipPath id="terminal-3444994516-clip-terminal">
59
+ <rect x="0" y="0" width="1170.1999999999998" height="877.4" />
60
+ </clipPath>
61
+ <clipPath id="terminal-3444994516-line-0">
62
+ <rect x="0" y="1.5" width="1171.2" height="24.65"/>
63
+ </clipPath>
64
+ <clipPath id="terminal-3444994516-line-1">
65
+ <rect x="0" y="25.9" width="1171.2" height="24.65"/>
66
+ </clipPath>
67
+ <clipPath id="terminal-3444994516-line-2">
68
+ <rect x="0" y="50.3" width="1171.2" height="24.65"/>
69
+ </clipPath>
70
+ <clipPath id="terminal-3444994516-line-3">
71
+ <rect x="0" y="74.7" width="1171.2" height="24.65"/>
72
+ </clipPath>
73
+ <clipPath id="terminal-3444994516-line-4">
74
+ <rect x="0" y="99.1" width="1171.2" height="24.65"/>
75
+ </clipPath>
76
+ <clipPath id="terminal-3444994516-line-5">
77
+ <rect x="0" y="123.5" width="1171.2" height="24.65"/>
78
+ </clipPath>
79
+ <clipPath id="terminal-3444994516-line-6">
80
+ <rect x="0" y="147.9" width="1171.2" height="24.65"/>
81
+ </clipPath>
82
+ <clipPath id="terminal-3444994516-line-7">
83
+ <rect x="0" y="172.3" width="1171.2" height="24.65"/>
84
+ </clipPath>
85
+ <clipPath id="terminal-3444994516-line-8">
86
+ <rect x="0" y="196.7" width="1171.2" height="24.65"/>
87
+ </clipPath>
88
+ <clipPath id="terminal-3444994516-line-9">
89
+ <rect x="0" y="221.1" width="1171.2" height="24.65"/>
90
+ </clipPath>
91
+ <clipPath id="terminal-3444994516-line-10">
92
+ <rect x="0" y="245.5" width="1171.2" height="24.65"/>
93
+ </clipPath>
94
+ <clipPath id="terminal-3444994516-line-11">
95
+ <rect x="0" y="269.9" width="1171.2" height="24.65"/>
96
+ </clipPath>
97
+ <clipPath id="terminal-3444994516-line-12">
98
+ <rect x="0" y="294.3" width="1171.2" height="24.65"/>
99
+ </clipPath>
100
+ <clipPath id="terminal-3444994516-line-13">
101
+ <rect x="0" y="318.7" width="1171.2" height="24.65"/>
102
+ </clipPath>
103
+ <clipPath id="terminal-3444994516-line-14">
104
+ <rect x="0" y="343.1" width="1171.2" height="24.65"/>
105
+ </clipPath>
106
+ <clipPath id="terminal-3444994516-line-15">
107
+ <rect x="0" y="367.5" width="1171.2" height="24.65"/>
108
+ </clipPath>
109
+ <clipPath id="terminal-3444994516-line-16">
110
+ <rect x="0" y="391.9" width="1171.2" height="24.65"/>
111
+ </clipPath>
112
+ <clipPath id="terminal-3444994516-line-17">
113
+ <rect x="0" y="416.3" width="1171.2" height="24.65"/>
114
+ </clipPath>
115
+ <clipPath id="terminal-3444994516-line-18">
116
+ <rect x="0" y="440.7" width="1171.2" height="24.65"/>
117
+ </clipPath>
118
+ <clipPath id="terminal-3444994516-line-19">
119
+ <rect x="0" y="465.1" width="1171.2" height="24.65"/>
120
+ </clipPath>
121
+ <clipPath id="terminal-3444994516-line-20">
122
+ <rect x="0" y="489.5" width="1171.2" height="24.65"/>
123
+ </clipPath>
124
+ <clipPath id="terminal-3444994516-line-21">
125
+ <rect x="0" y="513.9" width="1171.2" height="24.65"/>
126
+ </clipPath>
127
+ <clipPath id="terminal-3444994516-line-22">
128
+ <rect x="0" y="538.3" width="1171.2" height="24.65"/>
129
+ </clipPath>
130
+ <clipPath id="terminal-3444994516-line-23">
131
+ <rect x="0" y="562.7" width="1171.2" height="24.65"/>
132
+ </clipPath>
133
+ <clipPath id="terminal-3444994516-line-24">
134
+ <rect x="0" y="587.1" width="1171.2" height="24.65"/>
135
+ </clipPath>
136
+ <clipPath id="terminal-3444994516-line-25">
137
+ <rect x="0" y="611.5" width="1171.2" height="24.65"/>
138
+ </clipPath>
139
+ <clipPath id="terminal-3444994516-line-26">
140
+ <rect x="0" y="635.9" width="1171.2" height="24.65"/>
141
+ </clipPath>
142
+ <clipPath id="terminal-3444994516-line-27">
143
+ <rect x="0" y="660.3" width="1171.2" height="24.65"/>
144
+ </clipPath>
145
+ <clipPath id="terminal-3444994516-line-28">
146
+ <rect x="0" y="684.7" width="1171.2" height="24.65"/>
147
+ </clipPath>
148
+ <clipPath id="terminal-3444994516-line-29">
149
+ <rect x="0" y="709.1" width="1171.2" height="24.65"/>
150
+ </clipPath>
151
+ <clipPath id="terminal-3444994516-line-30">
152
+ <rect x="0" y="733.5" width="1171.2" height="24.65"/>
153
+ </clipPath>
154
+ <clipPath id="terminal-3444994516-line-31">
155
+ <rect x="0" y="757.9" width="1171.2" height="24.65"/>
156
+ </clipPath>
157
+ <clipPath id="terminal-3444994516-line-32">
158
+ <rect x="0" y="782.3" width="1171.2" height="24.65"/>
159
+ </clipPath>
160
+ <clipPath id="terminal-3444994516-line-33">
161
+ <rect x="0" y="806.7" width="1171.2" height="24.65"/>
162
+ </clipPath>
163
+ <clipPath id="terminal-3444994516-line-34">
164
+ <rect x="0" y="831.1" width="1171.2" height="24.65"/>
165
+ </clipPath>
166
+ </defs>
167
+
168
+ <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1188" height="926.4" rx="8"/><text class="terminal-3444994516-title" fill="#c5c8c6" text-anchor="middle" x="594" y="27">avios</text>
169
+ <g transform="translate(26,22)">
170
+ <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
171
+ <circle cx="22" cy="0" r="7" fill="#febc2e"/>
172
+ <circle cx="44" cy="0" r="7" fill="#28c840"/>
173
+ </g>
174
+
175
+ <g transform="translate(9, 41)" clip-path="url(#terminal-3444994516-clip-terminal)">
176
+ <rect fill="#242f38" x="0" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="12.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="24.4" y="1.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="85.4" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="97.6" y="1.5" width="256.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="353.8" y="1.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="414.8" y="1.5" width="36.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="451.4" y="1.5" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="780.8" y="1.5" width="268.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2c363f" x="1049.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2c363f" x="1061.4" y="1.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#2c363f" x="1159" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="25.9" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="50.3" width="353.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="50.3" width="451.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="805.2" y="50.3" width="366" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="353.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="74.7" width="451.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="805.2" y="74.7" width="366" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="353.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="99.1" width="451.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="805.2" y="99.1" width="366" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="353.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="123.5" width="451.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="805.2" y="123.5" width="366" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="353.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="147.9" width="451.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="805.2" y="147.9" width="366" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="353.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="172.3" width="451.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="805.2" y="172.3" width="366" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="402.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="402.6" y="196.7" width="366" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="768.6" y="196.7" width="402.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="0" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="12.2" y="221.1" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#0178d4" x="122" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="134.2" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="146.4" y="221.1" width="170.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="317.2" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="329.4" y="221.1" width="841.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="12.2" y="245.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="122" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="134.2" y="245.5" width="1037" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="24.4" y="269.9" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="146.4" y="269.9" width="85.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="231.8" y="269.9" width="902.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1134.6" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1146.8" y="269.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="24.4" y="294.3" width="219.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="244" y="294.3" width="902.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="1146.8" y="294.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="0" y="343.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="207.4" y="343.1" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="353.8" y="343.1" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="671" y="343.1" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="780.8" y="343.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="988.2" y="343.1" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#153854" x="0" y="367.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#153854" x="207.4" y="367.5" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#153854" x="353.8" y="367.5" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#153854" x="671" y="367.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#153854" x="780.8" y="367.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#153854" x="988.2" y="367.5" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="207.4" y="391.9" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="391.9" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="671" y="391.9" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="780.8" y="391.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="988.2" y="391.9" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="0" y="416.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="207.4" y="416.3" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="353.8" y="416.3" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="671" y="416.3" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="780.8" y="416.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="988.2" y="416.3" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="207.4" y="440.7" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="440.7" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="671" y="440.7" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="780.8" y="440.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="988.2" y="440.7" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="0" y="465.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="207.4" y="465.1" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="353.8" y="465.1" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="671" y="465.1" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="780.8" y="465.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="988.2" y="465.1" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="207.4" y="489.5" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="489.5" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="671" y="489.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="780.8" y="489.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="988.2" y="489.5" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="0" y="513.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="207.4" y="513.9" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="353.8" y="513.9" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="671" y="513.9" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="780.8" y="513.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="988.2" y="513.9" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="207.4" y="538.3" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="353.8" y="538.3" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="671" y="538.3" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="780.8" y="538.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="988.2" y="538.3" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="0" y="562.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="207.4" y="562.7" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="353.8" y="562.7" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="671" y="562.7" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="780.8" y="562.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="988.2" y="562.7" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="587.1" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="611.5" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="635.9" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="660.3" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="684.7" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="709.1" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="733.5" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="757.9" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="782.3" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="806.7" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="831.1" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="0" y="855.5" width="36.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="36.6" y="855.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="134.2" y="855.5" width="36.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="170.8" y="855.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="231.8" y="855.5" width="793" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="1024.8" y="855.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="1037" y="855.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="1061.4" y="855.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#242f38" x="1159" y="855.5" width="12.2" height="24.65" shape-rendering="crispEdges"/>
177
+ <g class="terminal-3444994516-matrix">
178
+ <text class="terminal-3444994516-r2" x="12.2" y="20" textLength="12.2" clip-path="url(#terminal-3444994516-line-0)">⭘</text><text class="terminal-3444994516-r2" x="353.8" y="20" textLength="61" clip-path="url(#terminal-3444994516-line-0)">avios</text><text class="terminal-3444994516-r3" x="414.8" y="20" textLength="36.6" clip-path="url(#terminal-3444994516-line-0)">&#160;—&#160;</text><text class="terminal-3444994516-r3" x="451.4" y="20" textLength="329.4" clip-path="url(#terminal-3444994516-line-0)">your&#160;Avios,&#160;in&#160;the&#160;terminal</text><text class="terminal-3444994516-r4" x="1061.4" y="20" textLength="97.6" clip-path="url(#terminal-3444994516-line-0)">16:55:52</text><text class="terminal-3444994516-r1" x="1171.2" y="20" textLength="12.2" clip-path="url(#terminal-3444994516-line-0)">
179
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="44.4" textLength="12.2" clip-path="url(#terminal-3444994516-line-1)">
180
+ </text><text class="terminal-3444994516-r5" x="353.8" y="68.8" textLength="451.4" clip-path="url(#terminal-3444994516-line-2)">&#160;█████╗&#160;██╗&#160;&#160;&#160;██╗██╗&#160;██████╗&#160;███████╗</text><text class="terminal-3444994516-r1" x="1171.2" y="68.8" textLength="12.2" clip-path="url(#terminal-3444994516-line-2)">
181
+ </text><text class="terminal-3444994516-r6" x="353.8" y="93.2" textLength="451.4" clip-path="url(#terminal-3444994516-line-3)">██╔══██╗██║&#160;&#160;&#160;██║██║██╔═══██╗██╔════╝</text><text class="terminal-3444994516-r1" x="1171.2" y="93.2" textLength="12.2" clip-path="url(#terminal-3444994516-line-3)">
182
+ </text><text class="terminal-3444994516-r7" x="353.8" y="117.6" textLength="451.4" clip-path="url(#terminal-3444994516-line-4)">███████║██║&#160;&#160;&#160;██║██║██║&#160;&#160;&#160;██║███████╗</text><text class="terminal-3444994516-r1" x="1171.2" y="117.6" textLength="12.2" clip-path="url(#terminal-3444994516-line-4)">
183
+ </text><text class="terminal-3444994516-r8" x="353.8" y="142" textLength="451.4" clip-path="url(#terminal-3444994516-line-5)">██╔══██║╚██╗&#160;██╔╝██║██║&#160;&#160;&#160;██║╚════██║</text><text class="terminal-3444994516-r1" x="1171.2" y="142" textLength="12.2" clip-path="url(#terminal-3444994516-line-5)">
184
+ </text><text class="terminal-3444994516-r9" x="353.8" y="166.4" textLength="451.4" clip-path="url(#terminal-3444994516-line-6)">██║&#160;&#160;██║&#160;╚████╔╝&#160;██║╚██████╔╝███████║</text><text class="terminal-3444994516-r1" x="1171.2" y="166.4" textLength="12.2" clip-path="url(#terminal-3444994516-line-6)">
185
+ </text><text class="terminal-3444994516-r10" x="353.8" y="190.8" textLength="451.4" clip-path="url(#terminal-3444994516-line-7)">╚═╝&#160;&#160;╚═╝&#160;&#160;╚═══╝&#160;&#160;╚═╝&#160;╚═════╝&#160;╚══════╝</text><text class="terminal-3444994516-r1" x="1171.2" y="190.8" textLength="12.2" clip-path="url(#terminal-3444994516-line-7)">
186
+ </text><text class="terminal-3444994516-r11" x="402.6" y="215.2" textLength="366" clip-path="url(#terminal-3444994516-line-8)">✈&#160;&#160;your&#160;Avios,&#160;in&#160;the&#160;terminal</text><text class="terminal-3444994516-r1" x="1171.2" y="215.2" textLength="12.2" clip-path="url(#terminal-3444994516-line-8)">
187
+ </text><text class="terminal-3444994516-r12" x="12.2" y="239.6" textLength="109.8" clip-path="url(#terminal-3444994516-line-9)">Dashboard</text><text class="terminal-3444994516-r13" x="146.4" y="239.6" textLength="170.8" clip-path="url(#terminal-3444994516-line-9)">Reward&#160;Flights</text><text class="terminal-3444994516-r1" x="1171.2" y="239.6" textLength="12.2" clip-path="url(#terminal-3444994516-line-9)">
188
+ </text><text class="terminal-3444994516-r14" x="0" y="264" textLength="12.2" clip-path="url(#terminal-3444994516-line-10)">╸</text><text class="terminal-3444994516-r15" x="12.2" y="264" textLength="109.8" clip-path="url(#terminal-3444994516-line-10)">━━━━━━━━━</text><text class="terminal-3444994516-r14" x="122" y="264" textLength="12.2" clip-path="url(#terminal-3444994516-line-10)">╺</text><text class="terminal-3444994516-r14" x="134.2" y="264" textLength="1037" clip-path="url(#terminal-3444994516-line-10)">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text class="terminal-3444994516-r1" x="1171.2" y="264" textLength="12.2" clip-path="url(#terminal-3444994516-line-10)">
189
+ </text><text class="terminal-3444994516-r16" x="24.4" y="288.4" textLength="122" clip-path="url(#terminal-3444994516-line-11)">Combined&#160;&#160;</text><text class="terminal-3444994516-r17" x="146.4" y="288.4" textLength="85.4" clip-path="url(#terminal-3444994516-line-11)">115,211</text><text class="terminal-3444994516-r18" x="231.8" y="288.4" textLength="902.8" clip-path="url(#terminal-3444994516-line-11)">&#160;&#160;&#160;&#160;&#160;British&#160;Airways&#160;75,751&#160;&#160;&#160;·&#160;&#160;&#160;Iberia&#160;22,040&#160;&#160;&#160;·&#160;&#160;&#160;Aer&#160;Lingus&#160;8,300&#160;&#160;&#160;·</text><text class="terminal-3444994516-r1" x="1171.2" y="288.4" textLength="12.2" clip-path="url(#terminal-3444994516-line-11)">
190
+ </text><text class="terminal-3444994516-r18" x="24.4" y="312.8" textLength="219.6" clip-path="url(#terminal-3444994516-line-12)">Finnair&#160;Plus&#160;9,120</text><text class="terminal-3444994516-r1" x="1171.2" y="312.8" textLength="12.2" clip-path="url(#terminal-3444994516-line-12)">
191
+ </text><text class="terminal-3444994516-r15" x="0" y="337.2" textLength="1171.2" clip-path="url(#terminal-3444994516-line-13)">────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-3444994516-r1" x="1171.2" y="337.2" textLength="12.2" clip-path="url(#terminal-3444994516-line-13)">
192
+ </text><text class="terminal-3444994516-r16" x="0" y="361.6" textLength="207.4" clip-path="url(#terminal-3444994516-line-14)">&#160;Programme&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r16" x="207.4" y="361.6" textLength="146.4" clip-path="url(#terminal-3444994516-line-14)">&#160;Date&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r16" x="353.8" y="361.6" textLength="317.2" clip-path="url(#terminal-3444994516-line-14)">&#160;Description&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r16" x="671" y="361.6" textLength="109.8" clip-path="url(#terminal-3444994516-line-14)">&#160;Avios&#160;&#160;&#160;</text><text class="terminal-3444994516-r16" x="780.8" y="361.6" textLength="207.4" clip-path="url(#terminal-3444994516-line-14)">&#160;Type&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="361.6" textLength="12.2" clip-path="url(#terminal-3444994516-line-14)">
193
+ </text><text class="terminal-3444994516-r2" x="0" y="386" textLength="207.4" clip-path="url(#terminal-3444994516-line-15)">&#160;Finnair&#160;Plus&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="386" textLength="146.4" clip-path="url(#terminal-3444994516-line-15)">&#160;2026-07-20&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="386" textLength="317.2" clip-path="url(#terminal-3444994516-line-15)">&#160;Finnair&#160;AY1337&#160;HEL-LHR&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="671" y="386" textLength="109.8" clip-path="url(#terminal-3444994516-line-15)">&#160;+3,100&#160;&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="386" textLength="207.4" clip-path="url(#terminal-3444994516-line-15)">&#160;Flight&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="386" textLength="12.2" clip-path="url(#terminal-3444994516-line-15)">
194
+ </text><text class="terminal-3444994516-r2" x="0" y="410.4" textLength="207.4" clip-path="url(#terminal-3444994516-line-16)">&#160;British&#160;Airways&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="410.4" textLength="146.4" clip-path="url(#terminal-3444994516-line-16)">&#160;2026-07-18&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="410.4" textLength="317.2" clip-path="url(#terminal-3444994516-line-16)">&#160;Flight&#160;BA286&#160;SFO-LHR&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="671" y="410.4" textLength="109.8" clip-path="url(#terminal-3444994516-line-16)">&#160;+8,500&#160;&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="410.4" textLength="207.4" clip-path="url(#terminal-3444994516-line-16)">&#160;Collection&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="410.4" textLength="12.2" clip-path="url(#terminal-3444994516-line-16)">
195
+ </text><text class="terminal-3444994516-r2" x="0" y="434.8" textLength="207.4" clip-path="url(#terminal-3444994516-line-17)">&#160;Aer&#160;Lingus&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="434.8" textLength="146.4" clip-path="url(#terminal-3444994516-line-17)">&#160;2026-07-15&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="434.8" textLength="317.2" clip-path="url(#terminal-3444994516-line-17)">&#160;Aer&#160;Lingus&#160;EI154&#160;DUB-LHR&#160;</text><text class="terminal-3444994516-r2" x="671" y="434.8" textLength="109.8" clip-path="url(#terminal-3444994516-line-17)">&#160;+1,900&#160;&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="434.8" textLength="207.4" clip-path="url(#terminal-3444994516-line-17)">&#160;Flight&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="434.8" textLength="12.2" clip-path="url(#terminal-3444994516-line-17)">
196
+ </text><text class="terminal-3444994516-r2" x="0" y="459.2" textLength="207.4" clip-path="url(#terminal-3444994516-line-18)">&#160;Iberia&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="459.2" textLength="146.4" clip-path="url(#terminal-3444994516-line-18)">&#160;2026-07-12&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="459.2" textLength="317.2" clip-path="url(#terminal-3444994516-line-18)">&#160;Iberia&#160;IB3170&#160;MAD-LHR&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="671" y="459.2" textLength="109.8" clip-path="url(#terminal-3444994516-line-18)">&#160;+4,200&#160;&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="459.2" textLength="207.4" clip-path="url(#terminal-3444994516-line-18)">&#160;Reward&#160;Flight&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="459.2" textLength="12.2" clip-path="url(#terminal-3444994516-line-18)">
197
+ </text><text class="terminal-3444994516-r2" x="0" y="483.6" textLength="207.4" clip-path="url(#terminal-3444994516-line-19)">&#160;British&#160;Airways&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="483.6" textLength="146.4" clip-path="url(#terminal-3444994516-line-19)">&#160;2026-07-02&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="483.6" textLength="317.2" clip-path="url(#terminal-3444994516-line-19)">&#160;Tesco&#160;groceries&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="671" y="483.6" textLength="109.8" clip-path="url(#terminal-3444994516-line-19)">&#160;+240&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="483.6" textLength="207.4" clip-path="url(#terminal-3444994516-line-19)">&#160;BA&#160;Avios&#160;eStore&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="483.6" textLength="12.2" clip-path="url(#terminal-3444994516-line-19)">
198
+ </text><text class="terminal-3444994516-r2" x="0" y="508" textLength="207.4" clip-path="url(#terminal-3444994516-line-20)">&#160;Aer&#160;Lingus&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="508" textLength="146.4" clip-path="url(#terminal-3444994516-line-20)">&#160;2026-06-28&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="508" textLength="317.2" clip-path="url(#terminal-3444994516-line-20)">&#160;AerClub&#160;Dining&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="671" y="508" textLength="109.8" clip-path="url(#terminal-3444994516-line-20)">&#160;+480&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="508" textLength="207.4" clip-path="url(#terminal-3444994516-line-20)">&#160;Dining&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="508" textLength="12.2" clip-path="url(#terminal-3444994516-line-20)">
199
+ </text><text class="terminal-3444994516-r2" x="0" y="532.4" textLength="207.4" clip-path="url(#terminal-3444994516-line-21)">&#160;Iberia&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="532.4" textLength="146.4" clip-path="url(#terminal-3444994516-line-21)">&#160;2026-06-21&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="532.4" textLength="317.2" clip-path="url(#terminal-3444994516-line-21)">&#160;NH&#160;Hotels&#160;Madrid&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="671" y="532.4" textLength="109.8" clip-path="url(#terminal-3444994516-line-21)">&#160;+1,600&#160;&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="532.4" textLength="207.4" clip-path="url(#terminal-3444994516-line-21)">&#160;Hotel&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="532.4" textLength="12.2" clip-path="url(#terminal-3444994516-line-21)">
200
+ </text><text class="terminal-3444994516-r2" x="0" y="556.8" textLength="207.4" clip-path="url(#terminal-3444994516-line-22)">&#160;Finnair&#160;Plus&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="556.8" textLength="146.4" clip-path="url(#terminal-3444994516-line-22)">&#160;2026-06-14&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="556.8" textLength="317.2" clip-path="url(#terminal-3444994516-line-22)">&#160;Nordic&#160;Hotels&#160;Helsinki&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="671" y="556.8" textLength="109.8" clip-path="url(#terminal-3444994516-line-22)">&#160;+720&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="556.8" textLength="207.4" clip-path="url(#terminal-3444994516-line-22)">&#160;Hotel&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="556.8" textLength="12.2" clip-path="url(#terminal-3444994516-line-22)">
201
+ </text><text class="terminal-3444994516-r2" x="0" y="581.2" textLength="207.4" clip-path="url(#terminal-3444994516-line-23)">&#160;British&#160;Airways&#160;</text><text class="terminal-3444994516-r2" x="207.4" y="581.2" textLength="146.4" clip-path="url(#terminal-3444994516-line-23)">&#160;2026-06-09&#160;</text><text class="terminal-3444994516-r2" x="353.8" y="581.2" textLength="317.2" clip-path="url(#terminal-3444994516-line-23)">&#160;Redemption&#160;LHR-JFK&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3444994516-r2" x="671" y="581.2" textLength="109.8" clip-path="url(#terminal-3444994516-line-23)">&#160;-50,000&#160;</text><text class="terminal-3444994516-r2" x="780.8" y="581.2" textLength="207.4" clip-path="url(#terminal-3444994516-line-23)">&#160;Reward&#160;Flight&#160;&#160;&#160;</text><text class="terminal-3444994516-r1" x="1171.2" y="581.2" textLength="12.2" clip-path="url(#terminal-3444994516-line-23)">
202
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="605.6" textLength="12.2" clip-path="url(#terminal-3444994516-line-24)">
203
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="630" textLength="12.2" clip-path="url(#terminal-3444994516-line-25)">
204
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="654.4" textLength="12.2" clip-path="url(#terminal-3444994516-line-26)">
205
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="678.8" textLength="12.2" clip-path="url(#terminal-3444994516-line-27)">
206
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="703.2" textLength="12.2" clip-path="url(#terminal-3444994516-line-28)">
207
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="727.6" textLength="12.2" clip-path="url(#terminal-3444994516-line-29)">
208
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="752" textLength="12.2" clip-path="url(#terminal-3444994516-line-30)">
209
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="776.4" textLength="12.2" clip-path="url(#terminal-3444994516-line-31)">
210
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="800.8" textLength="12.2" clip-path="url(#terminal-3444994516-line-32)">
211
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="825.2" textLength="12.2" clip-path="url(#terminal-3444994516-line-33)">
212
+ </text><text class="terminal-3444994516-r1" x="1171.2" y="849.6" textLength="12.2" clip-path="url(#terminal-3444994516-line-34)">
213
+ </text><text class="terminal-3444994516-r19" x="0" y="874" textLength="36.6" clip-path="url(#terminal-3444994516-line-35)">&#160;r&#160;</text><text class="terminal-3444994516-r2" x="36.6" y="874" textLength="97.6" clip-path="url(#terminal-3444994516-line-35)">Refresh&#160;</text><text class="terminal-3444994516-r19" x="134.2" y="874" textLength="36.6" clip-path="url(#terminal-3444994516-line-35)">&#160;q&#160;</text><text class="terminal-3444994516-r2" x="170.8" y="874" textLength="61" clip-path="url(#terminal-3444994516-line-35)">Quit&#160;</text><text class="terminal-3444994516-r20" x="1024.8" y="874" textLength="12.2" clip-path="url(#terminal-3444994516-line-35)">▏</text><text class="terminal-3444994516-r19" x="1037" y="874" textLength="24.4" clip-path="url(#terminal-3444994516-line-35)">^p</text><text class="terminal-3444994516-r2" x="1061.4" y="874" textLength="97.6" clip-path="url(#terminal-3444994516-line-35)">&#160;palette</text>
214
+ </g>
215
+ </g>
216
+ </svg>