avios-cli 0.3.0__tar.gz → 0.4.2__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 (59) hide show
  1. {avios_cli-0.3.0 → avios_cli-0.4.2}/CHANGELOG.md +49 -1
  2. {avios_cli-0.3.0 → avios_cli-0.4.2}/PKG-INFO +39 -12
  3. {avios_cli-0.3.0 → avios_cli-0.4.2}/README.md +37 -10
  4. {avios_cli-0.3.0 → avios_cli-0.4.2}/SECURITY.md +4 -0
  5. avios_cli-0.4.2/docs/dashboard.svg +216 -0
  6. avios_cli-0.4.2/docs/reward-flights.svg +223 -0
  7. {avios_cli-0.3.0 → avios_cli-0.4.2}/pyproject.toml +3 -3
  8. avios_cli-0.4.2/scripts/screenshot.py +149 -0
  9. avios_cli-0.4.2/src/avios/__init__.py +6 -0
  10. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/auth.py +70 -2
  11. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/cli.py +293 -1
  12. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/client.py +5 -0
  13. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/endpoints.py +3 -0
  14. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/finnair.py +37 -11
  15. avios_cli-0.4.2/src/avios/rewards.py +530 -0
  16. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/session.py +54 -10
  17. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/tui/app.py +26 -10
  18. avios_cli-0.4.2/src/avios/tui/rewards.py +380 -0
  19. avios_cli-0.4.2/src/avios/tui/styles.tcss +94 -0
  20. avios_cli-0.4.2/tests/fixtures/reward_search.rsc +3 -0
  21. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/test_auth.py +31 -3
  22. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/test_cli.py +176 -0
  23. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/test_finnair.py +32 -0
  24. avios_cli-0.4.2/tests/test_rewards.py +324 -0
  25. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/test_session.py +15 -0
  26. avios_cli-0.4.2/tests/test_tui.py +280 -0
  27. avios_cli-0.3.0/docs/dashboard.svg +0 -190
  28. avios_cli-0.3.0/scripts/screenshot.py +0 -84
  29. avios_cli-0.3.0/src/avios/__init__.py +0 -6
  30. avios_cli-0.3.0/src/avios/tui/styles.tcss +0 -21
  31. avios_cli-0.3.0/tests/test_tui.py +0 -137
  32. {avios_cli-0.3.0 → avios_cli-0.4.2}/.editorconfig +0 -0
  33. {avios_cli-0.3.0 → avios_cli-0.4.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  34. {avios_cli-0.3.0 → avios_cli-0.4.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  35. {avios_cli-0.3.0 → avios_cli-0.4.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  36. {avios_cli-0.3.0 → avios_cli-0.4.2}/.github/dependabot.yml +0 -0
  37. {avios_cli-0.3.0 → avios_cli-0.4.2}/.github/workflows/ci.yml +0 -0
  38. {avios_cli-0.3.0 → avios_cli-0.4.2}/.github/workflows/publish.yml +0 -0
  39. {avios_cli-0.3.0 → avios_cli-0.4.2}/.gitignore +0 -0
  40. {avios_cli-0.3.0 → avios_cli-0.4.2}/.pre-commit-config.yaml +0 -0
  41. {avios_cli-0.3.0 → avios_cli-0.4.2}/.python-version +0 -0
  42. {avios_cli-0.3.0 → avios_cli-0.4.2}/CONTRIBUTING.md +0 -0
  43. {avios_cli-0.3.0 → avios_cli-0.4.2}/LICENSE +0 -0
  44. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/accounts.py +0 -0
  45. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/aggregate.py +0 -0
  46. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/config.py +0 -0
  47. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/models.py +0 -0
  48. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/programmes.py +0 -0
  49. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/tui/__init__.py +0 -0
  50. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/tui/art.py +0 -0
  51. {avios_cli-0.3.0 → avios_cli-0.4.2}/src/avios/tui/widgets.py +0 -0
  52. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/conftest.py +0 -0
  53. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/fixtures/balance.json +0 -0
  54. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/fixtures/transactions.json +0 -0
  55. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/test_accounts.py +0 -0
  56. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/test_aggregate.py +0 -0
  57. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/test_client.py +0 -0
  58. {avios_cli-0.3.0 → avios_cli-0.4.2}/tests/test_models.py +0 -0
  59. {avios_cli-0.3.0 → avios_cli-0.4.2}/uv.lock +0 -0
@@ -6,6 +6,51 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.4.2] - 2026-07-27
10
+
11
+ ### Fixed
12
+ - **BA reward-flight searches failed with 403 after a successful login.** The
13
+ flight finder has a separate Auth0 session and rejects plain HTTP or automated
14
+ headless requests at Akamai. BA login now waits for the second reward-flight
15
+ prompt, and searches drive the site's own form in a background Chrome window
16
+ before parsing the returned RSC availability.
17
+ - Stored Akamai cookies are no longer replayed over Chrome's fresher browser jar,
18
+ and a transient Next.js shell response is retried once.
19
+
20
+ ## [0.4.1] - 2026-07-27
21
+
22
+ ### Fixed
23
+ - **Finnair balance/transactions failed with 403 immediately after login.** Login
24
+ captured the API key from the first `api.finnair.com` request (`getgauth`), which
25
+ uses a *different* `x-api-key` than the loyalty balance/transactions endpoints —
26
+ so every data call sent the wrong key and was refused. Login now captures
27
+ credentials only from a loyalty API request (`/d/loyalty-service/legacy/current/api/`),
28
+ which carries the key those endpoints accept. Fixes #28.
29
+ - A Finnair `403 Forbidden` is no longer mislabelled "session expired"; the message
30
+ now names the real cause (likely a stale/wrong API key) and includes the response.
31
+ Fixes #29.
32
+
33
+ ## [0.4.0] - 2026-07-27
34
+
35
+ ### Added
36
+ - **British Airways reward-flight availability.** `avios flights ORIGIN DEST`
37
+ supports exact-date and month-calendar searches, cabin/passenger filters,
38
+ available-only output by default, `--show-unavailable`, and scriptable JSON.
39
+ - Return journeys run two independent one-way searches with the route reversed
40
+ for the inbound leg.
41
+ - Typed reward calendar, day, flight, and cabin-availability models plus an
42
+ isolated parser for avios.com's authenticated React Server Components stream.
43
+ - The Textual app now has Dashboard and Reward Flights tabs. The search tab keeps
44
+ network work off the event loop and renders outbound/inbound results separately.
45
+
46
+ ### Changed
47
+ - BA browser-assisted login warms the separate `spend-avios` flight-search app
48
+ before saving cookies.
49
+
50
+ ### Security
51
+ - Reward-search action tokens from the private RSC response are ignored and never
52
+ stored; tests use a small sanitized fixture rather than the captured HAR.
53
+
9
54
  ## [0.3.0] - 2026-07-27
10
55
 
11
56
  ### Added
@@ -153,7 +198,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
153
198
  - Reward-flight **availability** search is not yet implemented (needs a British
154
199
  Airways capture).
155
200
 
156
- [Unreleased]: https://github.com/alexechoi/avios-cli/compare/v0.3.0...HEAD
201
+ [Unreleased]: https://github.com/alexechoi/avios-cli/compare/v0.4.2...HEAD
202
+ [0.4.2]: https://github.com/alexechoi/avios-cli/compare/v0.4.1...v0.4.2
203
+ [0.4.1]: https://github.com/alexechoi/avios-cli/compare/v0.4.0...v0.4.1
204
+ [0.4.0]: https://github.com/alexechoi/avios-cli/compare/v0.3.0...v0.4.0
157
205
  [0.3.0]: https://github.com/alexechoi/avios-cli/compare/v0.2.1...v0.3.0
158
206
  [0.2.1]: https://github.com/alexechoi/avios-cli/compare/v0.2.0...v0.2.1
159
207
  [0.2.0]: https://github.com/alexechoi/avios-cli/compare/v0.1.6...v0.2.0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: avios-cli
3
- Version: 0.3.0
4
- Summary: A CLI and TUI for avios.com — view your Avios balance and transactions from the terminal.
3
+ Version: 0.4.2
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
7
7
  Project-URL: Issues, https://github.com/alexechoi/avios-cli/issues
@@ -39,9 +39,10 @@ Description-Content-Type: text/markdown
39
39
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
40
40
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
41
41
 
42
- A **CLI and TUI for your Avios programmes** — check balances and browse transactions
43
- without leaving the terminal. British Airways and Iberia use avios.com; Finnair Plus
44
- uses Finnair's own OAuth and loyalty API.
42
+ A **CLI and TUI for your Avios programmes** — check balances, browse transactions,
43
+ and search British Airways reward-flight availability without leaving the terminal.
44
+ British Airways, Iberia, and Aer Lingus use avios.com; Finnair Plus uses Finnair's
45
+ own OAuth and loyalty API.
45
46
 
46
47
  > ⚠️ **Unofficial.** This project is not affiliated with, authorised by, or endorsed by
47
48
  > Avios, British Airways, Finnair or IAG Loyalty. It drives the same private endpoints
@@ -52,6 +53,10 @@ uses Finnair's own OAuth and loyalty API.
52
53
 
53
54
  <sub>The <code>avios tui</code> dashboard (demo data). Regenerate with <code>uv run python scripts/screenshot.py</code>.</sub>
54
55
 
56
+ ![avios reward-flight search](docs/reward-flights.svg)
57
+
58
+ <sub>Direct BA reward-seat availability by date and cabin (synthetic demo data).</sub>
59
+
55
60
  ## Status
56
61
 
57
62
  Early alpha, built in the open. See the [roadmap](#roadmap).
@@ -123,6 +128,12 @@ for Finnair because browser-cookie import cannot read that token.
123
128
  Each programme session is stored at `~/.config/avios/accounts/<programme>.json`
124
129
  (mode `600`). Sessions expire; just log in to that programme again. Use
125
130
  `avios logout <programme>` for one account or `avios logout` for all accounts.
131
+ For BA, browser-assisted login also opens the separate reward-flight application.
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.
126
137
 
127
138
  ## Usage
128
139
 
@@ -138,11 +149,17 @@ avios balance --account iberia # just one programme
138
149
  avios overview # dashboard summary
139
150
  avios whoami # name, tier, membership, email
140
151
  avios raw /shell/api/users/current/accounts # hit any endpoint directly
152
+
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
156
+ avios flights LON ABZ --month 2026-11 --cabin economy --cabin business
157
+ avios flights LON ABZ --month 2026-11 --return-month 2026-12 --json
141
158
  ```
142
159
 
143
- Add `--json` to `accounts`, `balance`, `transactions`, `pending` or `whoami` for
144
- scriptable output. With a single account, `balance` keeps the individual/household
145
- breakdown.
160
+ Add `--json` to `accounts`, `balance`, `transactions`, `pending`, `whoami`, or
161
+ `flights` for scriptable output. With a single account, `balance` keeps the
162
+ individual/household breakdown.
146
163
 
147
164
  ## TUI
148
165
 
@@ -150,9 +167,19 @@ breakdown.
150
167
  avios tui
151
168
  ```
152
169
 
153
- A full-screen dashboard across all your accounts: a combined balance header (with a
154
- per-programme breakdown) and a scrollable transactions table with a Programme column,
155
- merged newest-first. Press `r` to refresh, `q` to quit.
170
+ A tabbed full-screen application:
171
+
172
+ - **Dashboard** — combined balance header and transactions across every account.
173
+ - **Reward Flights** — BA date/calendar search with optional reverse-route return,
174
+ cabin/passenger controls, and independent outbound/inbound result tables.
175
+
176
+ Press `r` to refresh the dashboard and `q` to quit. Reward searches run only when
177
+ you press Search or Enter.
178
+
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.
156
183
 
157
184
  ## Roadmap
158
185
 
@@ -163,7 +190,7 @@ merged newest-first. Press `r` to refresh, `q` to quit.
163
190
  - [x] CLI commands
164
191
  - [x] Textual TUI dashboard
165
192
  - [x] Multiple accounts (BA, Iberia, Aer Lingus, Finnair) with combined views
166
- - [ ] Reward-flight **availability** search _(coming soon — needs a British Airways capture)_
193
+ - [x] British Airways reward-flight **availability** search (CLI + TUI)
167
194
 
168
195
  ## Development
169
196
 
@@ -4,9 +4,10 @@
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
5
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)
6
6
 
7
- A **CLI and TUI for your Avios programmes** — check balances and browse transactions
8
- without leaving the terminal. British Airways and Iberia use avios.com; Finnair Plus
9
- uses Finnair's own OAuth and loyalty API.
7
+ A **CLI and TUI for your Avios programmes** — check balances, browse transactions,
8
+ and search British Airways reward-flight availability without leaving the terminal.
9
+ British Airways, Iberia, and Aer Lingus use avios.com; Finnair Plus uses Finnair's
10
+ own OAuth and loyalty API.
10
11
 
11
12
  > ⚠️ **Unofficial.** This project is not affiliated with, authorised by, or endorsed by
12
13
  > Avios, British Airways, Finnair or IAG Loyalty. It drives the same private endpoints
@@ -17,6 +18,10 @@ uses Finnair's own OAuth and loyalty API.
17
18
 
18
19
  <sub>The <code>avios tui</code> dashboard (demo data). Regenerate with <code>uv run python scripts/screenshot.py</code>.</sub>
19
20
 
21
+ ![avios reward-flight search](docs/reward-flights.svg)
22
+
23
+ <sub>Direct BA reward-seat availability by date and cabin (synthetic demo data).</sub>
24
+
20
25
  ## Status
21
26
 
22
27
  Early alpha, built in the open. See the [roadmap](#roadmap).
@@ -88,6 +93,12 @@ for Finnair because browser-cookie import cannot read that token.
88
93
  Each programme session is stored at `~/.config/avios/accounts/<programme>.json`
89
94
  (mode `600`). Sessions expire; just log in to that programme again. Use
90
95
  `avios logout <programme>` for one account or `avios logout` for all accounts.
96
+ For BA, browser-assisted login also opens the separate reward-flight application.
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.
91
102
 
92
103
  ## Usage
93
104
 
@@ -103,11 +114,17 @@ avios balance --account iberia # just one programme
103
114
  avios overview # dashboard summary
104
115
  avios whoami # name, tier, membership, email
105
116
  avios raw /shell/api/users/current/accounts # hit any endpoint directly
117
+
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
121
+ avios flights LON ABZ --month 2026-11 --cabin economy --cabin business
122
+ avios flights LON ABZ --month 2026-11 --return-month 2026-12 --json
106
123
  ```
107
124
 
108
- Add `--json` to `accounts`, `balance`, `transactions`, `pending` or `whoami` for
109
- scriptable output. With a single account, `balance` keeps the individual/household
110
- breakdown.
125
+ Add `--json` to `accounts`, `balance`, `transactions`, `pending`, `whoami`, or
126
+ `flights` for scriptable output. With a single account, `balance` keeps the
127
+ individual/household breakdown.
111
128
 
112
129
  ## TUI
113
130
 
@@ -115,9 +132,19 @@ breakdown.
115
132
  avios tui
116
133
  ```
117
134
 
118
- A full-screen dashboard across all your accounts: a combined balance header (with a
119
- per-programme breakdown) and a scrollable transactions table with a Programme column,
120
- merged newest-first. Press `r` to refresh, `q` to quit.
135
+ A tabbed full-screen application:
136
+
137
+ - **Dashboard** — combined balance header and transactions across every account.
138
+ - **Reward Flights** — BA date/calendar search with optional reverse-route return,
139
+ cabin/passenger controls, and independent outbound/inbound result tables.
140
+
141
+ Press `r` to refresh the dashboard and `q` to quit. Reward searches run only when
142
+ you press Search or Enter.
143
+
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.
121
148
 
122
149
  ## Roadmap
123
150
 
@@ -128,7 +155,7 @@ merged newest-first. Press `r` to refresh, `q` to quit.
128
155
  - [x] CLI commands
129
156
  - [x] Textual TUI dashboard
130
157
  - [x] Multiple accounts (BA, Iberia, Aer Lingus, Finnair) with combined views
131
- - [ ] Reward-flight **availability** search _(coming soon — needs a British Airways capture)_
158
+ - [x] British Airways reward-flight **availability** search (CLI + TUI)
132
159
 
133
160
  ## Development
134
161
 
@@ -11,6 +11,10 @@
11
11
  - `avios logout` deletes stored sessions. They also expire on the server side.
12
12
  - `AVIOS_COOKIE` may be set to supply a cookie via the environment instead of the
13
13
  stored file — avoid committing it or storing it in shell history.
14
+ - Reward-flight search launches the isolated BA Chrome profile in the background;
15
+ Chrome sends the saved application cookie only to `www.avios.com` and refreshes
16
+ its own anti-bot cookies. The RSC response's short-lived action tokens are
17
+ neither exposed nor persisted.
14
18
 
15
19
  ## Unofficial software
16
20
 
@@ -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-1769193694-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-1769193694-title {
30
+ font-size: 18px;
31
+ font-weight: bold;
32
+ font-family: arial;
33
+ }
34
+
35
+ .terminal-1769193694-r1 { fill: #c5c8c6 }
36
+ .terminal-1769193694-r2 { fill: #e0e0e0 }
37
+ .terminal-1769193694-r3 { fill: #a3a3a3 }
38
+ .terminal-1769193694-r4 { fill: #c6c6c6 }
39
+ .terminal-1769193694-r5 { fill: #a6a6a6;font-weight: bold }
40
+ .terminal-1769193694-r6 { fill: #a9a9a9;font-weight: bold }
41
+ .terminal-1769193694-r7 { fill: #8d8d8d;font-weight: bold }
42
+ .terminal-1769193694-r8 { fill: #707070;font-weight: bold }
43
+ .terminal-1769193694-r9 { fill: #535353;font-weight: bold }
44
+ .terminal-1769193694-r10 { fill: #686868;font-weight: bold }
45
+ .terminal-1769193694-r11 { fill: #9e9e9e;font-style: italic; }
46
+ .terminal-1769193694-r12 { fill: #eaeaea;font-weight: bold }
47
+ .terminal-1769193694-r13 { fill: #7f7f7f }
48
+ .terminal-1769193694-r14 { fill: #585858 }
49
+ .terminal-1769193694-r15 { fill: #656565 }
50
+ .terminal-1769193694-r16 { fill: #e0e0e0;font-weight: bold }
51
+ .terminal-1769193694-r17 { fill: #b9b9b9;font-weight: bold }
52
+ .terminal-1769193694-r18 { fill: #9e9e9e }
53
+ .terminal-1769193694-r19 { fill: #b0b0b0;font-weight: bold }
54
+ .terminal-1769193694-r20 { fill: #515151 }
55
+ </style>
56
+
57
+ <defs>
58
+ <clipPath id="terminal-1769193694-clip-terminal">
59
+ <rect x="0" y="0" width="1170.1999999999998" height="877.4" />
60
+ </clipPath>
61
+ <clipPath id="terminal-1769193694-line-0">
62
+ <rect x="0" y="1.5" width="1171.2" height="24.65"/>
63
+ </clipPath>
64
+ <clipPath id="terminal-1769193694-line-1">
65
+ <rect x="0" y="25.9" width="1171.2" height="24.65"/>
66
+ </clipPath>
67
+ <clipPath id="terminal-1769193694-line-2">
68
+ <rect x="0" y="50.3" width="1171.2" height="24.65"/>
69
+ </clipPath>
70
+ <clipPath id="terminal-1769193694-line-3">
71
+ <rect x="0" y="74.7" width="1171.2" height="24.65"/>
72
+ </clipPath>
73
+ <clipPath id="terminal-1769193694-line-4">
74
+ <rect x="0" y="99.1" width="1171.2" height="24.65"/>
75
+ </clipPath>
76
+ <clipPath id="terminal-1769193694-line-5">
77
+ <rect x="0" y="123.5" width="1171.2" height="24.65"/>
78
+ </clipPath>
79
+ <clipPath id="terminal-1769193694-line-6">
80
+ <rect x="0" y="147.9" width="1171.2" height="24.65"/>
81
+ </clipPath>
82
+ <clipPath id="terminal-1769193694-line-7">
83
+ <rect x="0" y="172.3" width="1171.2" height="24.65"/>
84
+ </clipPath>
85
+ <clipPath id="terminal-1769193694-line-8">
86
+ <rect x="0" y="196.7" width="1171.2" height="24.65"/>
87
+ </clipPath>
88
+ <clipPath id="terminal-1769193694-line-9">
89
+ <rect x="0" y="221.1" width="1171.2" height="24.65"/>
90
+ </clipPath>
91
+ <clipPath id="terminal-1769193694-line-10">
92
+ <rect x="0" y="245.5" width="1171.2" height="24.65"/>
93
+ </clipPath>
94
+ <clipPath id="terminal-1769193694-line-11">
95
+ <rect x="0" y="269.9" width="1171.2" height="24.65"/>
96
+ </clipPath>
97
+ <clipPath id="terminal-1769193694-line-12">
98
+ <rect x="0" y="294.3" width="1171.2" height="24.65"/>
99
+ </clipPath>
100
+ <clipPath id="terminal-1769193694-line-13">
101
+ <rect x="0" y="318.7" width="1171.2" height="24.65"/>
102
+ </clipPath>
103
+ <clipPath id="terminal-1769193694-line-14">
104
+ <rect x="0" y="343.1" width="1171.2" height="24.65"/>
105
+ </clipPath>
106
+ <clipPath id="terminal-1769193694-line-15">
107
+ <rect x="0" y="367.5" width="1171.2" height="24.65"/>
108
+ </clipPath>
109
+ <clipPath id="terminal-1769193694-line-16">
110
+ <rect x="0" y="391.9" width="1171.2" height="24.65"/>
111
+ </clipPath>
112
+ <clipPath id="terminal-1769193694-line-17">
113
+ <rect x="0" y="416.3" width="1171.2" height="24.65"/>
114
+ </clipPath>
115
+ <clipPath id="terminal-1769193694-line-18">
116
+ <rect x="0" y="440.7" width="1171.2" height="24.65"/>
117
+ </clipPath>
118
+ <clipPath id="terminal-1769193694-line-19">
119
+ <rect x="0" y="465.1" width="1171.2" height="24.65"/>
120
+ </clipPath>
121
+ <clipPath id="terminal-1769193694-line-20">
122
+ <rect x="0" y="489.5" width="1171.2" height="24.65"/>
123
+ </clipPath>
124
+ <clipPath id="terminal-1769193694-line-21">
125
+ <rect x="0" y="513.9" width="1171.2" height="24.65"/>
126
+ </clipPath>
127
+ <clipPath id="terminal-1769193694-line-22">
128
+ <rect x="0" y="538.3" width="1171.2" height="24.65"/>
129
+ </clipPath>
130
+ <clipPath id="terminal-1769193694-line-23">
131
+ <rect x="0" y="562.7" width="1171.2" height="24.65"/>
132
+ </clipPath>
133
+ <clipPath id="terminal-1769193694-line-24">
134
+ <rect x="0" y="587.1" width="1171.2" height="24.65"/>
135
+ </clipPath>
136
+ <clipPath id="terminal-1769193694-line-25">
137
+ <rect x="0" y="611.5" width="1171.2" height="24.65"/>
138
+ </clipPath>
139
+ <clipPath id="terminal-1769193694-line-26">
140
+ <rect x="0" y="635.9" width="1171.2" height="24.65"/>
141
+ </clipPath>
142
+ <clipPath id="terminal-1769193694-line-27">
143
+ <rect x="0" y="660.3" width="1171.2" height="24.65"/>
144
+ </clipPath>
145
+ <clipPath id="terminal-1769193694-line-28">
146
+ <rect x="0" y="684.7" width="1171.2" height="24.65"/>
147
+ </clipPath>
148
+ <clipPath id="terminal-1769193694-line-29">
149
+ <rect x="0" y="709.1" width="1171.2" height="24.65"/>
150
+ </clipPath>
151
+ <clipPath id="terminal-1769193694-line-30">
152
+ <rect x="0" y="733.5" width="1171.2" height="24.65"/>
153
+ </clipPath>
154
+ <clipPath id="terminal-1769193694-line-31">
155
+ <rect x="0" y="757.9" width="1171.2" height="24.65"/>
156
+ </clipPath>
157
+ <clipPath id="terminal-1769193694-line-32">
158
+ <rect x="0" y="782.3" width="1171.2" height="24.65"/>
159
+ </clipPath>
160
+ <clipPath id="terminal-1769193694-line-33">
161
+ <rect x="0" y="806.7" width="1171.2" height="24.65"/>
162
+ </clipPath>
163
+ <clipPath id="terminal-1769193694-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-1769193694-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-1769193694-clip-terminal)">
176
+ <rect fill="#2d2d2d" x="0" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="12.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="24.4" y="1.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="85.4" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="97.6" y="1.5" width="256.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="353.8" y="1.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="414.8" y="1.5" width="36.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="451.4" y="1.5" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="780.8" y="1.5" width="268.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#353535" x="1049.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#353535" x="1061.4" y="1.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#353535" 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="#656565" x="0" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#656565" x="12.2" y="221.1" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#656565" 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="73.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="219.6" y="269.9" width="573.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="793" y="269.9" width="353.8" 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="1122.4" 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="#2d2d2d" x="0" y="343.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="207.4" y="343.1" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="353.8" y="343.1" width="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="634.4" y="343.1" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="744.2" y="343.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="951.6" y="343.1" width="219.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#333333" x="0" y="367.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#333333" x="207.4" y="367.5" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#333333" x="353.8" y="367.5" width="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#333333" x="634.4" y="367.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#333333" x="744.2" y="367.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#333333" x="951.6" y="367.5" width="219.6" 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="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="634.4" y="391.9" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="744.2" y="391.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="951.6" y="391.9" width="219.6" 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="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="634.4" y="416.3" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="744.2" y="416.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="951.6" y="416.3" width="219.6" 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="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="634.4" y="440.7" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="744.2" y="440.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="951.6" y="440.7" width="219.6" 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="280.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="634.4" y="465.1" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="744.2" y="465.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#171717" x="951.6" y="465.1" width="219.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="1171.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="1171.2" 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="#2d2d2d" x="0" y="855.5" width="36.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="36.6" y="855.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="134.2" y="855.5" width="36.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="170.8" y="855.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="231.8" y="855.5" width="793" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="1024.8" y="855.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="1037" y="855.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="1061.4" y="855.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#2d2d2d" x="1159" y="855.5" width="12.2" height="24.65" shape-rendering="crispEdges"/>
177
+ <g class="terminal-1769193694-matrix">
178
+ <text class="terminal-1769193694-r2" x="12.2" y="20" textLength="12.2" clip-path="url(#terminal-1769193694-line-0)">⭘</text><text class="terminal-1769193694-r2" x="353.8" y="20" textLength="61" clip-path="url(#terminal-1769193694-line-0)">avios</text><text class="terminal-1769193694-r3" x="414.8" y="20" textLength="36.6" clip-path="url(#terminal-1769193694-line-0)">&#160;—&#160;</text><text class="terminal-1769193694-r3" x="451.4" y="20" textLength="329.4" clip-path="url(#terminal-1769193694-line-0)">your&#160;Avios,&#160;in&#160;the&#160;terminal</text><text class="terminal-1769193694-r4" x="1061.4" y="20" textLength="97.6" clip-path="url(#terminal-1769193694-line-0)">15:20:42</text><text class="terminal-1769193694-r1" x="1171.2" y="20" textLength="12.2" clip-path="url(#terminal-1769193694-line-0)">
179
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="44.4" textLength="12.2" clip-path="url(#terminal-1769193694-line-1)">
180
+ </text><text class="terminal-1769193694-r5" x="353.8" y="68.8" textLength="451.4" clip-path="url(#terminal-1769193694-line-2)">&#160;█████╗&#160;██╗&#160;&#160;&#160;██╗██╗&#160;██████╗&#160;███████╗</text><text class="terminal-1769193694-r1" x="1171.2" y="68.8" textLength="12.2" clip-path="url(#terminal-1769193694-line-2)">
181
+ </text><text class="terminal-1769193694-r6" x="353.8" y="93.2" textLength="451.4" clip-path="url(#terminal-1769193694-line-3)">██╔══██╗██║&#160;&#160;&#160;██║██║██╔═══██╗██╔════╝</text><text class="terminal-1769193694-r1" x="1171.2" y="93.2" textLength="12.2" clip-path="url(#terminal-1769193694-line-3)">
182
+ </text><text class="terminal-1769193694-r7" x="353.8" y="117.6" textLength="451.4" clip-path="url(#terminal-1769193694-line-4)">███████║██║&#160;&#160;&#160;██║██║██║&#160;&#160;&#160;██║███████╗</text><text class="terminal-1769193694-r1" x="1171.2" y="117.6" textLength="12.2" clip-path="url(#terminal-1769193694-line-4)">
183
+ </text><text class="terminal-1769193694-r8" x="353.8" y="142" textLength="451.4" clip-path="url(#terminal-1769193694-line-5)">██╔══██║╚██╗&#160;██╔╝██║██║&#160;&#160;&#160;██║╚════██║</text><text class="terminal-1769193694-r1" x="1171.2" y="142" textLength="12.2" clip-path="url(#terminal-1769193694-line-5)">
184
+ </text><text class="terminal-1769193694-r9" x="353.8" y="166.4" textLength="451.4" clip-path="url(#terminal-1769193694-line-6)">██║&#160;&#160;██║&#160;╚████╔╝&#160;██║╚██████╔╝███████║</text><text class="terminal-1769193694-r1" x="1171.2" y="166.4" textLength="12.2" clip-path="url(#terminal-1769193694-line-6)">
185
+ </text><text class="terminal-1769193694-r10" x="353.8" y="190.8" textLength="451.4" clip-path="url(#terminal-1769193694-line-7)">╚═╝&#160;&#160;╚═╝&#160;&#160;╚═══╝&#160;&#160;╚═╝&#160;╚═════╝&#160;╚══════╝</text><text class="terminal-1769193694-r1" x="1171.2" y="190.8" textLength="12.2" clip-path="url(#terminal-1769193694-line-7)">
186
+ </text><text class="terminal-1769193694-r11" x="402.6" y="215.2" textLength="366" clip-path="url(#terminal-1769193694-line-8)">✈&#160;&#160;your&#160;Avios,&#160;in&#160;the&#160;terminal</text><text class="terminal-1769193694-r1" x="1171.2" y="215.2" textLength="12.2" clip-path="url(#terminal-1769193694-line-8)">
187
+ </text><text class="terminal-1769193694-r12" x="12.2" y="239.6" textLength="109.8" clip-path="url(#terminal-1769193694-line-9)">Dashboard</text><text class="terminal-1769193694-r13" x="146.4" y="239.6" textLength="170.8" clip-path="url(#terminal-1769193694-line-9)">Reward&#160;Flights</text><text class="terminal-1769193694-r1" x="1171.2" y="239.6" textLength="12.2" clip-path="url(#terminal-1769193694-line-9)">
188
+ </text><text class="terminal-1769193694-r14" x="0" y="264" textLength="12.2" clip-path="url(#terminal-1769193694-line-10)">╸</text><text class="terminal-1769193694-r15" x="12.2" y="264" textLength="109.8" clip-path="url(#terminal-1769193694-line-10)">━━━━━━━━━</text><text class="terminal-1769193694-r14" x="122" y="264" textLength="12.2" clip-path="url(#terminal-1769193694-line-10)">╺</text><text class="terminal-1769193694-r14" x="134.2" y="264" textLength="1037" clip-path="url(#terminal-1769193694-line-10)">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text class="terminal-1769193694-r1" x="1171.2" y="264" textLength="12.2" clip-path="url(#terminal-1769193694-line-10)">
189
+ </text><text class="terminal-1769193694-r16" x="24.4" y="288.4" textLength="122" clip-path="url(#terminal-1769193694-line-11)">Combined&#160;&#160;</text><text class="terminal-1769193694-r17" x="146.4" y="288.4" textLength="73.2" clip-path="url(#terminal-1769193694-line-11)">97,791</text><text class="terminal-1769193694-r18" x="219.6" y="288.4" textLength="573.4" clip-path="url(#terminal-1769193694-line-11)">&#160;&#160;&#160;&#160;&#160;British&#160;Airways&#160;75,751&#160;&#160;&#160;·&#160;&#160;&#160;Iberia&#160;22,040</text><text class="terminal-1769193694-r1" x="1171.2" y="288.4" textLength="12.2" clip-path="url(#terminal-1769193694-line-11)">
190
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="312.8" textLength="12.2" clip-path="url(#terminal-1769193694-line-12)">
191
+ </text><text class="terminal-1769193694-r15" x="0" y="337.2" textLength="1171.2" clip-path="url(#terminal-1769193694-line-13)">────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-1769193694-r1" x="1171.2" y="337.2" textLength="12.2" clip-path="url(#terminal-1769193694-line-13)">
192
+ </text><text class="terminal-1769193694-r16" x="0" y="361.6" textLength="207.4" clip-path="url(#terminal-1769193694-line-14)">&#160;Programme&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r16" x="207.4" y="361.6" textLength="146.4" clip-path="url(#terminal-1769193694-line-14)">&#160;Date&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r16" x="353.8" y="361.6" textLength="280.6" clip-path="url(#terminal-1769193694-line-14)">&#160;Description&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r16" x="634.4" y="361.6" textLength="109.8" clip-path="url(#terminal-1769193694-line-14)">&#160;Avios&#160;&#160;&#160;</text><text class="terminal-1769193694-r16" x="744.2" y="361.6" textLength="207.4" clip-path="url(#terminal-1769193694-line-14)">&#160;Type&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r1" x="1171.2" y="361.6" textLength="12.2" clip-path="url(#terminal-1769193694-line-14)">
193
+ </text><text class="terminal-1769193694-r2" x="0" y="386" textLength="207.4" clip-path="url(#terminal-1769193694-line-15)">&#160;British&#160;Airways&#160;</text><text class="terminal-1769193694-r2" x="207.4" y="386" textLength="146.4" clip-path="url(#terminal-1769193694-line-15)">&#160;2026-07-18&#160;</text><text class="terminal-1769193694-r2" x="353.8" y="386" textLength="280.6" clip-path="url(#terminal-1769193694-line-15)">&#160;Flight&#160;BA286&#160;SFO-LHR&#160;&#160;</text><text class="terminal-1769193694-r2" x="634.4" y="386" textLength="109.8" clip-path="url(#terminal-1769193694-line-15)">&#160;+8,500&#160;&#160;</text><text class="terminal-1769193694-r2" x="744.2" y="386" textLength="207.4" clip-path="url(#terminal-1769193694-line-15)">&#160;Collection&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r1" x="1171.2" y="386" textLength="12.2" clip-path="url(#terminal-1769193694-line-15)">
194
+ </text><text class="terminal-1769193694-r2" x="0" y="410.4" textLength="207.4" clip-path="url(#terminal-1769193694-line-16)">&#160;Iberia&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r2" x="207.4" y="410.4" textLength="146.4" clip-path="url(#terminal-1769193694-line-16)">&#160;2026-07-12&#160;</text><text class="terminal-1769193694-r2" x="353.8" y="410.4" textLength="280.6" clip-path="url(#terminal-1769193694-line-16)">&#160;Iberia&#160;IB3170&#160;MAD-LHR&#160;</text><text class="terminal-1769193694-r2" x="634.4" y="410.4" textLength="109.8" clip-path="url(#terminal-1769193694-line-16)">&#160;+4,200&#160;&#160;</text><text class="terminal-1769193694-r2" x="744.2" y="410.4" textLength="207.4" clip-path="url(#terminal-1769193694-line-16)">&#160;Reward&#160;Flight&#160;&#160;&#160;</text><text class="terminal-1769193694-r1" x="1171.2" y="410.4" textLength="12.2" clip-path="url(#terminal-1769193694-line-16)">
195
+ </text><text class="terminal-1769193694-r2" x="0" y="434.8" textLength="207.4" clip-path="url(#terminal-1769193694-line-17)">&#160;British&#160;Airways&#160;</text><text class="terminal-1769193694-r2" x="207.4" y="434.8" textLength="146.4" clip-path="url(#terminal-1769193694-line-17)">&#160;2026-07-02&#160;</text><text class="terminal-1769193694-r2" x="353.8" y="434.8" textLength="280.6" clip-path="url(#terminal-1769193694-line-17)">&#160;Tesco&#160;groceries&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r2" x="634.4" y="434.8" textLength="109.8" clip-path="url(#terminal-1769193694-line-17)">&#160;+240&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r2" x="744.2" y="434.8" textLength="207.4" clip-path="url(#terminal-1769193694-line-17)">&#160;BA&#160;Avios&#160;eStore&#160;</text><text class="terminal-1769193694-r1" x="1171.2" y="434.8" textLength="12.2" clip-path="url(#terminal-1769193694-line-17)">
196
+ </text><text class="terminal-1769193694-r2" x="0" y="459.2" textLength="207.4" clip-path="url(#terminal-1769193694-line-18)">&#160;Iberia&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r2" x="207.4" y="459.2" textLength="146.4" clip-path="url(#terminal-1769193694-line-18)">&#160;2026-06-21&#160;</text><text class="terminal-1769193694-r2" x="353.8" y="459.2" textLength="280.6" clip-path="url(#terminal-1769193694-line-18)">&#160;NH&#160;Hotels&#160;Madrid&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r2" x="634.4" y="459.2" textLength="109.8" clip-path="url(#terminal-1769193694-line-18)">&#160;+1,600&#160;&#160;</text><text class="terminal-1769193694-r2" x="744.2" y="459.2" textLength="207.4" clip-path="url(#terminal-1769193694-line-18)">&#160;Hotel&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r1" x="1171.2" y="459.2" textLength="12.2" clip-path="url(#terminal-1769193694-line-18)">
197
+ </text><text class="terminal-1769193694-r2" x="0" y="483.6" textLength="207.4" clip-path="url(#terminal-1769193694-line-19)">&#160;British&#160;Airways&#160;</text><text class="terminal-1769193694-r2" x="207.4" y="483.6" textLength="146.4" clip-path="url(#terminal-1769193694-line-19)">&#160;2026-06-09&#160;</text><text class="terminal-1769193694-r2" x="353.8" y="483.6" textLength="280.6" clip-path="url(#terminal-1769193694-line-19)">&#160;Redemption&#160;LHR-JFK&#160;&#160;&#160;&#160;</text><text class="terminal-1769193694-r2" x="634.4" y="483.6" textLength="109.8" clip-path="url(#terminal-1769193694-line-19)">&#160;-50,000&#160;</text><text class="terminal-1769193694-r2" x="744.2" y="483.6" textLength="207.4" clip-path="url(#terminal-1769193694-line-19)">&#160;Reward&#160;Flight&#160;&#160;&#160;</text><text class="terminal-1769193694-r1" x="1171.2" y="483.6" textLength="12.2" clip-path="url(#terminal-1769193694-line-19)">
198
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="508" textLength="12.2" clip-path="url(#terminal-1769193694-line-20)">
199
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="532.4" textLength="12.2" clip-path="url(#terminal-1769193694-line-21)">
200
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="556.8" textLength="12.2" clip-path="url(#terminal-1769193694-line-22)">
201
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="581.2" textLength="12.2" clip-path="url(#terminal-1769193694-line-23)">
202
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="605.6" textLength="12.2" clip-path="url(#terminal-1769193694-line-24)">
203
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="630" textLength="12.2" clip-path="url(#terminal-1769193694-line-25)">
204
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="654.4" textLength="12.2" clip-path="url(#terminal-1769193694-line-26)">
205
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="678.8" textLength="12.2" clip-path="url(#terminal-1769193694-line-27)">
206
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="703.2" textLength="12.2" clip-path="url(#terminal-1769193694-line-28)">
207
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="727.6" textLength="12.2" clip-path="url(#terminal-1769193694-line-29)">
208
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="752" textLength="12.2" clip-path="url(#terminal-1769193694-line-30)">
209
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="776.4" textLength="12.2" clip-path="url(#terminal-1769193694-line-31)">
210
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="800.8" textLength="12.2" clip-path="url(#terminal-1769193694-line-32)">
211
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="825.2" textLength="12.2" clip-path="url(#terminal-1769193694-line-33)">
212
+ </text><text class="terminal-1769193694-r1" x="1171.2" y="849.6" textLength="12.2" clip-path="url(#terminal-1769193694-line-34)">
213
+ </text><text class="terminal-1769193694-r19" x="0" y="874" textLength="36.6" clip-path="url(#terminal-1769193694-line-35)">&#160;r&#160;</text><text class="terminal-1769193694-r2" x="36.6" y="874" textLength="97.6" clip-path="url(#terminal-1769193694-line-35)">Refresh&#160;</text><text class="terminal-1769193694-r19" x="134.2" y="874" textLength="36.6" clip-path="url(#terminal-1769193694-line-35)">&#160;q&#160;</text><text class="terminal-1769193694-r2" x="170.8" y="874" textLength="61" clip-path="url(#terminal-1769193694-line-35)">Quit&#160;</text><text class="terminal-1769193694-r20" x="1024.8" y="874" textLength="12.2" clip-path="url(#terminal-1769193694-line-35)">▏</text><text class="terminal-1769193694-r19" x="1037" y="874" textLength="24.4" clip-path="url(#terminal-1769193694-line-35)">^p</text><text class="terminal-1769193694-r2" x="1061.4" y="874" textLength="97.6" clip-path="url(#terminal-1769193694-line-35)">&#160;palette</text>
214
+ </g>
215
+ </g>
216
+ </svg>