iobroker.jetframe 1.0.0

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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -0
  3. package/admin/SF-Pro.ttf +0 -0
  4. package/admin/admin.d.ts +65 -0
  5. package/admin/frame.html +982 -0
  6. package/admin/frame.html.bak-aircraft-card-real-row-20260518-1608 +1236 -0
  7. package/admin/frame.html.bak-aircraft-card-structure-20260518-1517 +1236 -0
  8. package/admin/frame.html.bak-aircraft-logo-id-fix-20260518-1639 +1239 -0
  9. package/admin/frame.html.bak-shortcut-test +1236 -0
  10. package/admin/frame.html.bak-tablet-class-20260518-1729 +1239 -0
  11. package/admin/heatmap.html +216 -0
  12. package/admin/index.html +268 -0
  13. package/admin/index_m.html +1749 -0
  14. package/admin/jetframe.css +1260 -0
  15. package/admin/jetframe.css.bak-airbus-landscape-fix +4630 -0
  16. package/admin/jetframe.css.bak-aircraft-card-clean-equal-20260518-1438 +4899 -0
  17. package/admin/jetframe.css.bak-aircraft-card-real-row-20260518-1608 +4814 -0
  18. package/admin/jetframe.css.bak-aircraft-card-row-left-20260518-1525 +4604 -0
  19. package/admin/jetframe.css.bak-aircraft-card-slim-equal-20260518-1446 +4647 -0
  20. package/admin/jetframe.css.bak-aircraft-card-structure-20260518-1517 +4646 -0
  21. package/admin/jetframe.css.bak-aircraft-inline-final-20260518-1527 +4654 -0
  22. package/admin/jetframe.css.bak-aircraft-row-compact-fix-20260518-1639 +4763 -0
  23. package/admin/jetframe.css.bak-before-aircrafttype-purge +4818 -0
  24. package/admin/jetframe.css.bak-before-cleanup +4670 -0
  25. package/admin/jetframe.css.bak-before-remove-tablet-only-20260518-1711 +4896 -0
  26. package/admin/jetframe.css.bak-before-tablet-layout-rework-20260518-1650 +4914 -0
  27. package/admin/jetframe.css.bak-clean-duplicate-fonts-20260518-1340 +4975 -0
  28. package/admin/jetframe.css.bak-clean-old-index-fix-20260518-1937 +5167 -0
  29. package/admin/jetframe.css.bak-hardleft-airbus +4751 -0
  30. package/admin/jetframe.css.bak-index-iphone-landscape-20260518-1931 +5030 -0
  31. package/admin/jetframe.css.bak-index-landscape-final-20260518-1941 +5167 -0
  32. package/admin/jetframe.css.bak-index-landscape-real-20260518-1936 +5186 -0
  33. package/admin/jetframe.css.bak-landscape-compact-jumbo-bold-20260518-1343 +4802 -0
  34. package/admin/jetframe.css.bak-logo-align-final +4551 -0
  35. package/admin/jetframe.css.bak-logo-final2 +4551 -0
  36. package/admin/jetframe.css.bak-narrowbody-font-fix +4992 -0
  37. package/admin/jetframe.css.bak-nuke-airbus-align +4790 -0
  38. package/admin/jetframe.css.bak-pill-balance-20260518-1603 +4773 -0
  39. package/admin/jetframe.css.bak-pill-balance-fix +4910 -0
  40. package/admin/jetframe.css.bak-radar-fix-fonts +4710 -0
  41. package/admin/jetframe.css.bak-shortcut-test +4899 -0
  42. package/admin/jetframe.css.bak-smaller-aircraft-card-fonts-20260518-1345 +4897 -0
  43. package/admin/jetframe.css.bak-tablet-fix-real-20260518-1748 +4945 -0
  44. package/admin/jetframe.css.bak-tablet-fullscreen-fix-20260518-1804 +4972 -0
  45. package/admin/jetframe.css.bak-tablet-landscape-layout-20260518-1645 +4802 -0
  46. package/admin/jetframe.css.bak-tablet-layout-final-20260518-1839 +4802 -0
  47. package/admin/jetframe.css.bak-tablet-layout-v3-20260518-1729 +4802 -0
  48. package/admin/jetframe.css.bak-tablet-layout-v4-20260518-1801 +4957 -0
  49. package/admin/jetframe.css.bak-tablet-layout-v5-20260518-1843 +4970 -0
  50. package/admin/jetframe.css.bak-tablet-layout-v6-20260518-1848 +4958 -0
  51. package/admin/jetframe.css.bak-tablet-layout-v7-20260518-1909 +4985 -0
  52. package/admin/jetframe.css.bak-tablet-only-landscape-v2-20260518-1707 +4802 -0
  53. package/admin/jetframe.css.bak-tablet-pages-final-20260519-1857 +5188 -0
  54. package/admin/jetframe.css.bak-tablet-pages-final-20260519-1859 +5347 -0
  55. package/admin/jetframe.css.bak-tablet-pages-v2-20260519-190807 +5349 -0
  56. package/admin/jetframe.css.bak-typography-align-final +4818 -0
  57. package/admin/jetframe.png +0 -0
  58. package/admin/manifest.webmanifest +15 -0
  59. package/admin/src/app.tsx +58 -0
  60. package/admin/src/components/settings.tsx +97 -0
  61. package/admin/src/i18n/de.json +11 -0
  62. package/admin/src/i18n/en.json +11 -0
  63. package/admin/src/i18n/es.json +11 -0
  64. package/admin/src/i18n/fr.json +11 -0
  65. package/admin/src/i18n/i18n.d.ts +28 -0
  66. package/admin/src/i18n/it.json +11 -0
  67. package/admin/src/i18n/nl.json +11 -0
  68. package/admin/src/i18n/pl.json +11 -0
  69. package/admin/src/i18n/pt.json +11 -0
  70. package/admin/src/i18n/ru.json +11 -0
  71. package/admin/src/i18n/uk.json +11 -0
  72. package/admin/src/i18n/zh-cn.json +11 -0
  73. package/admin/src/index.tsx +25 -0
  74. package/admin/stats.html +228 -0
  75. package/admin/style.css +32 -0
  76. package/admin/tsconfig.json +11 -0
  77. package/admin/words.js +46 -0
  78. package/build/lib/adsb.js +218 -0
  79. package/build/lib/adsb.js.map +7 -0
  80. package/build/lib/airportNamesDe.js +131 -0
  81. package/build/lib/airportNamesDe.js.map +7 -0
  82. package/build/lib/airports.js +281 -0
  83. package/build/lib/airports.js.map +7 -0
  84. package/build/lib/classify.js +339 -0
  85. package/build/lib/classify.js.map +7 -0
  86. package/build/lib/config.js +103 -0
  87. package/build/lib/config.js.map +7 -0
  88. package/build/lib/flightInfo.js +1409 -0
  89. package/build/lib/flightInfo.js.map +7 -0
  90. package/build/lib/geo.js +84 -0
  91. package/build/lib/geo.js.map +7 -0
  92. package/build/lib/images.js +422 -0
  93. package/build/lib/images.js.map +7 -0
  94. package/build/lib/specialLiveries.js +342 -0
  95. package/build/lib/specialLiveries.js.map +7 -0
  96. package/build/lib/states.js +971 -0
  97. package/build/lib/states.js.map +7 -0
  98. package/build/lib/staticFiles.js +73 -0
  99. package/build/lib/staticFiles.js.map +7 -0
  100. package/build/lib/types.js +17 -0
  101. package/build/lib/types.js.map +7 -0
  102. package/build/lib/visConfig.js +52 -0
  103. package/build/lib/visConfig.js.map +7 -0
  104. package/build/main.js +1454 -0
  105. package/build/main.js.map +7 -0
  106. package/io-package.json +169 -0
  107. package/package.json +82 -0
@@ -0,0 +1,4790 @@
1
+ /* ==================================================
2
+ JetFrame Unified Clean CSS
3
+ ================================================== */
4
+
5
+ :root {
6
+ --bg: #05060a;
7
+ --muted: rgba(255,255,255,.62);
8
+ --green: #35e66b;
9
+ --blue: #56a8ff;
10
+ --yellow: #ffd84d;
11
+ --red: #ff5a5a;
12
+ }
13
+
14
+ * {
15
+ box-sizing: border-box;
16
+ -webkit-tap-highlight-color: transparent;
17
+ }
18
+
19
+ html,
20
+ body {
21
+ margin: 0;
22
+ width: 100%;
23
+ height: 100%;
24
+ min-height: 100dvh;
25
+ overflow: hidden;
26
+ background: var(--bg);
27
+ color: white;
28
+ font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", Arial, sans-serif;
29
+ }
30
+
31
+ html,
32
+ body{
33
+ touch-action:pan-x pan-y;
34
+ overscroll-behavior:none;
35
+ }
36
+
37
+ body {
38
+ background:
39
+ radial-gradient(circle at 18% 8%, rgba(70,110,180,.38), transparent 38%),
40
+ radial-gradient(circle at 85% 22%, rgba(255,150,60,.18), transparent 34%),
41
+ linear-gradient(145deg, #090b11, #020306 72%);
42
+ }
43
+
44
+ #app {
45
+ width: 100vw;
46
+ height: 100dvh;
47
+ padding:
48
+ calc(10px + env(safe-area-inset-top))
49
+ calc(10px + env(safe-area-inset-right))
50
+ calc(10px + env(safe-area-inset-bottom))
51
+ calc(10px + env(safe-area-inset-left));
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ overflow: hidden;
56
+ }
57
+
58
+ .card,
59
+ .wall,
60
+ .jf-shell {
61
+ width: min(1280px, 96vw);
62
+ height: min(820px, calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 20px));
63
+ border-radius: 32px;
64
+ padding: 16px;
65
+ background: linear-gradient(145deg, rgba(62,70,90,.58), rgba(18,18,20,.80));
66
+ border: 1px solid rgba(255,255,255,.18);
67
+ box-shadow:
68
+ 0 35px 100px rgba(0,0,0,.58),
69
+ inset 0 1px 0 rgba(255,255,255,.22);
70
+ backdrop-filter: blur(24px);
71
+ -webkit-backdrop-filter: blur(24px);
72
+ overflow: hidden;
73
+ position: relative;
74
+ }
75
+
76
+ @media (orientation: portrait) {
77
+ .card,
78
+ .wall,
79
+ .jf-shell {
80
+ width: 96vw;
81
+ height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 20px);
82
+ border-radius: 30px;
83
+ }
84
+ }
85
+
86
+ /* ==================================================
87
+ Common
88
+ ================================================== */
89
+
90
+ .backBtn {
91
+ position: fixed;
92
+ top: calc(env(safe-area-inset-top) + 10px);
93
+ left: calc(env(safe-area-inset-left) + 10px);
94
+ width: 34px;
95
+ height: 34px;
96
+ border-radius: 999px;
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ background: rgba(0,0,0,.22);
101
+ backdrop-filter: blur(16px);
102
+ -webkit-backdrop-filter: blur(16px);
103
+ border: 1px solid rgba(255,255,255,.10);
104
+ color: rgba(255,255,255,.86);
105
+ font-size: 24px;
106
+ font-weight: 900;
107
+ text-decoration: none;
108
+ z-index: 9999;
109
+ opacity: .72;
110
+ }
111
+
112
+ .simpleApiWarning {
113
+ position: fixed;
114
+ left: 50%;
115
+ bottom: calc(env(safe-area-inset-bottom) + 18px);
116
+ transform: translateX(-50%) translateY(12px);
117
+ z-index: 99999;
118
+ max-width: min(92vw, 560px);
119
+ padding: 12px 16px;
120
+ border-radius: 18px;
121
+ background: rgba(255,90,90,.18);
122
+ border: 1px solid rgba(255,90,90,.34);
123
+ color: rgba(255,235,235,.96);
124
+ box-shadow: 0 18px 50px rgba(0,0,0,.45);
125
+ backdrop-filter: blur(18px);
126
+ -webkit-backdrop-filter: blur(18px);
127
+ font-size: 14px;
128
+ font-weight: 800;
129
+ line-height: 1.25;
130
+ text-align: center;
131
+ opacity: 0;
132
+ pointer-events: none;
133
+ transition: opacity .25s ease, transform .25s ease;
134
+ }
135
+
136
+ .simpleApiWarning.visible {
137
+ opacity: 1;
138
+ transform: translateX(-50%) translateY(0);
139
+ }
140
+
141
+ /* ==================================================
142
+ Frame / Live
143
+ ================================================== */
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+ /* ==================================================
188
+ Heatmap
189
+ ================================================== */
190
+
191
+ body.jf-page-heatmap .jf-shell {
192
+ display: grid;
193
+ grid-template-rows: auto auto auto minmax(0, 1fr) 160px;
194
+ gap: 9px;
195
+ }
196
+
197
+ body.jf-page-heatmap .header {
198
+ display: grid;
199
+ grid-template-columns: minmax(0,1fr) auto;
200
+ align-items: center;
201
+ gap: 12px;
202
+ }
203
+
204
+ body.jf-page-heatmap .title {
205
+ font-size: clamp(25px, 5vw, 42px);
206
+ font-weight: 950;
207
+ letter-spacing: -.055em;
208
+ line-height: .95;
209
+ }
210
+
211
+ body.jf-page-heatmap .sub {
212
+ margin-top: 4px;
213
+ color: var(--muted);
214
+ font-size: clamp(12px, 1.6vw, 16px);
215
+ font-weight: 700;
216
+ }
217
+
218
+ body.jf-page-heatmap .livePill {
219
+ padding: 7px 13px;
220
+ border-radius: 999px;
221
+ background: rgba(53,230,107,.13);
222
+ border: 1px solid rgba(53,230,107,.28);
223
+ color: rgba(210,255,225,.92);
224
+ font-size: 12px;
225
+ font-weight: 900;
226
+ white-space: nowrap;
227
+ }
228
+
229
+ body.jf-page-heatmap .stats {
230
+ display: grid;
231
+ grid-template-columns: repeat(4, minmax(0, 1fr));
232
+ gap: 8px;
233
+ }
234
+
235
+ body.jf-page-heatmap .stat {
236
+ min-height: 44px;
237
+ border-radius: 18px;
238
+ background: rgba(255,255,255,.07);
239
+ border: 1px solid rgba(255,255,255,.12);
240
+ display: flex;
241
+ flex-direction: column;
242
+ align-items: center;
243
+ justify-content: center;
244
+ padding: 5px 6px;
245
+ overflow: hidden;
246
+ }
247
+
248
+ body.jf-page-heatmap .value {
249
+ font-size: clamp(24px, 5vw, 38px);
250
+ font-weight: 950;
251
+ letter-spacing: -.05em;
252
+ line-height: .9;
253
+ }
254
+
255
+ body.jf-page-heatmap .label {
256
+ margin-top: 4px;
257
+ font-size: 7px;
258
+ letter-spacing: .13em;
259
+ color: var(--muted);
260
+ font-weight: 850;
261
+ white-space: nowrap;
262
+ }
263
+
264
+ body.jf-page-heatmap .rush {
265
+ min-height: 38px;
266
+ max-height: 42px;
267
+ border-radius: 18px;
268
+ padding: 7px 12px;
269
+ background: rgba(255,216,77,.10);
270
+ border: 1px solid rgba(255,216,77,.22);
271
+ color: rgba(255,240,170,.94);
272
+ font-size: clamp(13px, 2.4vw, 18px);
273
+ font-weight: 900;
274
+ display: flex;
275
+ align-items: center;
276
+ justify-content: space-between;
277
+ gap: 10px;
278
+ white-space: nowrap;
279
+ overflow: hidden;
280
+ }
281
+
282
+ body.jf-page-heatmap .rush span {
283
+ min-width: 0;
284
+ overflow: hidden;
285
+ text-overflow: ellipsis;
286
+ }
287
+
288
+ body.jf-page-heatmap .scroller {
289
+ min-height: 0;
290
+ height: 100%;
291
+ display: flex;
292
+ align-items: stretch;
293
+ gap: 12px;
294
+ overflow-x: auto;
295
+ overflow-y: hidden;
296
+ scroll-snap-type: x mandatory;
297
+ padding: 0 4px 4px;
298
+ -webkit-overflow-scrolling: touch;
299
+ }
300
+
301
+ body.jf-page-heatmap .scroller::-webkit-scrollbar {
302
+ display: none;
303
+ }
304
+
305
+ body.jf-page-heatmap .hourCard {
306
+ scroll-snap-align: center;
307
+ flex: 0 0 min(430px, 74vw);
308
+ height: 100%;
309
+ min-height: 0;
310
+ border-radius: 26px;
311
+ padding: 16px;
312
+ background: rgba(255,255,255,.075);
313
+ border: 1px solid rgba(255,255,255,.12);
314
+ position: relative;
315
+ overflow: hidden;
316
+ display: flex;
317
+ align-items: stretch;
318
+ }
319
+
320
+ body.jf-page-heatmap .hourCard::before {
321
+ content: "";
322
+ position: absolute;
323
+ inset: 0;
324
+ opacity: var(--heat, .08);
325
+ background:
326
+ radial-gradient(circle at 50% 0%, rgba(53,230,107,.9), transparent 62%),
327
+ linear-gradient(145deg, rgba(86,168,255,.7), rgba(255,216,77,.6));
328
+ pointer-events: none;
329
+ }
330
+
331
+ body.jf-page-heatmap .hourCard.now {
332
+ border-color: rgba(53,230,107,.4);
333
+ box-shadow: 0 0 28px rgba(53,230,107,.16);
334
+ }
335
+
336
+ body.jf-page-heatmap .hourInner {
337
+ position: relative;
338
+ z-index: 2;
339
+ width: 100%;
340
+ display: flex;
341
+ flex-direction: column;
342
+ }
343
+
344
+ body.jf-page-heatmap .hourTop {
345
+ display: flex;
346
+ justify-content: space-between;
347
+ align-items: center;
348
+ gap: 12px;
349
+ }
350
+
351
+ body.jf-page-heatmap .hour {
352
+ font-size: clamp(34px, 8vw, 66px);
353
+ font-weight: 950;
354
+ letter-spacing: -.055em;
355
+ line-height: .95;
356
+ }
357
+
358
+ body.jf-page-heatmap .badge {
359
+ padding: 5px 9px;
360
+ border-radius: 999px;
361
+ background: rgba(0,0,0,.22);
362
+ border: 1px solid rgba(255,255,255,.13);
363
+ color: rgba(255,255,255,.78);
364
+ font-size: clamp(10px, 1.7vw, 14px);
365
+ font-weight: 850;
366
+ white-space: nowrap;
367
+ }
368
+
369
+ body.jf-page-heatmap .hourTotal {
370
+ font-size: clamp(78px, 17vw, 138px);
371
+ line-height: .82;
372
+ font-weight: 950;
373
+ letter-spacing: -.075em;
374
+ margin-top: auto;
375
+ }
376
+
377
+ body.jf-page-heatmap .hourSub {
378
+ margin-top: 8px;
379
+ color: var(--muted);
380
+ font-size: clamp(16px, 3.2vw, 26px);
381
+ font-weight: 800;
382
+ }
383
+
384
+ body.jf-page-heatmap .bars {
385
+ display: grid;
386
+ grid-template-columns: repeat(3, 1fr);
387
+ gap: 8px;
388
+ margin-top: auto;
389
+ }
390
+
391
+ body.jf-page-heatmap .bar {
392
+ height: 42px;
393
+ border-radius: 14px;
394
+ background: rgba(255,255,255,.10);
395
+ border: 1px solid rgba(255,255,255,.12);
396
+ display: flex;
397
+ align-items: center;
398
+ justify-content: center;
399
+ font-weight: 900;
400
+ font-size: clamp(12px, 2.2vw, 18px);
401
+ }
402
+
403
+ body.jf-page-heatmap .rankings {
404
+ min-height: 0;
405
+ display: grid;
406
+ grid-template-columns: 1fr 1fr;
407
+ gap: 10px;
408
+ }
409
+
410
+ body.jf-page-heatmap .panel {
411
+ min-height: 0;
412
+ height: 100%;
413
+ border-radius: 20px;
414
+ background: rgba(255,255,255,.075);
415
+ border: 1px solid rgba(255,255,255,.12);
416
+ padding: 12px 14px;
417
+ overflow: hidden;
418
+ }
419
+
420
+ body.jf-page-heatmap .panel h3 {
421
+ margin: 0 0 8px;
422
+ font-size: clamp(13px, 2vw, 17px);
423
+ letter-spacing: .10em;
424
+ color: var(--muted);
425
+ text-transform: uppercase;
426
+ }
427
+
428
+ body.jf-page-heatmap .panel pre {
429
+ margin: 0;
430
+ white-space: pre-wrap;
431
+ font-family: inherit;
432
+ font-size: clamp(12px, 1.8vw, 16px);
433
+ line-height: 1.18;
434
+ font-weight: 800;
435
+ color: rgba(255,255,255,.90);
436
+ }
437
+
438
+ body.jf-page-heatmap .footer {
439
+ display: none;
440
+ }
441
+
442
+ @media (orientation: landscape) {
443
+ body.jf-page-heatmap .jf-shell {
444
+ padding: 14px 26px !important;
445
+ grid-template-rows: auto auto auto minmax(0, 1fr) 108px !important;
446
+ gap: 8px !important;
447
+ }
448
+
449
+ body.jf-page-heatmap .stats {
450
+ grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
451
+ gap: 10px !important;
452
+ }
453
+
454
+ body.jf-page-heatmap .stat {
455
+ min-height: 48px !important;
456
+ border-radius: 17px !important;
457
+ padding: 4px 8px !important;
458
+ }
459
+
460
+ body.jf-page-heatmap .value {
461
+ font-size: clamp(24px, 3.1vw, 34px) !important;
462
+ }
463
+
464
+ body.jf-page-heatmap .rush {
465
+ min-height: 34px !important;
466
+ max-height: 36px !important;
467
+ padding: 6px 14px !important;
468
+ font-size: clamp(13px, 1.55vw, 18px) !important;
469
+ }
470
+
471
+ body.jf-page-heatmap .hourCard {
472
+ flex: 0 0 min(340px, 32vw) !important;
473
+ border-radius: 22px !important;
474
+ padding: 15px 18px !important;
475
+ }
476
+
477
+ body.jf-page-heatmap .hour {
478
+ font-size: clamp(30px, 3.8vw, 50px) !important;
479
+ }
480
+
481
+ body.jf-page-heatmap .hourTotal {
482
+ font-size: clamp(58px, 6.8vw, 92px) !important;
483
+ }
484
+
485
+ body.jf-page-heatmap .hourSub {
486
+ font-size: clamp(14px, 1.7vw, 20px) !important;
487
+ }
488
+
489
+ body.jf-page-heatmap .bar {
490
+ height: 34px !important;
491
+ border-radius: 12px !important;
492
+ font-size: 13px !important;
493
+ }
494
+
495
+ body.jf-page-heatmap .rankings {
496
+ height: 108px !important;
497
+ }
498
+
499
+ body.jf-page-heatmap .panel {
500
+ border-radius: 18px !important;
501
+ padding: 10px 14px !important;
502
+ }
503
+
504
+ body.jf-page-heatmap .panel h3 {
505
+ font-size: 12px !important;
506
+ margin-bottom: 5px !important;
507
+ }
508
+
509
+ body.jf-page-heatmap .panel pre {
510
+ font-size: clamp(11px, 1.25vw, 14px) !important;
511
+ line-height: 1.12 !important;
512
+ }
513
+ }
514
+
515
+
516
+ /* ==================================================
517
+ Stats
518
+ ================================================== */
519
+
520
+ body.jf-page-stats .jf-shell {
521
+ display: grid;
522
+ grid-template-rows: auto auto 1fr;
523
+ gap: 10px;
524
+ }
525
+
526
+ body.jf-page-stats .header {
527
+ display: flex;
528
+ align-items: flex-start;
529
+ justify-content: space-between;
530
+ gap: 12px;
531
+ }
532
+
533
+ body.jf-page-stats .title {
534
+ font-size: clamp(24px, 4.5vw, 42px);
535
+ font-weight: 950;
536
+ letter-spacing: -.055em;
537
+ line-height: .95;
538
+ }
539
+
540
+ body.jf-page-stats .sub {
541
+ margin-top: 4px;
542
+ color: var(--muted);
543
+ font-size: clamp(12px, 1.6vw, 16px);
544
+ font-weight: 700;
545
+ }
546
+
547
+ body.jf-page-stats .grid {
548
+ display: grid;
549
+ grid-template-columns: repeat(3, 1fr);
550
+ gap: 10px;
551
+ }
552
+
553
+ body.jf-page-stats .stat {
554
+ min-height: 78px;
555
+ border-radius: 22px;
556
+ background: rgba(255,255,255,.075);
557
+ border: 1px solid rgba(255,255,255,.12);
558
+ padding: 12px;
559
+ display: flex;
560
+ flex-direction: column;
561
+ justify-content: center;
562
+ overflow: hidden;
563
+ }
564
+
565
+ body.jf-page-stats .stat.big {
566
+ background: linear-gradient(145deg, rgba(86,168,255,.20), rgba(53,230,107,.11));
567
+ }
568
+
569
+ body.jf-page-stats .stat.warn {
570
+ background: linear-gradient(145deg, rgba(255,216,77,.20), rgba(255,90,90,.10));
571
+ }
572
+
573
+ body.jf-page-stats .label {
574
+ color: var(--muted);
575
+ font-size: 10px;
576
+ font-weight: 850;
577
+ letter-spacing: .13em;
578
+ text-transform: uppercase;
579
+ white-space: nowrap;
580
+ }
581
+
582
+ body.jf-page-stats .value {
583
+ margin-top: 5px;
584
+ font-size: clamp(24px, 4vw, 42px);
585
+ font-weight: 950;
586
+ line-height: .9;
587
+ letter-spacing: -.055em;
588
+ white-space: nowrap;
589
+ overflow: hidden;
590
+ text-overflow: ellipsis;
591
+ }
592
+
593
+ body.jf-page-stats .small {
594
+ margin-top: 4px;
595
+ color: var(--muted);
596
+ font-size: 12px;
597
+ font-weight: 700;
598
+ white-space: nowrap;
599
+ overflow: hidden;
600
+ text-overflow: ellipsis;
601
+ }
602
+
603
+ body.jf-page-stats .panels {
604
+ min-height: 0;
605
+ display: grid;
606
+ grid-template-columns: 1fr 1fr;
607
+ grid-template-rows: 1fr 1fr;
608
+ gap: 10px;
609
+ }
610
+
611
+ body.jf-page-stats .panel {
612
+ min-height: 0;
613
+ border-radius: 22px;
614
+ background: rgba(255,255,255,.07);
615
+ border: 1px solid rgba(255,255,255,.11);
616
+ padding: 12px;
617
+ overflow: hidden;
618
+ }
619
+
620
+ body.jf-page-stats .panel h3 {
621
+ margin: 0 0 8px;
622
+ color: var(--muted);
623
+ font-size: 12px;
624
+ font-weight: 900;
625
+ letter-spacing: .12em;
626
+ text-transform: uppercase;
627
+ }
628
+
629
+ body.jf-page-stats .panel pre {
630
+ margin: 0;
631
+ font-family: inherit;
632
+ font-size: clamp(10px, 1.4vw, 15px);
633
+ line-height: 1.22;
634
+ font-weight: 760;
635
+ color: rgba(255,255,255,.9);
636
+ white-space: pre-wrap;
637
+ }
638
+
639
+ @media (orientation: portrait) {
640
+ body.jf-page-stats .grid {
641
+ grid-template-columns: repeat(2, 1fr);
642
+ }
643
+
644
+ body.jf-page-stats .panels {
645
+ grid-template-columns: 1fr;
646
+ grid-template-rows: repeat(4, 1fr);
647
+ }
648
+ }
649
+
650
+
651
+
652
+ /* ==================================================
653
+ Home
654
+ ================================================== */
655
+
656
+ body.jf-page-home .jf-shell {
657
+ display: flex;
658
+ flex-direction: column;
659
+ gap: 18px;
660
+ }
661
+
662
+ body.jf-page-home .hero {
663
+ flex: 1 1 auto;
664
+ display: flex;
665
+ flex-direction: column;
666
+ justify-content: center;
667
+ min-height: 0;
668
+ }
669
+
670
+ body.jf-page-home .logo {
671
+ font-size: clamp(54px, 14vw, 96px);
672
+ line-height: .9;
673
+ margin-bottom: 14px;
674
+ }
675
+
676
+ body.jf-page-home h1 {
677
+ margin: 0;
678
+ font-size: clamp(42px, 11vw, 76px);
679
+ line-height: .88;
680
+ letter-spacing: -.07em;
681
+ font-weight: 950;
682
+ }
683
+
684
+ body.jf-page-home .sub {
685
+ margin-top: 14px;
686
+ color: var(--muted);
687
+ font-size: clamp(17px, 4vw, 28px);
688
+ font-weight: 750;
689
+ }
690
+
691
+ body.jf-page-home .status,
692
+ body.jf-page-home [id="statusText"] {
693
+ display: inline-flex;
694
+ align-items: center;
695
+ justify-content: center;
696
+ width: fit-content;
697
+ max-width: 92%;
698
+ margin: 18px auto 0 auto;
699
+ padding: 9px 18px;
700
+ border-radius: 999px;
701
+ background: rgba(53,230,107,.13);
702
+ border: 1px solid rgba(53,230,107,.28);
703
+ color: rgba(210,255,225,.94);
704
+ font-size: clamp(11px, 2vw, 15px);
705
+ font-weight: 850;
706
+ line-height: 1;
707
+ white-space: nowrap;
708
+ overflow: hidden;
709
+ text-overflow: ellipsis;
710
+ }
711
+
712
+ body.jf-page-home .buttons {
713
+ display: grid;
714
+ grid-template-columns: 1fr;
715
+ gap: 12px;
716
+ }
717
+
718
+ body.jf-page-home a {
719
+ text-decoration: none;
720
+ color: white;
721
+ }
722
+
723
+ body.jf-page-home .btn {
724
+ border-radius: 26px;
725
+ padding: 20px;
726
+ background: rgba(255,255,255,.085);
727
+ border: 1px solid rgba(255,255,255,.14);
728
+ display: flex;
729
+ align-items: center;
730
+ justify-content: space-between;
731
+ gap: 14px;
732
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.12);
733
+ }
734
+
735
+ body.jf-page-home .btn.primary {
736
+ background: linear-gradient(145deg, rgba(86,168,255,.40), rgba(53,230,107,.24));
737
+ border-color: rgba(86,168,255,.34);
738
+ }
739
+
740
+ body.jf-page-home .btn.heat {
741
+ background: linear-gradient(145deg, rgba(255,216,77,.32), rgba(255,90,90,.20));
742
+ border-color: rgba(255,216,77,.30);
743
+ }
744
+
745
+ body.jf-page-home .btnTitle {
746
+ font-size: clamp(22px, 5vw, 34px);
747
+ font-weight: 920;
748
+ letter-spacing: -.035em;
749
+ }
750
+
751
+ body.jf-page-home .btnSub {
752
+ margin-top: 4px;
753
+ color: var(--muted);
754
+ font-size: clamp(12px, 2.8vw, 16px);
755
+ font-weight: 700;
756
+ }
757
+
758
+ body.jf-page-home .arrow {
759
+ font-size: 28px;
760
+ font-weight: 700;
761
+ color: rgba(255,255,255,.82);
762
+ }
763
+
764
+ body.jf-page-home .stats {
765
+ display: grid;
766
+ grid-template-columns: repeat(3, 1fr);
767
+ gap: 10px;
768
+ }
769
+
770
+ body.jf-page-home .stat {
771
+ min-height: 70px;
772
+ border-radius: 20px;
773
+ background: rgba(255,255,255,.075);
774
+ border: 1px solid rgba(255,255,255,.12);
775
+ display: flex;
776
+ flex-direction: column;
777
+ align-items: center;
778
+ justify-content: center;
779
+ }
780
+
781
+ body.jf-page-home .value {
782
+ font-size: clamp(28px, 6vw, 46px);
783
+ font-weight: 950;
784
+ line-height: .9;
785
+ letter-spacing: -.05em;
786
+ }
787
+
788
+ body.jf-page-home .label {
789
+ margin-top: 5px;
790
+ font-size: 10px;
791
+ letter-spacing: .16em;
792
+ color: var(--muted);
793
+ font-weight: 850;
794
+ }
795
+
796
+ body.jf-page-home .footer {
797
+ color: rgba(255,255,255,.86);
798
+ font-size: 14px;
799
+ font-weight: 600;
800
+ }
801
+
802
+ @media (orientation: landscape) {
803
+ body.jf-page-home .jf-shell {
804
+ display: grid;
805
+ grid-template-columns: 40% 60%;
806
+ grid-template-rows: 1fr auto;
807
+ gap: 14px;
808
+ padding: 18px;
809
+ }
810
+
811
+ body.jf-page-home .hero {
812
+ grid-column: 1;
813
+ grid-row: 1 / span 2;
814
+ justify-content: center;
815
+ align-items: flex-start;
816
+ }
817
+
818
+ body.jf-page-home .buttons {
819
+ grid-column: 2;
820
+ grid-row: 1;
821
+ align-self: center;
822
+ gap: 10px;
823
+ }
824
+
825
+ body.jf-page-home .btn {
826
+ min-height: 72px;
827
+ padding: 14px 18px;
828
+ border-radius: 22px;
829
+ }
830
+
831
+ body.jf-page-home .btnTitle {
832
+ font-size: clamp(24px, 3.2vw, 40px);
833
+ }
834
+
835
+ body.jf-page-home .btnSub {
836
+ font-size: clamp(12px, 1.5vw, 18px);
837
+ }
838
+
839
+ body.jf-page-home .stats {
840
+ grid-column: 2;
841
+ grid-row: 2;
842
+ }
843
+
844
+ body.jf-page-home .stat {
845
+ min-height: 44px;
846
+ border-radius: 16px;
847
+ }
848
+
849
+ body.jf-page-home .value {
850
+ font-size: clamp(24px, 3.2vw, 38px);
851
+ }
852
+
853
+ body.jf-page-home .label {
854
+ font-size: 8px;
855
+ }
856
+
857
+ body.jf-page-home .status,
858
+ body.jf-page-home [id="statusText"] {
859
+ margin: 12px 0 0 0;
860
+ padding: 7px 14px;
861
+ font-size: clamp(8px, 1.15vw, 12px);
862
+ max-width: 100%;
863
+ }
864
+
865
+ body.jf-page-home .footer {
866
+ position: absolute;
867
+ left: 22px;
868
+ bottom: 16px;
869
+ margin: 0;
870
+ font-size: 12px;
871
+ }
872
+ }
873
+
874
+ @keyframes radarSpin {
875
+ to { transform: rotate(360deg); }
876
+ }
877
+
878
+ @keyframes idleFloat {
879
+ 0%,100% { transform: translateY(0) rotate(-8deg); }
880
+ 50% { transform: translateY(-9px) rotate(-2deg); }
881
+ }
882
+
883
+
884
+ /* ==================================================
885
+ Home final shell layout
886
+ ================================================== */
887
+
888
+ body.jf-page-home .jf-shell {
889
+ display: flex;
890
+ flex-direction: column;
891
+ gap: 18px;
892
+ }
893
+
894
+ body.jf-page-home .hero {
895
+ flex: 1 1 auto;
896
+ display: flex;
897
+ flex-direction: column;
898
+ justify-content: center;
899
+ min-height: 0;
900
+ }
901
+
902
+ body.jf-page-home .logo {
903
+ font-size: clamp(54px, 14vw, 96px);
904
+ line-height: .9;
905
+ margin-bottom: 14px;
906
+ }
907
+
908
+ body.jf-page-home h1 {
909
+ margin: 0;
910
+ font-size: clamp(42px, 11vw, 76px);
911
+ line-height: .88;
912
+ letter-spacing: -.07em;
913
+ font-weight: 950;
914
+ }
915
+
916
+ body.jf-page-home .sub {
917
+ margin-top: 14px;
918
+ color: var(--muted);
919
+ font-size: clamp(17px, 4vw, 28px);
920
+ font-weight: 750;
921
+ }
922
+
923
+ body.jf-page-home .status,
924
+ body.jf-page-home [id="statusText"] {
925
+ display: inline-flex;
926
+ align-items: center;
927
+ justify-content: center;
928
+ width: fit-content;
929
+ max-width: 92%;
930
+ margin: 18px auto 0 auto;
931
+ padding: 9px 18px;
932
+ border-radius: 999px;
933
+ background: rgba(53,230,107,.13);
934
+ border: 1px solid rgba(53,230,107,.28);
935
+ color: rgba(210,255,225,.94);
936
+ font-size: clamp(11px, 2vw, 15px);
937
+ font-weight: 850;
938
+ line-height: 1;
939
+ white-space: nowrap;
940
+ overflow: hidden;
941
+ text-overflow: ellipsis;
942
+ }
943
+
944
+ body.jf-page-home .buttons {
945
+ display: grid;
946
+ grid-template-columns: 1fr;
947
+ gap: 12px;
948
+ }
949
+
950
+ body.jf-page-home a {
951
+ text-decoration: none;
952
+ color: white;
953
+ }
954
+
955
+ body.jf-page-home .btn {
956
+ border-radius: 26px;
957
+ padding: 20px;
958
+ background: rgba(255,255,255,.085);
959
+ border: 1px solid rgba(255,255,255,.14);
960
+ display: flex;
961
+ align-items: center;
962
+ justify-content: space-between;
963
+ gap: 14px;
964
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.12);
965
+ }
966
+
967
+ body.jf-page-home .btn.primary {
968
+ background: linear-gradient(145deg, rgba(86,168,255,.40), rgba(53,230,107,.24));
969
+ border-color: rgba(86,168,255,.34);
970
+ }
971
+
972
+ body.jf-page-home .btn.heat {
973
+ background: linear-gradient(145deg, rgba(255,216,77,.32), rgba(255,90,90,.20));
974
+ border-color: rgba(255,216,77,.30);
975
+ }
976
+
977
+ body.jf-page-home .btnTitle {
978
+ font-size: clamp(22px, 5vw, 34px);
979
+ font-weight: 920;
980
+ letter-spacing: -.035em;
981
+ }
982
+
983
+ body.jf-page-home .btnSub {
984
+ margin-top: 4px;
985
+ color: var(--muted);
986
+ font-size: clamp(12px, 2.8vw, 16px);
987
+ font-weight: 700;
988
+ }
989
+
990
+ body.jf-page-home .arrow {
991
+ font-size: 28px;
992
+ font-weight: 700;
993
+ color: rgba(255,255,255,.82);
994
+ }
995
+
996
+ body.jf-page-home .stats {
997
+ display: grid;
998
+ grid-template-columns: repeat(3, 1fr);
999
+ gap: 10px;
1000
+ }
1001
+
1002
+ body.jf-page-home .stat {
1003
+ min-height: 70px;
1004
+ border-radius: 20px;
1005
+ background: rgba(255,255,255,.075);
1006
+ border: 1px solid rgba(255,255,255,.12);
1007
+ display: flex;
1008
+ flex-direction: column;
1009
+ align-items: center;
1010
+ justify-content: center;
1011
+ }
1012
+
1013
+ body.jf-page-home .value {
1014
+ font-size: clamp(28px, 6vw, 46px);
1015
+ font-weight: 950;
1016
+ line-height: .9;
1017
+ letter-spacing: -.05em;
1018
+ }
1019
+
1020
+ body.jf-page-home .label {
1021
+ margin-top: 5px;
1022
+ font-size: 10px;
1023
+ letter-spacing: .16em;
1024
+ color: var(--muted);
1025
+ font-weight: 850;
1026
+ }
1027
+
1028
+ body.jf-page-home .footer {
1029
+ color: rgba(255,255,255,.86);
1030
+ font-size: 14px;
1031
+ font-weight: 600;
1032
+ }
1033
+
1034
+ @media (orientation: landscape) {
1035
+ body.jf-page-home .jf-shell {
1036
+ display: grid;
1037
+ grid-template-columns: 40% 60%;
1038
+ grid-template-rows: 1fr auto;
1039
+ gap: 14px;
1040
+ padding: 18px;
1041
+ }
1042
+
1043
+ body.jf-page-home .hero {
1044
+ grid-column: 1;
1045
+ grid-row: 1 / span 2;
1046
+ justify-content: center;
1047
+ align-items: flex-start;
1048
+ }
1049
+
1050
+ body.jf-page-home .buttons {
1051
+ grid-column: 2;
1052
+ grid-row: 1;
1053
+ align-self: center;
1054
+ gap: 10px;
1055
+ }
1056
+
1057
+ body.jf-page-home .stats {
1058
+ grid-column: 2;
1059
+ grid-row: 2;
1060
+ }
1061
+
1062
+ body.jf-page-home .btn {
1063
+ min-height: 72px;
1064
+ padding: 14px 18px;
1065
+ border-radius: 22px;
1066
+ }
1067
+
1068
+ body.jf-page-home .stat {
1069
+ min-height: 44px;
1070
+ border-radius: 16px;
1071
+ }
1072
+
1073
+ body.jf-page-home .status,
1074
+ body.jf-page-home [id="statusText"] {
1075
+ margin: 12px 0 0 0;
1076
+ padding: 7px 14px;
1077
+ font-size: clamp(8px, 1.15vw, 12px);
1078
+ max-width: 100%;
1079
+ }
1080
+
1081
+ body.jf-page-home .footer {
1082
+ position: absolute;
1083
+ left: 22px;
1084
+ bottom: 16px;
1085
+ margin: 0;
1086
+ font-size: 12px;
1087
+ }
1088
+ }
1089
+
1090
+ /* ==================================================
1091
+ HOME LANDSCAPE STATS FINAL
1092
+ ================================================== */
1093
+
1094
+ @media (orientation: landscape) {
1095
+ body.jf-page-home .jf-shell {
1096
+ grid-template-rows: minmax(0, 1fr) 54px !important;
1097
+ gap: 10px !important;
1098
+ padding-bottom: 12px !important;
1099
+ }
1100
+
1101
+ body.jf-page-home .stats {
1102
+ align-self: end !important;
1103
+ height: 54px !important;
1104
+ }
1105
+
1106
+ body.jf-page-home .stat {
1107
+ min-height: 54px !important;
1108
+ height: 54px !important;
1109
+ padding: 4px 8px !important;
1110
+ }
1111
+
1112
+ body.jf-page-home .value {
1113
+ font-size: clamp(24px, 3vw, 34px) !important;
1114
+ line-height: .9 !important;
1115
+ }
1116
+
1117
+ body.jf-page-home .label {
1118
+ margin-top: 3px !important;
1119
+ font-size: 7px !important;
1120
+ line-height: 1 !important;
1121
+ }
1122
+
1123
+ body.jf-page-home .footer {
1124
+ bottom: 10px !important;
1125
+ }
1126
+ }
1127
+
1128
+
1129
+
1130
+
1131
+ /* ==================================================
1132
+ HEATMAP FINAL MICRO REPLACE
1133
+ ================================================== */
1134
+
1135
+ /* Backbutton wirklich in die Header-Reihe */
1136
+ body.jf-page-heatmap .header {
1137
+ display: grid !important;
1138
+ grid-template-columns: 34px minmax(0, 1fr) auto !important;
1139
+ align-items: center !important;
1140
+ gap: 10px !important;
1141
+ padding-left: 0 !important;
1142
+ position: relative !important;
1143
+ }
1144
+
1145
+ body.jf-page-heatmap .backBtn {
1146
+ position: static !important;
1147
+ width: 34px !important;
1148
+ height: 34px !important;
1149
+ flex: 0 0 34px !important;
1150
+ margin: 0 !important;
1151
+ z-index: 10 !important;
1152
+ }
1153
+
1154
+ @media (orientation: portrait) {
1155
+ body.jf-page-heatmap .header {
1156
+ grid-template-columns: 34px minmax(0, 1fr) auto !important;
1157
+ }
1158
+
1159
+ body.jf-page-heatmap .title {
1160
+ font-size: clamp(24px, 6vw, 34px) !important;
1161
+ }
1162
+
1163
+ body.jf-page-heatmap .sub {
1164
+ font-size: clamp(12px, 3vw, 15px) !important;
1165
+ }
1166
+ }
1167
+
1168
+ /* Querformat: links Swipe groß, rechts Ranking klein passend */
1169
+ @media (orientation: landscape) {
1170
+ body.jf-page-heatmap .jf-shell {
1171
+ display: grid !important;
1172
+ grid-template-columns: minmax(0, 58%) minmax(0, 42%) !important;
1173
+ grid-template-rows: auto 48px 34px minmax(0, 1fr) !important;
1174
+ gap: 8px 14px !important;
1175
+ padding: 14px 26px !important;
1176
+ }
1177
+
1178
+ body.jf-page-heatmap .header {
1179
+ grid-column: 1 / 3 !important;
1180
+ grid-row: 1 !important;
1181
+ grid-template-columns: 34px minmax(0, 1fr) auto !important;
1182
+ min-height: 36px !important;
1183
+ }
1184
+
1185
+ body.jf-page-heatmap .stats {
1186
+ grid-column: 1 / 3 !important;
1187
+ grid-row: 2 !important;
1188
+ }
1189
+
1190
+ body.jf-page-heatmap .rush {
1191
+ grid-column: 1 / 3 !important;
1192
+ grid-row: 3 !important;
1193
+ height: 34px !important;
1194
+ min-height: 34px !important;
1195
+ max-height: 34px !important;
1196
+ padding: 5px 14px !important;
1197
+ font-size: clamp(13px, 1.45vw, 17px) !important;
1198
+ }
1199
+
1200
+ body.jf-page-heatmap .scroller {
1201
+ grid-column: 1 !important;
1202
+ grid-row: 4 !important;
1203
+ height: 100% !important;
1204
+ min-height: 0 !important;
1205
+ }
1206
+
1207
+ body.jf-page-heatmap .rankings {
1208
+ grid-column: 2 !important;
1209
+ grid-row: 4 !important;
1210
+ display: grid !important;
1211
+ grid-template-columns: 1fr !important;
1212
+ grid-template-rows: 1fr 1fr !important;
1213
+ gap: 10px !important;
1214
+ height: 100% !important;
1215
+ min-height: 0 !important;
1216
+ }
1217
+
1218
+ body.jf-page-heatmap .rankings .panel {
1219
+ padding: 10px 13px !important;
1220
+ overflow: hidden !important;
1221
+ }
1222
+
1223
+ body.jf-page-heatmap .rankings .panel h3 {
1224
+ font-size: 10px !important;
1225
+ line-height: 1 !important;
1226
+ margin: 0 0 5px !important;
1227
+ letter-spacing: 1.8px !important;
1228
+ }
1229
+
1230
+ body.jf-page-heatmap #airlineRanking,
1231
+ body.jf-page-heatmap #routeRanking {
1232
+ font-size: 10px !important;
1233
+ line-height: 1.08 !important;
1234
+ font-weight: 800 !important;
1235
+ letter-spacing: 0 !important;
1236
+ }
1237
+ }
1238
+
1239
+
1240
+ /* ==================================================
1241
+ JETFRAME DESIGN SYSTEM CLEAN V1
1242
+ Einheitliche Header / Pills / Boxen / responsive Text
1243
+ ================================================== */
1244
+
1245
+ @font-face {
1246
+ font-family: "JetFrameSF";
1247
+ src: url("SF-Pro.ttf") format("truetype");
1248
+ font-weight: 100 1000;
1249
+ font-style: normal;
1250
+ font-display: swap;
1251
+ }
1252
+
1253
+ :root {
1254
+ --jf-font: "JetFrameSF", -apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", Arial, sans-serif;
1255
+
1256
+ --jf-text-xs: clamp(8px, 1.05cqw, 12px);
1257
+ --jf-text-sm: clamp(10px, 1.35cqw, 15px);
1258
+ --jf-text-md: clamp(13px, 1.75cqw, 20px);
1259
+ --jf-text-lg: clamp(20px, 3.2cqw, 38px);
1260
+ --jf-text-xl: clamp(30px, 5.2cqw, 64px);
1261
+
1262
+ --jf-radius-shell: clamp(26px, 4cqw, 34px);
1263
+ --jf-radius-box: clamp(18px, 3cqw, 28px);
1264
+
1265
+ --jf-gap: clamp(8px, 1.35cqw, 16px);
1266
+ --jf-pad: clamp(14px, 2.2cqw, 26px);
1267
+
1268
+ --jf-box-bg: rgba(255,255,255,.075);
1269
+ --jf-box-border: 1px solid rgba(255,255,255,.13);
1270
+ }
1271
+
1272
+ html,
1273
+ body,
1274
+ button,
1275
+ input,
1276
+ textarea,
1277
+ select {
1278
+ font-family: var(--jf-font) !important;
1279
+ }
1280
+
1281
+ .card,
1282
+ .wall,
1283
+ .jf-shell {
1284
+ container-type: size;
1285
+ border-radius: var(--jf-radius-shell) !important;
1286
+ padding: var(--jf-pad) !important;
1287
+ overflow: hidden !important;
1288
+ }
1289
+
1290
+ /* ---------- Einheitlicher Header auf allen Unterseiten ---------- */
1291
+
1292
+ body:not(.jf-page-home) .header {
1293
+ display: grid !important;
1294
+ grid-template-columns: clamp(30px, 4cqw, 42px) minmax(0, 1fr) auto !important;
1295
+ grid-template-rows: auto auto !important;
1296
+ column-gap: clamp(8px, 1.3cqw, 14px) !important;
1297
+ align-items: center !important;
1298
+
1299
+ height: clamp(48px, 8cqh, 74px) !important;
1300
+ min-height: clamp(48px, 8cqh, 74px) !important;
1301
+ margin: 0 0 var(--jf-gap) 0 !important;
1302
+ padding: 0 !important;
1303
+ overflow: visible !important;
1304
+ }
1305
+
1306
+ body:not(.jf-page-home) .backBtn {
1307
+ position: static !important;
1308
+ grid-column: 1 !important;
1309
+ grid-row: 1 / span 2 !important;
1310
+ width: clamp(30px, 4cqw, 42px) !important;
1311
+ height: clamp(30px, 4cqw, 42px) !important;
1312
+ margin: 0 !important;
1313
+ align-self: center !important;
1314
+ }
1315
+
1316
+ body:not(.jf-page-home) .header > div:not(.livePill):not(.frameHeaderActions),
1317
+ body:not(.jf-page-home) .headerTitleBlock {
1318
+ grid-column: 2 !important;
1319
+ grid-row: 1 / span 2 !important;
1320
+ min-width: 0 !important;
1321
+ align-self: center !important;
1322
+ overflow: visible !important;
1323
+ }
1324
+
1325
+ body:not(.jf-page-home) .title {
1326
+ margin: 0 !important;
1327
+ padding: 0 !important;
1328
+ font-size: clamp(25px, 4.1cqw, 44px) !important;
1329
+ font-weight: 950 !important;
1330
+ line-height: .98 !important;
1331
+ letter-spacing: -.06em !important;
1332
+ color: #fff !important;
1333
+ white-space: nowrap !important;
1334
+ overflow: visible !important;
1335
+ text-overflow: clip !important;
1336
+ }
1337
+
1338
+ body:not(.jf-page-home) .sub {
1339
+ margin: 1px 0 0 0 !important;
1340
+ font-size: clamp(12px, 1.7cqw, 18px) !important;
1341
+ font-weight: 760 !important;
1342
+ line-height: 1.08 !important;
1343
+ color: rgba(255,255,255,.62) !important;
1344
+ white-space: nowrap !important;
1345
+ overflow: hidden !important;
1346
+ text-overflow: ellipsis !important;
1347
+ }
1348
+
1349
+ /* ---------- Einheitliche Live-Pille ---------- */
1350
+
1351
+ body:not(.jf-page-home) .livePill,
1352
+ body:not(.jf-page-home) .frameLivePill {
1353
+ grid-column: 3 !important;
1354
+ grid-row: 1 / span 2 !important;
1355
+ justify-self: end !important;
1356
+ align-self: center !important;
1357
+
1358
+ display: inline-flex !important;
1359
+ align-items: center !important;
1360
+ justify-content: center !important;
1361
+ gap: .55em !important;
1362
+
1363
+ height: clamp(32px, 4.5cqw, 44px) !important;
1364
+ min-width: clamp(74px, 10cqw, 104px) !important;
1365
+ padding: 0 clamp(12px, 1.7cqw, 18px) !important;
1366
+
1367
+ border-radius: 999px !important;
1368
+ background: rgba(53,230,107,.13) !important;
1369
+ border: 1px solid rgba(53,230,107,.32) !important;
1370
+ box-shadow: 0 0 22px rgba(53,230,107,.14) !important;
1371
+
1372
+ color: rgba(210,255,225,.96) !important;
1373
+ font-size: clamp(13px, 1.75cqw, 18px) !important;
1374
+ font-weight: 900 !important;
1375
+ line-height: 1 !important;
1376
+ }
1377
+
1378
+ body:not(.jf-page-home) .livePill::before,
1379
+ body:not(.jf-page-home) .frameLivePill::before {
1380
+ content: "";
1381
+ width: clamp(8px, 1.2cqw, 12px);
1382
+ height: clamp(8px, 1.2cqw, 12px);
1383
+ border-radius: 50%;
1384
+ background: var(--green);
1385
+ box-shadow: 0 0 14px rgba(53,230,107,.75);
1386
+ }
1387
+
1388
+ body:not(.jf-page-home) .livePill .dot,
1389
+ body:not(.jf-page-home) .frameLivePill .dot {
1390
+ display: none !important;
1391
+ }
1392
+
1393
+ /* Live-Frame: Speaker links neben Live-Pille */
1394
+
1395
+
1396
+
1397
+ /* ---------- Grundbausteine ---------- */
1398
+
1399
+ .jf-box,
1400
+ .stat,
1401
+ .metric,
1402
+ .panel,
1403
+ .hourCard {
1404
+ border-radius: var(--jf-radius-box) !important;
1405
+ background: var(--jf-box-bg) !important;
1406
+ border: var(--jf-box-border) !important;
1407
+ }
1408
+
1409
+ .value,
1410
+ .metricValue,
1411
+ .hourTotal,
1412
+ .iataCallsign {
1413
+ font-weight: 950 !important;
1414
+ line-height: .9 !important;
1415
+ letter-spacing: -.055em !important;
1416
+ }
1417
+
1418
+ .label,
1419
+ .metricLabel,
1420
+ .panel h3 {
1421
+ font-size: var(--jf-text-xs) !important;
1422
+ font-weight: 850 !important;
1423
+ letter-spacing: .16em !important;
1424
+ color: rgba(255,255,255,.62) !important;
1425
+ text-transform: uppercase !important;
1426
+ }
1427
+
1428
+ /* ---------- Live Frame ---------- */
1429
+
1430
+
1431
+
1432
+
1433
+
1434
+
1435
+
1436
+
1437
+ /* Warte-Ansicht ruhiger */
1438
+
1439
+
1440
+ /* ---------- Heatmap ---------- */
1441
+
1442
+ body.jf-page-heatmap .rush {
1443
+ display: grid !important;
1444
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) !important;
1445
+ align-items: center !important;
1446
+ gap: clamp(8px, 1.6cqw, 18px) !important;
1447
+ min-height: clamp(32px, 4.6cqh, 44px) !important;
1448
+ padding: 0 clamp(12px, 2cqw, 22px) !important;
1449
+ font-size: clamp(11px, 1.65cqw, 18px) !important;
1450
+ line-height: 1 !important;
1451
+ white-space: nowrap !important;
1452
+ overflow: hidden !important;
1453
+ }
1454
+
1455
+ body.jf-page-heatmap .rush span {
1456
+ min-width: 0 !important;
1457
+ overflow: hidden !important;
1458
+ text-overflow: ellipsis !important;
1459
+ white-space: nowrap !important;
1460
+ }
1461
+
1462
+ body.jf-page-heatmap .rush span:last-child {
1463
+ text-align: right !important;
1464
+ }
1465
+
1466
+ body.jf-page-heatmap .stat {
1467
+ min-height: clamp(50px, 7.5cqh, 76px) !important;
1468
+ }
1469
+
1470
+ body.jf-page-heatmap .value {
1471
+ font-size: clamp(24px, 5cqw, 42px) !important;
1472
+ }
1473
+
1474
+ body.jf-page-heatmap .hour {
1475
+ font-size: clamp(30px, 5.5cqw, 58px) !important;
1476
+ }
1477
+
1478
+ body.jf-page-heatmap .hourTotal {
1479
+ font-size: clamp(62px, 13cqw, 120px) !important;
1480
+ }
1481
+
1482
+ body.jf-page-heatmap .hourSub {
1483
+ font-size: clamp(14px, 2.4cqw, 24px) !important;
1484
+ }
1485
+
1486
+ body.jf-page-heatmap .panel pre {
1487
+ font-size: clamp(10px, 1.65cqw, 15px) !important;
1488
+ line-height: 1.08 !important;
1489
+ }
1490
+
1491
+ /* ---------- Statistik ---------- */
1492
+
1493
+ body.jf-page-stats .value {
1494
+ font-size: clamp(30px, 5.4cqw, 64px) !important;
1495
+ }
1496
+
1497
+ body.jf-page-stats .small {
1498
+ font-size: clamp(11px, 1.85cqw, 17px) !important;
1499
+ line-height: 1.12 !important;
1500
+ }
1501
+
1502
+ body.jf-page-stats .panel pre {
1503
+ font-size: clamp(9px, 1.45cqw, 14px) !important;
1504
+ line-height: 1.08 !important;
1505
+ overflow: hidden !important;
1506
+ }
1507
+
1508
+ /* ---------- Portrait ---------- */
1509
+
1510
+ @media (orientation: portrait) {
1511
+ .card,
1512
+ .wall,
1513
+ .jf-shell {
1514
+ width: 96vw !important;
1515
+ height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 20px) !important;
1516
+ }
1517
+
1518
+ body.jf-page-heatmap .card,
1519
+ body.jf-page-heatmap .jf-shell {
1520
+ display: grid !important;
1521
+ grid-template-rows:
1522
+ auto
1523
+ auto
1524
+ auto
1525
+ minmax(0, 1fr)
1526
+ clamp(132px, 18cqh, 210px) !important;
1527
+ gap: var(--jf-gap) !important;
1528
+ }
1529
+
1530
+ body.jf-page-heatmap .stats {
1531
+ grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
1532
+ gap: clamp(6px, 1.2cqw, 10px) !important;
1533
+ }
1534
+
1535
+ body.jf-page-heatmap .hourCard {
1536
+ flex: 0 0 clamp(250px, 78cqw, 580px) !important;
1537
+ height: 100% !important;
1538
+ }
1539
+
1540
+ body.jf-page-heatmap .rankings {
1541
+ grid-template-columns: 1fr 1fr !important;
1542
+ gap: var(--jf-gap) !important;
1543
+ }
1544
+
1545
+ body.jf-page-stats .grid {
1546
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
1547
+ gap: var(--jf-gap) !important;
1548
+ }
1549
+
1550
+ body.jf-page-stats .panels {
1551
+ grid-template-columns: 1fr !important;
1552
+ grid-template-rows: 1.05fr 1.15fr 1.25fr 1.25fr !important;
1553
+ gap: var(--jf-gap) !important;
1554
+ min-height: 0 !important;
1555
+ }
1556
+
1557
+ body.jf-page-stats .panel {
1558
+ min-height: 0 !important;
1559
+ overflow: hidden !important;
1560
+ }
1561
+ }
1562
+
1563
+ /* ---------- Landscape ---------- */
1564
+
1565
+ @media (orientation: landscape) {
1566
+ .card,
1567
+ .wall,
1568
+ .jf-shell {
1569
+ width: min(1280px, 92vw) !important;
1570
+ height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 18px) !important;
1571
+ }
1572
+
1573
+ body:not(.jf-page-home) .header {
1574
+ height: clamp(44px, 9cqh, 66px) !important;
1575
+ min-height: clamp(44px, 9cqh, 66px) !important;
1576
+ }
1577
+
1578
+ body:not(.jf-page-home) .title {
1579
+ font-size: clamp(26px, 3.8cqw, 48px) !important;
1580
+ }
1581
+
1582
+ body:not(.jf-page-home) .sub {
1583
+ font-size: clamp(11px, 1.25cqw, 17px) !important;
1584
+ }
1585
+
1586
+ body.jf-page-heatmap .card,
1587
+ body.jf-page-heatmap .jf-shell {
1588
+ display: grid !important;
1589
+ grid-template-columns: minmax(0, .56fr) minmax(250px, .44fr) !important;
1590
+ grid-template-rows: auto auto auto minmax(0, 1fr) !important;
1591
+ gap: clamp(7px, 1.2cqh, 12px) clamp(12px, 1.5cqw, 20px) !important;
1592
+ }
1593
+
1594
+ body.jf-page-heatmap .header,
1595
+ body.jf-page-heatmap .stats,
1596
+ body.jf-page-heatmap .rush {
1597
+ grid-column: 1 / -1 !important;
1598
+ }
1599
+
1600
+ body.jf-page-heatmap .stats {
1601
+ grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
1602
+ }
1603
+
1604
+ body.jf-page-heatmap .scroller {
1605
+ grid-column: 1 !important;
1606
+ grid-row: 4 !important;
1607
+ min-height: 0 !important;
1608
+ height: 100% !important;
1609
+ }
1610
+
1611
+ body.jf-page-heatmap .hourCard {
1612
+ flex: 0 0 clamp(210px, 25cqw, 340px) !important;
1613
+ height: 100% !important;
1614
+ }
1615
+
1616
+ body.jf-page-heatmap .hourTotal {
1617
+ font-size: clamp(48px, 6cqw, 88px) !important;
1618
+ }
1619
+
1620
+ body.jf-page-heatmap .rankings {
1621
+ grid-column: 2 !important;
1622
+ grid-row: 4 !important;
1623
+ grid-template-columns: 1fr !important;
1624
+ grid-template-rows: 1fr 1fr !important;
1625
+ min-height: 0 !important;
1626
+ }
1627
+
1628
+ body.jf-page-heatmap .panel pre {
1629
+ font-size: clamp(8px, .95cqw, 13px) !important;
1630
+ }
1631
+
1632
+ body.jf-page-stats .card,
1633
+ body.jf-page-stats .jf-shell {
1634
+ display: grid !important;
1635
+ grid-template-columns: minmax(0, .57fr) minmax(280px, .43fr) !important;
1636
+ grid-template-rows: auto minmax(0, 1fr) !important;
1637
+ gap: clamp(8px, 1.25cqh, 12px) clamp(12px, 1.6cqw, 20px) !important;
1638
+ }
1639
+
1640
+ body.jf-page-stats .header {
1641
+ grid-column: 1 / -1 !important;
1642
+ }
1643
+
1644
+ body.jf-page-stats .grid {
1645
+ grid-column: 1 !important;
1646
+ grid-row: 2 !important;
1647
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
1648
+ grid-template-rows: repeat(3, minmax(0, 1fr)) !important;
1649
+ min-height: 0 !important;
1650
+ gap: var(--jf-gap) !important;
1651
+ }
1652
+
1653
+ body.jf-page-stats .panels {
1654
+ grid-column: 2 !important;
1655
+ grid-row: 2 !important;
1656
+ grid-template-columns: 1fr !important;
1657
+ grid-template-rows: repeat(4, minmax(0, 1fr)) !important;
1658
+ min-height: 0 !important;
1659
+ gap: var(--jf-gap) !important;
1660
+ }
1661
+
1662
+ body.jf-page-stats .panel {
1663
+ min-height: 0 !important;
1664
+ overflow: hidden !important;
1665
+ }
1666
+
1667
+ body.jf-page-stats .value {
1668
+ font-size: clamp(28px, 4cqw, 56px) !important;
1669
+ }
1670
+
1671
+ body.jf-page-stats .panel pre {
1672
+ font-size: clamp(7px, .8cqw, 11px) !important;
1673
+ line-height: 1.02 !important;
1674
+ }
1675
+ }
1676
+
1677
+ /* ==================================================
1678
+ LIVE TITLE STRONGER
1679
+ ================================================== */
1680
+
1681
+ .liveDirection,
1682
+ .flightDirection,
1683
+ .approachLabel{
1684
+ font-size: clamp(26px, 2.1cqw, 42px) !important;
1685
+ font-weight: 700 !important;
1686
+ line-height: 1.05 !important;
1687
+ letter-spacing: -.01em !important;
1688
+ }
1689
+
1690
+
1691
+ /* ==================================================
1692
+ NO FLIGHT CLEANUP 2026-05-17
1693
+ ================================================== */
1694
+
1695
+ /* Kein Flug: Flight-Überschrift, Logo-Kreis und Airline-Zeile weg */
1696
+
1697
+ /* Kein Flug: Info-Bereich nicht künstlich mit leerem Content füllen */
1698
+
1699
+ /* Runway-Text unten in Info-Bereich als grüne Pille */
1700
+
1701
+
1702
+ /* gelbe Fenster-Pille bei kein Flug weg */
1703
+
1704
+ /* Runway Text IM Bild ausblenden, damit er nicht doppelt ist */
1705
+
1706
+ /* Warte-Text im Bild alleine mittig unten */
1707
+
1708
+ /* Wenn Flug da ist: Placeholder/Radar komplett aus */
1709
+ body:not(.jf-no-flight) #placeholder,
1710
+ body:not(.jf-no-flight) .placeholder,
1711
+ body:not(.jf-no-flight) .radarCircle,
1712
+ body:not(.jf-no-flight) .radarSweep,
1713
+ body:not(.jf-no-flight) .idlePlane,
1714
+ body:not(.jf-no-flight) .idleText,
1715
+ body:not(.jf-no-flight) .idleRunwayText{
1716
+ display:none !important;
1717
+ opacity:0 !important;
1718
+ pointer-events:none !important;
1719
+ }
1720
+
1721
+
1722
+ /* ======================================================
1723
+ HEATMAP FINAL: Top Airlines / Top Routen größer
1724
+ ====================================================== */
1725
+
1726
+ body.jf-page-heatmap .topBox,
1727
+ body.jf-page-heatmap .topListBox,
1728
+ body.jf-page-heatmap .summaryBox{
1729
+ container-type:inline-size;
1730
+ }
1731
+
1732
+ body.jf-page-heatmap .topBox h3,
1733
+ body.jf-page-heatmap .topListBox h3,
1734
+ body.jf-page-heatmap .summaryBox h3{
1735
+ font-size:clamp(18px, 5.4cqw, 26px) !important;
1736
+ line-height:1.05 !important;
1737
+ }
1738
+
1739
+ body.jf-page-heatmap .topBox,
1740
+ body.jf-page-heatmap .topBox *,
1741
+ body.jf-page-heatmap .topListBox,
1742
+ body.jf-page-heatmap .topListBox *,
1743
+ body.jf-page-heatmap .summaryBox,
1744
+ body.jf-page-heatmap .summaryBox *{
1745
+ font-size:clamp(17px, 5.0cqw, 24px) !important;
1746
+ line-height:1.18 !important;
1747
+ }
1748
+
1749
+ @media (orientation:landscape){
1750
+ body.jf-page-heatmap .topBox h3,
1751
+ body.jf-page-heatmap .topListBox h3,
1752
+ body.jf-page-heatmap .summaryBox h3{
1753
+ font-size:clamp(16px, 2.0cqw, 24px) !important;
1754
+ }
1755
+
1756
+ body.jf-page-heatmap .topBox,
1757
+ body.jf-page-heatmap .topBox *,
1758
+ body.jf-page-heatmap .topListBox,
1759
+ body.jf-page-heatmap .topListBox *,
1760
+ body.jf-page-heatmap .summaryBox,
1761
+ body.jf-page-heatmap .summaryBox *{
1762
+ font-size:clamp(15px, 1.7cqw, 22px) !important;
1763
+ line-height:1.16 !important;
1764
+ }
1765
+ }
1766
+
1767
+ /* ======================================================
1768
+ STATS FINAL: echte Textspalten stabil
1769
+ ====================================================== */
1770
+
1771
+ .panel.jf-split-panel pre{
1772
+ display:grid !important;
1773
+ grid-template-columns:repeat(2, minmax(0, 1fr)) !important;
1774
+ column-gap:22px !important;
1775
+ row-gap:2px !important;
1776
+
1777
+ margin:0 !important;
1778
+ white-space:normal !important;
1779
+
1780
+ font-size:clamp(13px, 1.55cqw, 19px) !important;
1781
+ line-height:1.14 !important;
1782
+ font-weight:800 !important;
1783
+ }
1784
+
1785
+ .panel.jf-split-panel pre .jf-line{
1786
+ display:block !important;
1787
+ min-width:0 !important;
1788
+ white-space:nowrap !important;
1789
+ overflow:hidden !important;
1790
+ text-overflow:ellipsis !important;
1791
+ }
1792
+
1793
+ @media (orientation:landscape){
1794
+ .panel.jf-split-panel pre{
1795
+ grid-template-columns:repeat(3, minmax(0, 1fr)) !important;
1796
+ column-gap:24px !important;
1797
+ font-size:clamp(10px, .9cqw, 14px) !important;
1798
+ line-height:1.08 !important;
1799
+ }
1800
+ }
1801
+
1802
+
1803
+
1804
+ /* ======================================================
1805
+ FRAME PAGE CLEAN V1
1806
+ Nur frame.html. Globale JetFrame-Basis bleibt erhalten.
1807
+ ====================================================== */
1808
+
1809
+ html,
1810
+ body.jf-page-frame{
1811
+ width:100%;
1812
+ height:100%;
1813
+ margin:0;
1814
+ overflow:hidden;
1815
+ }
1816
+
1817
+ body.jf-page-frame{
1818
+ min-height:100dvh;
1819
+ background:
1820
+ radial-gradient(circle at 18% 8%, rgba(50,120,255,.22), transparent 34%),
1821
+ radial-gradient(circle at 86% 12%, rgba(255,130,55,.13), transparent 30%),
1822
+ linear-gradient(180deg,#111827 0%,#05060a 76%);
1823
+ }
1824
+
1825
+ body.jf-page-frame #app{
1826
+ width:100vw;
1827
+ height:100dvh;
1828
+ padding:calc(env(safe-area-inset-top) + clamp(8px, 1.8vmin, 18px))
1829
+ calc(env(safe-area-inset-right) + clamp(8px, 1.8vmin, 18px))
1830
+ calc(env(safe-area-inset-bottom) + clamp(8px, 1.8vmin, 18px))
1831
+ calc(env(safe-area-inset-left) + clamp(8px, 1.8vmin, 18px));
1832
+ overflow:hidden;
1833
+ }
1834
+
1835
+ body.jf-page-frame #wall.jf-shell{
1836
+ width:100%;
1837
+ height:100%;
1838
+ max-width:none;
1839
+ max-height:none;
1840
+ margin:0;
1841
+ overflow:hidden;
1842
+ border-radius:clamp(26px, 4vmin, 44px);
1843
+ display:grid;
1844
+ grid-template-rows:auto minmax(0, 1fr);
1845
+ gap:clamp(10px, 1.5vmin, 18px);
1846
+ padding:clamp(12px, 1.8vmin, 24px);
1847
+ }
1848
+
1849
+ body.jf-page-frame .header{
1850
+ min-height:auto;
1851
+ display:grid;
1852
+ grid-template-columns:auto minmax(0, 1fr) auto;
1853
+ align-items:center;
1854
+ gap:clamp(10px, 1.4vmin, 18px);
1855
+ }
1856
+
1857
+ body.jf-page-frame .headerTitleBlock{
1858
+ min-width:0;
1859
+ }
1860
+
1861
+ body.jf-page-frame .title{
1862
+ white-space:nowrap;
1863
+ line-height:.95;
1864
+ }
1865
+
1866
+ body.jf-page-frame .sub{
1867
+ white-space:nowrap;
1868
+ }
1869
+
1870
+ body.jf-page-frame .frameHeaderActions{
1871
+ display:flex;
1872
+ align-items:center;
1873
+ justify-content:flex-end;
1874
+ gap:clamp(8px, 1.2vmin, 14px);
1875
+ }
1876
+
1877
+ body.jf-page-frame #toggleBtn,
1878
+ body.jf-page-frame .jfHiddenToggle{
1879
+ display:none !important;
1880
+ }
1881
+
1882
+ body.jf-page-frame .jfFrameMain{
1883
+ position:relative;
1884
+ min-height:0;
1885
+ height:100%;
1886
+ display:grid;
1887
+ gap:clamp(10px, 1.5vmin, 18px);
1888
+ grid-template-areas:
1889
+ "photo"
1890
+ "info"
1891
+ "metrics";
1892
+ grid-template-rows:minmax(230px, 42%) minmax(0, 1fr) auto;
1893
+ }
1894
+
1895
+ body.jf-page-frame .photoWrap{
1896
+ grid-area:photo;
1897
+ position:relative;
1898
+ min-height:0;
1899
+ overflow:hidden;
1900
+ border-radius:clamp(22px, 3vmin, 36px);
1901
+ border:1px solid rgba(255,255,255,.18);
1902
+ background:rgba(255,255,255,.06);
1903
+ }
1904
+
1905
+ body.jf-page-frame #planePhoto{
1906
+ width:100%;
1907
+ height:100%;
1908
+ object-fit:cover;
1909
+ display:none;
1910
+ }
1911
+
1912
+ body.jf-page-frame #placeholder{
1913
+ position:absolute;
1914
+ inset:0;
1915
+ display:grid;
1916
+ place-items:center;
1917
+ overflow:hidden;
1918
+ }
1919
+
1920
+ body.jf-page-frame .info{
1921
+ grid-area:info;
1922
+ min-height:0;
1923
+ overflow:hidden;
1924
+ display:flex;
1925
+ flex-direction:column;
1926
+ align-items:flex-start;
1927
+ gap:clamp(5px, .9vmin, 11px);
1928
+ }
1929
+
1930
+ body.jf-page-frame .mode{
1931
+ font-size:clamp(22px, 3.4vmin, 42px);
1932
+ font-weight:900;
1933
+ line-height:1;
1934
+ }
1935
+
1936
+ body.jf-page-frame .flightInfoPillRow{
1937
+ display:flex;
1938
+ align-items:center;
1939
+ gap:clamp(8px, 1.2vmin, 14px);
1940
+ flex-wrap:wrap;
1941
+ }
1942
+
1943
+ body.jf-page-frame .windowInfo,
1944
+ body.jf-page-frame .runwayInfo{
1945
+ display:none;
1946
+ align-items:center;
1947
+ gap:8px;
1948
+ border-radius:999px;
1949
+ padding:clamp(7px, 1vmin, 11px) clamp(12px, 1.6vmin, 20px);
1950
+ font-size:clamp(14px, 2vmin, 24px);
1951
+ font-weight:900;
1952
+ white-space:nowrap;
1953
+ }
1954
+
1955
+ body.jf-page-frame .runwayInfo.visible,
1956
+ body.jf-page-frame .windowInfo.visible{
1957
+ display:inline-flex;
1958
+ }
1959
+
1960
+ body.jf-page-frame .iataCallsign{
1961
+ font-size:clamp(42px, 7vmin, 82px);
1962
+ font-weight:950;
1963
+ letter-spacing:-.07em;
1964
+ line-height:.92;
1965
+ white-space:nowrap;
1966
+ }
1967
+
1968
+ body.jf-page-frame .operatorCallsign,
1969
+ body.jf-page-frame .routeCodes,
1970
+ body.jf-page-frame .reg{
1971
+ font-size:clamp(18px, 2.7vmin, 32px);
1972
+ font-weight:700;
1973
+ color:rgba(255,255,255,.62);
1974
+ letter-spacing:-.035em;
1975
+ }
1976
+
1977
+ body.jf-page-frame .routeCities{
1978
+ font-size:clamp(32px, 5.3vmin, 66px);
1979
+ font-weight:950;
1980
+ letter-spacing:-.07em;
1981
+ line-height:.98;
1982
+ white-space:nowrap;
1983
+ max-width:100%;
1984
+ overflow:hidden;
1985
+ text-overflow:ellipsis;
1986
+ }
1987
+
1988
+ body.jf-page-frame #aircraftCard.aircraftCard{
1989
+ margin-top:clamp(5px, .9vmin, 12px);
1990
+ display:grid;
1991
+ grid-template-columns:auto 1px auto auto auto;
1992
+ align-items:center;
1993
+ gap:clamp(8px, 1.15vmin, 15px);
1994
+ max-width:100%;
1995
+ border-radius:clamp(22px, 3vmin, 34px);
1996
+ border:1px solid rgba(255,255,255,.16);
1997
+ background:rgba(255,255,255,.075);
1998
+ padding:clamp(9px, 1.35vmin, 16px) clamp(12px, 1.8vmin, 22px);
1999
+ }
2000
+
2001
+ body.jf-page-frame #airlineMini,
2002
+ body.jf-page-frame #manufacturerLogo{
2003
+ display:inline-flex;
2004
+ align-items:center;
2005
+ gap:clamp(8px, 1.1vmin, 13px);
2006
+ min-width:0;
2007
+ }
2008
+
2009
+ body.jf-page-frame #airlineLogoImg,
2010
+ body.jf-page-frame #manufacturerLogoImg,
2011
+ body.jf-page-frame #manufacturerLogoText{
2012
+ width:clamp(28px, 4vmin, 46px);
2013
+ height:clamp(28px, 4vmin, 46px);
2014
+ border-radius:999px;
2015
+ object-fit:contain;
2016
+ flex:0 0 auto;
2017
+ }
2018
+
2019
+ body.jf-page-frame #airline,
2020
+ body.jf-page-frame #aircraftTypeText,
2021
+ body.jf-page-frame #aircraftSize{
2022
+ font-size:clamp(18px, 2.6vmin, 32px);
2023
+ font-weight:900;
2024
+ letter-spacing:-.04em;
2025
+ white-space:nowrap;
2026
+ }
2027
+
2028
+ body.jf-page-frame #aircraftSize{
2029
+ color:#ffe77a;
2030
+ }
2031
+
2032
+ body.jf-page-frame .aircraftSep{
2033
+ width:1px;
2034
+ height:clamp(28px, 4vmin, 48px);
2035
+ background:rgba(255,255,255,.16);
2036
+ }
2037
+
2038
+ body.jf-page-frame .special{
2039
+ display:none;
2040
+ }
2041
+
2042
+ body.jf-page-frame .metrics{
2043
+ grid-area:metrics;
2044
+ display:grid;
2045
+ grid-template-columns:repeat(4, minmax(0, 1fr));
2046
+ gap:clamp(8px, 1.3vmin, 16px);
2047
+ min-height:clamp(58px, 8.8vmin, 96px);
2048
+ }
2049
+
2050
+ body.jf-page-frame .metric{
2051
+ min-width:0;
2052
+ }
2053
+
2054
+ body.jf-page-frame .metricValue{
2055
+ font-size:clamp(27px, 4.8vmin, 56px);
2056
+ line-height:.9;
2057
+ white-space:nowrap;
2058
+ }
2059
+
2060
+ body.jf-page-frame .metricLabel{
2061
+ white-space:nowrap;
2062
+ }
2063
+
2064
+ /* Idle Runway Pill */
2065
+ body.jf-page-frame #idleRunwayText.idleRunwayText{
2066
+ display:none;
2067
+ position:absolute;
2068
+ left:50%;
2069
+ bottom:clamp(12px, 2.2vmin, 28px);
2070
+ transform:translateX(-50%);
2071
+ max-width:90%;
2072
+ border-radius:999px;
2073
+ padding:clamp(8px, 1.2vmin, 13px) clamp(14px, 1.8vmin, 22px);
2074
+ background:rgba(50,232,121,.15);
2075
+ border:1px solid rgba(50,232,121,.32);
2076
+ color:#dffff0;
2077
+ font-weight:850;
2078
+ white-space:nowrap;
2079
+ z-index:4;
2080
+ }
2081
+
2082
+ body.jf-page-frame #idleRunwayText.idleRunwayText.visible{
2083
+ display:inline-flex;
2084
+ }
2085
+
2086
+ /* No Flight */
2087
+ body.jf-page-frame.jf-no-flight .info .callsigns,
2088
+ body.jf-page-frame.jf-no-flight .routeBig,
2089
+ body.jf-page-frame.jf-no-flight #aircraftCard,
2090
+ body.jf-page-frame.jf-no-flight .reg,
2091
+ body.jf-page-frame.jf-no-flight .flightInfoPillRow{
2092
+ display:none !important;
2093
+ }
2094
+
2095
+ /* Preload Overlay */
2096
+ body.jf-page-frame .jfPreloadOverlay{
2097
+ position:absolute;
2098
+ inset:0;
2099
+ z-index:30;
2100
+ pointer-events:none;
2101
+ display:grid;
2102
+ gap:clamp(10px, 1.5vmin, 18px);
2103
+ grid-template-areas:
2104
+ "prePhoto"
2105
+ "preInfo"
2106
+ "preMetrics";
2107
+ grid-template-rows:minmax(230px, 42%) minmax(0, 1fr) auto;
2108
+ opacity:0;
2109
+ visibility:hidden;
2110
+ transition:opacity .18s ease, visibility .18s ease;
2111
+ }
2112
+
2113
+ body.jf-page-frame.jf-preload .jfPreloadOverlay{
2114
+ opacity:1;
2115
+ visibility:visible;
2116
+ }
2117
+
2118
+ body.jf-page-frame.jf-preload .photoWrap > *,
2119
+ body.jf-page-frame.jf-preload .info > *,
2120
+ body.jf-page-frame.jf-preload .metrics > *{
2121
+ opacity:0 !important;
2122
+ }
2123
+
2124
+ body.jf-page-frame .prePhoto{
2125
+ grid-area:prePhoto;
2126
+ border-radius:clamp(22px, 3vmin, 36px);
2127
+ border:1px solid rgba(255,255,255,.18);
2128
+ background:rgba(255,255,255,.06);
2129
+ }
2130
+
2131
+ body.jf-page-frame .preInfo{
2132
+ grid-area:preInfo;
2133
+ display:flex;
2134
+ flex-direction:column;
2135
+ align-items:flex-start;
2136
+ gap:clamp(8px, 1.05vmin, 13px);
2137
+ overflow:hidden;
2138
+ }
2139
+
2140
+ body.jf-page-frame .preMetrics{
2141
+ grid-area:preMetrics;
2142
+ display:grid;
2143
+ grid-template-columns:repeat(4, minmax(0, 1fr));
2144
+ gap:clamp(8px, 1.3vmin, 16px);
2145
+ min-height:clamp(58px, 8.8vmin, 96px);
2146
+ }
2147
+
2148
+ body.jf-page-frame .sk{
2149
+ display:block;
2150
+ border-radius:999px;
2151
+ background:linear-gradient(110deg, rgba(255,255,255,.10), rgba(255,255,255,.35), rgba(255,255,255,.10));
2152
+ background-size:240% 100%;
2153
+ animation:jfFrameSkeleton 1.12s ease-in-out infinite;
2154
+ }
2155
+
2156
+ body.jf-page-frame .skMode{width:min(360px,46%);height:clamp(26px,3.4vmin,42px)}
2157
+ body.jf-page-frame .prePillRow{display:flex;gap:clamp(8px,1.2vmin,14px)}
2158
+ body.jf-page-frame .skPillA{width:clamp(190px,28vmin,320px);height:clamp(34px,4.8vmin,52px)}
2159
+ body.jf-page-frame .skPillB{width:clamp(120px,17vmin,190px);height:clamp(34px,4.8vmin,52px)}
2160
+ body.jf-page-frame .skCall{width:min(340px,42%);height:clamp(42px,6.8vmin,82px)}
2161
+ body.jf-page-frame .skSmall{width:min(230px,28%);height:clamp(19px,2.8vmin,34px)}
2162
+ body.jf-page-frame .skRoute{width:min(720px,86%);height:clamp(34px,5.2vmin,66px)}
2163
+ body.jf-page-frame .skCodes{width:min(260px,35%);height:clamp(18px,2.8vmin,34px)}
2164
+ body.jf-page-frame .skReg{width:min(380px,48%);height:clamp(18px,2.7vmin,32px)}
2165
+
2166
+ body.jf-page-frame .preCard{
2167
+ width:min(620px,70%);
2168
+ border-radius:clamp(22px,3vmin,34px);
2169
+ border:1px solid rgba(255,255,255,.16);
2170
+ background:rgba(255,255,255,.075);
2171
+ padding:clamp(9px, 1.35vmin, 16px) clamp(12px, 1.8vmin, 22px);
2172
+ display:grid;
2173
+ gap:clamp(8px,1.15vmin,14px);
2174
+ }
2175
+
2176
+ body.jf-page-frame .preCardRow{
2177
+ display:grid;
2178
+ grid-template-columns:clamp(28px,4vmin,46px) minmax(0,1fr) auto;
2179
+ align-items:center;
2180
+ gap:clamp(8px,1.15vmin,15px);
2181
+ }
2182
+
2183
+ body.jf-page-frame .preLogo{
2184
+ width:clamp(28px,4vmin,46px);
2185
+ height:clamp(28px,4vmin,46px);
2186
+ border-radius:999px;
2187
+ background:rgba(255,255,255,.22);
2188
+ }
2189
+
2190
+ body.jf-page-frame .preDivider{
2191
+ height:1px;
2192
+ background:rgba(255,255,255,.16);
2193
+ }
2194
+
2195
+ body.jf-page-frame .skAirline{width:55%;height:clamp(16px,2.6vmin,32px)}
2196
+ body.jf-page-frame .skType{width:70%;height:clamp(16px,2.6vmin,32px)}
2197
+ body.jf-page-frame .skSize{width:clamp(90px,12vmin,150px);height:clamp(16px,2.4vmin,28px)}
2198
+
2199
+ body.jf-page-frame .preMetric{
2200
+ border-radius:clamp(19px,2.8vmin,30px);
2201
+ border:1px solid rgba(255,255,255,.18);
2202
+ background:rgba(255,255,255,.075);
2203
+ display:grid;
2204
+ place-items:center;
2205
+ align-content:center;
2206
+ }
2207
+
2208
+ body.jf-page-frame .preMetric .sk{
2209
+ width:48%;
2210
+ height:clamp(14px,2.1vmin,24px);
2211
+ }
2212
+
2213
+ @media (orientation:landscape){
2214
+ body.jf-page-frame .jfFrameMain,
2215
+ body.jf-page-frame .jfPreloadOverlay{
2216
+ grid-template-columns:minmax(0, 47%) minmax(0, 1fr);
2217
+ grid-template-rows:minmax(0, 1fr) auto;
2218
+ grid-template-areas:
2219
+ "photo info"
2220
+ "metrics metrics";
2221
+ }
2222
+
2223
+ body.jf-page-frame .jfPreloadOverlay{
2224
+ grid-template-areas:
2225
+ "prePhoto preInfo"
2226
+ "preMetrics preMetrics";
2227
+ }
2228
+
2229
+ body.jf-page-frame .info,
2230
+ body.jf-page-frame .preInfo{
2231
+ padding-top:clamp(2px,.5vmin,8px);
2232
+ }
2233
+
2234
+ body.jf-page-frame #aircraftCard.aircraftCard{
2235
+ width:max-content;
2236
+ max-width:100%;
2237
+ }
2238
+ }
2239
+
2240
+ @keyframes jfFrameSkeleton{
2241
+ 0%{background-position:120% 0;opacity:.55}
2242
+ 50%{opacity:1}
2243
+ 100%{background-position:-120% 0;opacity:.55}
2244
+ }
2245
+
2246
+
2247
+
2248
+ /* ======================================================
2249
+ FRAME PATCH: Window/Runway Pills + Special Pill
2250
+ ====================================================== */
2251
+
2252
+ body.jf-page-frame .windowInfo,
2253
+ body.jf-page-frame .runwayInfo{
2254
+ display:inline-flex;
2255
+ align-items:center;
2256
+ gap:8px;
2257
+ border-radius:999px;
2258
+ padding:clamp(7px, 1vmin, 11px) clamp(13px, 1.7vmin, 21px);
2259
+ font-weight:900;
2260
+ white-space:nowrap;
2261
+ border:1px solid rgba(255,255,255,.18);
2262
+ background:rgba(255,255,255,.08);
2263
+ color:rgba(255,255,255,.78);
2264
+ }
2265
+
2266
+ body.jf-page-frame .windowInfo{
2267
+ border-color:rgba(255,231,122,.34);
2268
+ background:rgba(255,231,122,.13);
2269
+ color:#fff0a2;
2270
+ }
2271
+
2272
+ body.jf-page-frame .runwayInfo{
2273
+ border-color:rgba(255,255,255,.18);
2274
+ background:rgba(255,255,255,.08);
2275
+ color:rgba(255,255,255,.78);
2276
+ }
2277
+
2278
+ body.jf-page-frame .special{
2279
+ display:none;
2280
+ margin-top:clamp(4px, .8vmin, 10px);
2281
+ border-radius:999px;
2282
+ padding:clamp(8px, 1.1vmin, 12px) clamp(14px, 1.8vmin, 22px);
2283
+ border:1px solid rgba(255,231,122,.36);
2284
+ background:rgba(255,231,122,.14);
2285
+ color:#fff0a2;
2286
+ font-size:clamp(15px, 2.1vmin, 25px);
2287
+ font-weight:900;
2288
+ white-space:nowrap;
2289
+ }
2290
+
2291
+ body.jf-page-frame .special:not(:empty){
2292
+ display:inline-flex;
2293
+ align-items:center;
2294
+ }
2295
+
2296
+ body.jf-page-frame .special.emergency{
2297
+ border-color:rgba(255,77,94,.42);
2298
+ background:rgba(255,77,94,.16);
2299
+ color:#ffd2d7;
2300
+ }
2301
+
2302
+
2303
+ /* ======================================================
2304
+ FRAME PATCH: Speaker rund + Metrics zentriert
2305
+ ====================================================== */
2306
+
2307
+ body.jf-page-frame #speechBtn.speechBtn{
2308
+ width:clamp(42px, 5.2vmin, 58px) !important;
2309
+ min-width:clamp(42px, 5.2vmin, 58px) !important;
2310
+ height:clamp(42px, 5.2vmin, 58px) !important;
2311
+ padding:0 !important;
2312
+ border-radius:999px !important;
2313
+ display:grid !important;
2314
+ place-items:center !important;
2315
+ line-height:1 !important;
2316
+ aspect-ratio:1 / 1 !important;
2317
+ background:rgba(255,255,255,.08) !important;
2318
+ border:1px solid rgba(255,255,255,.18) !important;
2319
+ }
2320
+
2321
+ body.jf-page-frame #speechBtn.speechBtn.on{
2322
+ background:rgba(255,255,255,.08) !important;
2323
+ border-color:rgba(255,255,255,.18) !important;
2324
+ }
2325
+
2326
+ body.jf-page-frame .metrics{
2327
+ align-items:stretch !important;
2328
+ }
2329
+
2330
+ body.jf-page-frame .metric{
2331
+ display:grid !important;
2332
+ place-items:center !important;
2333
+ align-content:center !important;
2334
+ justify-items:center !important;
2335
+ text-align:center !important;
2336
+ padding:clamp(7px, 1.1vmin, 12px) !important;
2337
+ }
2338
+
2339
+ body.jf-page-frame .metricValue{
2340
+ width:100% !important;
2341
+ text-align:center !important;
2342
+ justify-self:center !important;
2343
+ align-self:center !important;
2344
+ margin:0 auto !important;
2345
+ }
2346
+
2347
+ body.jf-page-frame .metricLabel{
2348
+ width:100% !important;
2349
+ text-align:center !important;
2350
+ justify-self:center !important;
2351
+ margin-left:0 !important;
2352
+ margin-right:0 !important;
2353
+ }
2354
+
2355
+
2356
+ /* ======================================================
2357
+ FRAME PATCH: kompakter + Speaker rund + Metrics sauber
2358
+ ====================================================== */
2359
+
2360
+ /* alles etwas kleiner, damit Special noch Platz hat */
2361
+ body.jf-page-frame .jfFrameMain{
2362
+ grid-template-rows:minmax(210px, 39%) minmax(0, 1fr) auto !important;
2363
+ gap:clamp(8px, 1.15vmin, 14px) !important;
2364
+ }
2365
+
2366
+ body.jf-page-frame .photoWrap{
2367
+ border-radius:clamp(20px, 2.6vmin, 32px) !important;
2368
+ }
2369
+
2370
+ body.jf-page-frame .info{
2371
+ gap:clamp(3px, .65vmin, 8px) !important;
2372
+ }
2373
+
2374
+ body.jf-page-frame .mode{
2375
+ font-size:clamp(20px, 3.0vmin, 36px) !important;
2376
+ }
2377
+
2378
+ body.jf-page-frame .iataCallsign{
2379
+ font-size:clamp(36px, 6.1vmin, 70px) !important;
2380
+ line-height:.9 !important;
2381
+ }
2382
+
2383
+ body.jf-page-frame .routeCities{
2384
+ font-size:clamp(28px, 4.7vmin, 56px) !important;
2385
+ line-height:.94 !important;
2386
+ }
2387
+
2388
+ body.jf-page-frame .operatorCallsign,
2389
+ body.jf-page-frame .routeCodes,
2390
+ body.jf-page-frame .reg{
2391
+ font-size:clamp(16px, 2.35vmin, 28px) !important;
2392
+ }
2393
+
2394
+ body.jf-page-frame .windowInfo,
2395
+ body.jf-page-frame .runwayInfo{
2396
+ font-size:clamp(13px, 1.75vmin, 21px) !important;
2397
+ padding:clamp(6px, .85vmin, 9px) clamp(11px, 1.45vmin, 17px) !important;
2398
+ }
2399
+
2400
+ body.jf-page-frame #aircraftCard.aircraftCard{
2401
+ width:min(560px, 70%) !important;
2402
+ padding:clamp(8px, 1.1vmin, 13px) clamp(12px, 1.5vmin, 18px) !important;
2403
+ border-radius:clamp(20px, 2.6vmin, 30px) !important;
2404
+ }
2405
+
2406
+ body.jf-page-frame #airline,
2407
+ body.jf-page-frame #aircraftTypeText,
2408
+ body.jf-page-frame #aircraftSize{
2409
+ font-size:clamp(16px, 2.25vmin, 27px) !important;
2410
+ }
2411
+
2412
+ body.jf-page-frame #airlineLogoImg,
2413
+ body.jf-page-frame #manufacturerLogoImg,
2414
+ body.jf-page-frame #manufacturerLogoText{
2415
+ width:clamp(25px, 3.5vmin, 40px) !important;
2416
+ height:clamp(25px, 3.5vmin, 40px) !important;
2417
+ }
2418
+
2419
+ body.jf-page-frame .special{
2420
+ font-size:clamp(14px, 1.9vmin, 23px) !important;
2421
+ padding:clamp(6px, .85vmin, 10px) clamp(12px, 1.5vmin, 18px) !important;
2422
+ }
2423
+
2424
+ /* Speaker komplett unabhängig vom Toggle-Button */
2425
+ body.jf-page-frame #speechBtn,
2426
+ body.jf-page-frame #speechBtn.toggleBtn,
2427
+ body.jf-page-frame #speechBtn.speechBtn,
2428
+ body.jf-page-frame #speechBtn.toggleBtn.on,
2429
+ body.jf-page-frame #speechBtn.speechBtn.on{
2430
+ width:clamp(40px, 4.7vmin, 52px) !important;
2431
+ min-width:clamp(40px, 4.7vmin, 52px) !important;
2432
+ height:clamp(40px, 4.7vmin, 52px) !important;
2433
+ min-height:clamp(40px, 4.7vmin, 52px) !important;
2434
+ padding:0 !important;
2435
+ border-radius:999px !important;
2436
+ aspect-ratio:1 / 1 !important;
2437
+ display:grid !important;
2438
+ place-items:center !important;
2439
+ background:rgba(255,255,255,.08) !important;
2440
+ border:1px solid rgba(255,255,255,.18) !important;
2441
+ box-shadow:none !important;
2442
+ color:#fff !important;
2443
+ font-size:clamp(18px, 2.35vmin, 26px) !important;
2444
+ line-height:1 !important;
2445
+ }
2446
+
2447
+ /* Metrics kleiner und Inhalt wirklich mittig */
2448
+ body.jf-page-frame .metrics{
2449
+ min-height:clamp(54px, 7.8vmin, 84px) !important;
2450
+ gap:clamp(7px, 1.05vmin, 13px) !important;
2451
+ }
2452
+
2453
+ body.jf-page-frame .metric{
2454
+ min-height:clamp(54px, 7.8vmin, 84px) !important;
2455
+ padding:clamp(5px, .8vmin, 9px) !important;
2456
+ display:flex !important;
2457
+ flex-direction:column !important;
2458
+ align-items:center !important;
2459
+ justify-content:center !important;
2460
+ text-align:center !important;
2461
+ }
2462
+
2463
+ body.jf-page-frame .metricValue{
2464
+ font-size:clamp(24px, 4.1vmin, 46px) !important;
2465
+ line-height:.88 !important;
2466
+ width:100% !important;
2467
+ text-align:center !important;
2468
+ margin:0 !important;
2469
+ letter-spacing:-.06em !important;
2470
+ }
2471
+
2472
+ body.jf-page-frame .metricLabel{
2473
+ font-size:clamp(8px, 1.05vmin, 12px) !important;
2474
+ line-height:1 !important;
2475
+ letter-spacing:.22em !important;
2476
+ width:100% !important;
2477
+ text-align:center !important;
2478
+ margin-top:clamp(3px, .45vmin, 5px) !important;
2479
+ padding-left:.22em !important;
2480
+ }
2481
+
2482
+ /* Portrait noch etwas Luft unten */
2483
+ @media (orientation:portrait){
2484
+ body.jf-page-frame #wall.jf-shell{
2485
+ padding-bottom:clamp(14px, 2vmin, 24px) !important;
2486
+ }
2487
+
2488
+ body.jf-page-frame .jfFrameMain{
2489
+ grid-template-rows:minmax(200px, 38%) minmax(0, 1fr) auto !important;
2490
+ }
2491
+ }
2492
+
2493
+
2494
+ /* ======================================================
2495
+ FRAME PATCH: Speaker wie Live-Höhe + Preload synchron
2496
+ ====================================================== */
2497
+
2498
+ /* Speaker exakt gleiche Höhe wie Live-Pill, aber rund */
2499
+ body.jf-page-frame #speechBtn,
2500
+ body.jf-page-frame #speechBtn.toggleBtn,
2501
+ body.jf-page-frame #speechBtn.speechBtn,
2502
+ body.jf-page-frame #speechBtn.toggleBtn.on,
2503
+ body.jf-page-frame #speechBtn.speechBtn.on{
2504
+ width:clamp(38px, 4.2vmin, 48px) !important;
2505
+ min-width:clamp(38px, 4.2vmin, 48px) !important;
2506
+ height:clamp(38px, 4.2vmin, 48px) !important;
2507
+ min-height:clamp(38px, 4.2vmin, 48px) !important;
2508
+ padding:0 !important;
2509
+ border-radius:999px !important;
2510
+ aspect-ratio:1 / 1 !important;
2511
+ display:grid !important;
2512
+ place-items:center !important;
2513
+ font-size:clamp(17px, 2.05vmin, 23px) !important;
2514
+ line-height:1 !important;
2515
+ }
2516
+
2517
+ /* Preload bekommt exakt die gleiche neue Kompakt-Aufteilung wie echtes Layout */
2518
+ body.jf-page-frame .jfPreloadOverlay{
2519
+ grid-template-rows:minmax(200px, 38%) minmax(0, 1fr) auto !important;
2520
+ gap:clamp(8px, 1.15vmin, 14px) !important;
2521
+ }
2522
+
2523
+ body.jf-page-frame .prePhoto{
2524
+ border-radius:clamp(20px, 2.6vmin, 32px) !important;
2525
+ }
2526
+
2527
+ body.jf-page-frame .preInfo{
2528
+ gap:clamp(3px, .65vmin, 8px) !important;
2529
+ }
2530
+
2531
+ body.jf-page-frame .skMode{
2532
+ height:clamp(20px, 3.0vmin, 36px) !important;
2533
+ width:min(330px, 46%) !important;
2534
+ }
2535
+
2536
+ body.jf-page-frame .skPillA,
2537
+ body.jf-page-frame .skPillB{
2538
+ height:clamp(30px, 4.0vmin, 44px) !important;
2539
+ }
2540
+
2541
+ body.jf-page-frame .skPillA{ width:clamp(180px, 25vmin, 290px) !important; }
2542
+ body.jf-page-frame .skPillB{ width:clamp(110px, 15vmin, 170px) !important; }
2543
+
2544
+ body.jf-page-frame .skCall{
2545
+ height:clamp(36px, 6.1vmin, 70px) !important;
2546
+ width:min(310px, 42%) !important;
2547
+ }
2548
+
2549
+ body.jf-page-frame .skRoute{
2550
+ height:clamp(28px, 4.7vmin, 56px) !important;
2551
+ width:min(640px, 86%) !important;
2552
+ }
2553
+
2554
+ body.jf-page-frame .skSmall,
2555
+ body.jf-page-frame .skCodes,
2556
+ body.jf-page-frame .skReg{
2557
+ height:clamp(16px, 2.35vmin, 28px) !important;
2558
+ }
2559
+
2560
+ body.jf-page-frame .preCard{
2561
+ width:min(560px, 70%) !important;
2562
+ padding:clamp(8px, 1.1vmin, 13px) clamp(12px, 1.5vmin, 18px) !important;
2563
+ border-radius:clamp(20px, 2.6vmin, 30px) !important;
2564
+ }
2565
+
2566
+ body.jf-page-frame .preLogo{
2567
+ width:clamp(25px, 3.5vmin, 40px) !important;
2568
+ height:clamp(25px, 3.5vmin, 40px) !important;
2569
+ }
2570
+
2571
+ body.jf-page-frame .skAirline,
2572
+ body.jf-page-frame .skType{
2573
+ height:clamp(16px, 2.25vmin, 27px) !important;
2574
+ }
2575
+
2576
+ body.jf-page-frame .skSize{
2577
+ height:clamp(16px, 2.25vmin, 27px) !important;
2578
+ width:clamp(80px, 11vmin, 130px) !important;
2579
+ }
2580
+
2581
+ body.jf-page-frame .preMetrics{
2582
+ min-height:clamp(54px, 7.8vmin, 84px) !important;
2583
+ gap:clamp(7px, 1.05vmin, 13px) !important;
2584
+ }
2585
+
2586
+ body.jf-page-frame .preMetric{
2587
+ min-height:clamp(54px, 7.8vmin, 84px) !important;
2588
+ }
2589
+
2590
+ body.jf-page-frame .preMetric .sk{
2591
+ height:clamp(12px, 1.8vmin, 20px) !important;
2592
+ width:45% !important;
2593
+ }
2594
+
2595
+ @media (orientation:portrait){
2596
+ body.jf-page-frame .jfPreloadOverlay{
2597
+ grid-template-rows:minmax(200px, 38%) minmax(0, 1fr) auto !important;
2598
+ }
2599
+ }
2600
+
2601
+
2602
+
2603
+ /* ======================================================
2604
+ FRAME PATCH: Warte-auf-Flug sauber V2
2605
+ ====================================================== */
2606
+
2607
+ body.jf-page-frame .frameIdleRunwaySlot{
2608
+ grid-area:info;
2609
+ display:none;
2610
+ align-items:center;
2611
+ justify-content:center;
2612
+ width:100%;
2613
+ margin:0 0 clamp(6px, .9vmin, 10px) 0;
2614
+ z-index:4;
2615
+ }
2616
+
2617
+ body.jf-page-frame.jf-no-flight .frameIdleRunwaySlot{
2618
+ display:flex !important;
2619
+ }
2620
+
2621
+ body.jf-page-frame #idleRunwayText.idleRunwayText{
2622
+ position:relative !important;
2623
+ left:auto !important;
2624
+ right:auto !important;
2625
+ top:auto !important;
2626
+ bottom:auto !important;
2627
+ transform:none !important;
2628
+ display:none;
2629
+ max-width:92%;
2630
+ border-radius:999px;
2631
+ padding:clamp(8px, 1.1vmin, 13px) clamp(16px, 1.9vmin, 24px);
2632
+ background:rgba(50,232,121,.16);
2633
+ border:1px solid rgba(50,232,121,.36);
2634
+ color:#dffff0;
2635
+ font-weight:900;
2636
+ white-space:nowrap;
2637
+ text-align:center;
2638
+ }
2639
+
2640
+ body.jf-page-frame.jf-no-flight #idleRunwayText.idleRunwayText.visible{
2641
+ display:inline-flex !important;
2642
+ align-items:center;
2643
+ justify-content:center;
2644
+ }
2645
+
2646
+ /* Wartezustand: keine leeren Fake-Daten */
2647
+ body.jf-page-frame.jf-no-flight .info{
2648
+ align-items:center !important;
2649
+ text-align:center !important;
2650
+ justify-content:flex-start !important;
2651
+ }
2652
+
2653
+ body.jf-page-frame.jf-no-flight .info > :not(#mode){
2654
+ display:none !important;
2655
+ }
2656
+
2657
+ body.jf-page-frame.jf-no-flight .metrics{
2658
+ display:none !important;
2659
+ }
2660
+
2661
+ body.jf-page-frame.jf-no-flight #mode{
2662
+ margin-top:clamp(6px, 1vmin, 12px) !important;
2663
+ font-size:clamp(24px, 3.5vmin, 42px) !important;
2664
+ }
2665
+
2666
+ /* Wartezustand: Foto bleibt Radar/Animation */
2667
+ body.jf-page-frame.jf-no-flight #planePhoto{
2668
+ display:none !important;
2669
+ opacity:0 !important;
2670
+ visibility:hidden !important;
2671
+ }
2672
+
2673
+ body.jf-page-frame.jf-no-flight #placeholder{
2674
+ display:grid !important;
2675
+ opacity:1 !important;
2676
+ visibility:visible !important;
2677
+ background:
2678
+ radial-gradient(circle at 50% 45%, rgba(255,255,255,.08), transparent 34%),
2679
+ linear-gradient(135deg, rgba(255,255,255,.07), rgba(255,255,255,.025)) !important;
2680
+ }
2681
+
2682
+ body.jf-page-frame.jf-no-flight .radarCircle{
2683
+ position:absolute;
2684
+ width:min(48vmin, 360px);
2685
+ aspect-ratio:1;
2686
+ border-radius:999px;
2687
+ border:1px solid rgba(255,255,255,.15);
2688
+ box-shadow:
2689
+ 0 0 0 11vmin rgba(255,255,255,.018),
2690
+ 0 0 0 22vmin rgba(255,255,255,.012);
2691
+ }
2692
+
2693
+ body.jf-page-frame.jf-no-flight .radarSweep{
2694
+ position:absolute;
2695
+ width:min(48vmin, 360px);
2696
+ aspect-ratio:1;
2697
+ border-radius:999px;
2698
+ background:conic-gradient(from 0deg, rgba(50,232,121,.30), transparent 18%, transparent);
2699
+ animation:jfRadarSpin2 2.8s linear infinite;
2700
+ opacity:.42;
2701
+ }
2702
+
2703
+ body.jf-page-frame.jf-no-flight .idlePlane{
2704
+ position:relative;
2705
+ z-index:3;
2706
+ font-size:clamp(42px, 7vmin, 78px);
2707
+ filter:drop-shadow(0 10px 24px rgba(0,0,0,.35));
2708
+ }
2709
+
2710
+ body.jf-page-frame .idleFlyers{
2711
+ display:none;
2712
+ }
2713
+
2714
+ body.jf-page-frame.jf-no-flight .idleFlyers{
2715
+ display:block;
2716
+ position:absolute;
2717
+ inset:0;
2718
+ pointer-events:none;
2719
+ overflow:hidden;
2720
+ z-index:2;
2721
+ }
2722
+
2723
+ body.jf-page-frame.jf-no-flight .idleFlyers span{
2724
+ position:absolute;
2725
+ left:-14%;
2726
+ font-size:clamp(20px, 3.2vmin, 34px);
2727
+ opacity:0;
2728
+ filter:drop-shadow(0 8px 18px rgba(0,0,0,.35));
2729
+ animation:jfIdleFly2 5.8s ease-in-out infinite;
2730
+ }
2731
+
2732
+ body.jf-page-frame.jf-no-flight .idleFlyers span:nth-child(1){ top:30%; animation-delay:.2s; }
2733
+ body.jf-page-frame.jf-no-flight .idleFlyers span:nth-child(2){ top:58%; animation-delay:1.8s; }
2734
+ body.jf-page-frame.jf-no-flight .idleFlyers span:nth-child(3){ top:44%; animation-delay:3.4s; }
2735
+
2736
+ body.jf-page-frame.jf-no-flight .idleText{
2737
+ position:absolute;
2738
+ left:50%;
2739
+ bottom:clamp(16px, 2.5vmin, 32px);
2740
+ transform:translateX(-50%);
2741
+ font-weight:850;
2742
+ font-size:clamp(18px, 2.5vmin, 28px);
2743
+ color:rgba(255,255,255,.72);
2744
+ white-space:nowrap;
2745
+ z-index:3;
2746
+ }
2747
+
2748
+ @keyframes jfRadarSpin2{
2749
+ to{ transform:rotate(360deg); }
2750
+ }
2751
+
2752
+ @keyframes jfIdleFly2{
2753
+ 0%{ transform:translateX(0) translateY(20px) rotate(8deg); opacity:0; }
2754
+ 12%{ opacity:.85; }
2755
+ 82%{ opacity:.85; }
2756
+ 100%{ transform:translateX(115vw) translateY(-38px) rotate(8deg); opacity:0; }
2757
+ }
2758
+
2759
+ /* ======================================================
2760
+ FRAME PATCH: sauberer Übergang Warteanimation -> Flug
2761
+ ====================================================== */
2762
+
2763
+ /* Sobald echter Flug erkannt:
2764
+ Radar sofort weg
2765
+ aber Skeleton darf bleiben */
2766
+ body.jf-page-frame.jf-preload:not(.jf-no-flight) #placeholder{
2767
+ opacity:0 !important;
2768
+ visibility:hidden !important;
2769
+ pointer-events:none !important;
2770
+ transition:
2771
+ opacity .22s ease,
2772
+ visibility .22s ease !important;
2773
+ }
2774
+
2775
+ /* Flugfoto schon weich einblenden während Skeleton noch sichtbar */
2776
+ body.jf-page-frame.jf-preload:not(.jf-no-flight) #planePhoto{
2777
+ display:block !important;
2778
+ opacity:.22 !important;
2779
+ filter:blur(3px) saturate(.9);
2780
+ transform:scale(1.01);
2781
+ transition:
2782
+ opacity .28s ease,
2783
+ filter .35s ease,
2784
+ transform .35s ease !important;
2785
+ }
2786
+
2787
+ /* Nach preload echtes Bild vollständig */
2788
+ body.jf-page-frame.jf-loaded #planePhoto{
2789
+ opacity:1 !important;
2790
+ filter:none !important;
2791
+ transform:none !important;
2792
+ }
2793
+
2794
+ /* Skeleton etwas transparenter sobald echte Flugdaten da sind */
2795
+ body.jf-page-frame.jf-preload:not(.jf-no-flight) .jfPreloadOverlay{
2796
+ background:
2797
+ linear-gradient(
2798
+ 180deg,
2799
+ rgba(5,6,10,.10),
2800
+ rgba(5,6,10,.18)
2801
+ ) !important;
2802
+
2803
+ backdrop-filter:blur(2px);
2804
+ }
2805
+
2806
+ /* Skeleton nicht mehr komplett dominant */
2807
+ body.jf-page-frame.jf-preload:not(.jf-no-flight) .sk{
2808
+ opacity:.72 !important;
2809
+ }
2810
+
2811
+ /* Warteanimation NUR wenn wirklich jf-no-flight */
2812
+ body.jf-page-frame:not(.jf-no-flight) .idlePlane,
2813
+ body.jf-page-frame:not(.jf-no-flight) .idleFlyers,
2814
+ body.jf-page-frame:not(.jf-no-flight) .radarCircle,
2815
+ body.jf-page-frame:not(.jf-no-flight) .radarSweep,
2816
+ body.jf-page-frame:not(.jf-no-flight) .idleText{
2817
+ display:none !important;
2818
+ }
2819
+
2820
+
2821
+ /* ======================================================
2822
+ FRAME PATCH: Querformat getrennt iPad / iPhone
2823
+ ====================================================== */
2824
+
2825
+ /* ------------------------------------------------------
2826
+ iPad / Tablet Querformat
2827
+ Ziel: Layout behalten, aber Metrics unten flacher
2828
+ ------------------------------------------------------ */
2829
+ @media (orientation:landscape) and (min-width: 900px) and (min-height: 600px){
2830
+
2831
+ body.jf-page-frame #wall.jf-shell{
2832
+ gap:clamp(8px, 1.1vmin, 14px) !important;
2833
+ }
2834
+
2835
+ body.jf-page-frame .jfFrameMain,
2836
+ body.jf-page-frame .jfPreloadOverlay{
2837
+ grid-template-columns:minmax(0, 47%) minmax(0, 1fr) !important;
2838
+ grid-template-rows:minmax(0, 1fr) clamp(54px, 8vh, 74px) !important;
2839
+ gap:clamp(8px, 1.1vmin, 14px) !important;
2840
+ }
2841
+
2842
+ body.jf-page-frame .metrics,
2843
+ body.jf-page-frame .preMetrics{
2844
+ min-height:clamp(54px, 8vh, 74px) !important;
2845
+ height:clamp(54px, 8vh, 74px) !important;
2846
+ gap:clamp(8px, 1.1vmin, 14px) !important;
2847
+ }
2848
+
2849
+ body.jf-page-frame .metric,
2850
+ body.jf-page-frame .preMetric{
2851
+ min-height:clamp(54px, 8vh, 74px) !important;
2852
+ height:clamp(54px, 8vh, 74px) !important;
2853
+ border-radius:clamp(16px, 2.1vmin, 24px) !important;
2854
+ padding:clamp(4px, .7vmin, 8px) !important;
2855
+ }
2856
+
2857
+ body.jf-page-frame .metricValue{
2858
+ font-size:clamp(24px, 4.2vmin, 42px) !important;
2859
+ line-height:.86 !important;
2860
+ }
2861
+
2862
+ body.jf-page-frame .metricLabel{
2863
+ font-size:clamp(7px, .95vmin, 11px) !important;
2864
+ letter-spacing:.20em !important;
2865
+ margin-top:clamp(2px, .35vmin, 4px) !important;
2866
+ }
2867
+
2868
+ body.jf-page-frame .preMetric .sk{
2869
+ height:clamp(10px, 1.4vmin, 16px) !important;
2870
+ }
2871
+ }
2872
+
2873
+
2874
+ /* ------------------------------------------------------
2875
+ iPhone Querformat / sehr niedrige Höhe
2876
+ Ziel: rechte Info-Spalte deutlich kompakter
2877
+ ------------------------------------------------------ */
2878
+ @media (orientation:landscape) and (max-height: 520px){
2879
+
2880
+ body.jf-page-frame #app{
2881
+ padding:calc(env(safe-area-inset-top) + 6px)
2882
+ calc(env(safe-area-inset-right) + 8px)
2883
+ calc(env(safe-area-inset-bottom) + 6px)
2884
+ calc(env(safe-area-inset-left) + 8px) !important;
2885
+ }
2886
+
2887
+ body.jf-page-frame #wall.jf-shell{
2888
+ padding:clamp(8px, 1.6vmin, 14px) !important;
2889
+ gap:clamp(6px, 1vmin, 10px) !important;
2890
+ border-radius:clamp(22px, 3.2vmin, 32px) !important;
2891
+ }
2892
+
2893
+ body.jf-page-frame .header{
2894
+ gap:clamp(7px, 1.1vmin, 12px) !important;
2895
+ }
2896
+
2897
+ body.jf-page-frame .title{
2898
+ font-size:clamp(23px, 5.1vmin, 36px) !important;
2899
+ line-height:.88 !important;
2900
+ }
2901
+
2902
+ body.jf-page-frame .sub{
2903
+ font-size:clamp(12px, 2.5vmin, 18px) !important;
2904
+ line-height:1 !important;
2905
+ }
2906
+
2907
+ body.jf-page-frame .backBtn,
2908
+ body.jf-page-frame #speechBtn,
2909
+ body.jf-page-frame #speechBtn.toggleBtn,
2910
+ body.jf-page-frame #speechBtn.speechBtn{
2911
+ width:clamp(32px, 6.2vmin, 42px) !important;
2912
+ min-width:clamp(32px, 6.2vmin, 42px) !important;
2913
+ height:clamp(32px, 6.2vmin, 42px) !important;
2914
+ min-height:clamp(32px, 6.2vmin, 42px) !important;
2915
+ font-size:clamp(15px, 3vmin, 21px) !important;
2916
+ }
2917
+
2918
+ body.jf-page-frame .livePill{
2919
+ height:clamp(32px, 6.2vmin, 42px) !important;
2920
+ padding:0 clamp(10px, 2vmin, 16px) !important;
2921
+ font-size:clamp(14px, 2.8vmin, 20px) !important;
2922
+ }
2923
+
2924
+ body.jf-page-frame .jfFrameMain,
2925
+ body.jf-page-frame .jfPreloadOverlay{
2926
+ grid-template-columns:minmax(0, 48%) minmax(0, 1fr) !important;
2927
+ grid-template-rows:minmax(0, 1fr) clamp(44px, 12vh, 58px) !important;
2928
+ gap:clamp(6px, 1vmin, 10px) !important;
2929
+ }
2930
+
2931
+ body.jf-page-frame .photoWrap,
2932
+ body.jf-page-frame .prePhoto{
2933
+ border-radius:clamp(16px, 3vmin, 24px) !important;
2934
+ }
2935
+
2936
+ body.jf-page-frame .info,
2937
+ body.jf-page-frame .preInfo{
2938
+ gap:clamp(2px, .65vmin, 5px) !important;
2939
+ padding-top:0 !important;
2940
+ }
2941
+
2942
+ body.jf-page-frame .mode{
2943
+ font-size:clamp(17px, 3.3vmin, 24px) !important;
2944
+ line-height:.95 !important;
2945
+ }
2946
+
2947
+ body.jf-page-frame .windowInfo,
2948
+ body.jf-page-frame .runwayInfo{
2949
+ font-size:clamp(10px, 2.15vmin, 15px) !important;
2950
+ padding:clamp(4px, .8vmin, 6px) clamp(8px, 1.5vmin, 12px) !important;
2951
+ }
2952
+
2953
+ body.jf-page-frame .iataCallsign{
2954
+ font-size:clamp(28px, 6.2vmin, 44px) !important;
2955
+ line-height:.82 !important;
2956
+ }
2957
+
2958
+ body.jf-page-frame .operatorCallsign,
2959
+ body.jf-page-frame .routeCodes,
2960
+ body.jf-page-frame .reg{
2961
+ font-size:clamp(12px, 2.45vmin, 17px) !important;
2962
+ line-height:1 !important;
2963
+ }
2964
+
2965
+ body.jf-page-frame .routeCities{
2966
+ font-size:clamp(22px, 5.1vmin, 36px) !important;
2967
+ line-height:.86 !important;
2968
+ }
2969
+
2970
+ body.jf-page-frame #aircraftCard.aircraftCard{
2971
+ width:min(440px, 92%) !important;
2972
+ padding:clamp(5px, 1vmin, 8px) clamp(8px, 1.5vmin, 12px) !important;
2973
+ border-radius:clamp(15px, 2.8vmin, 22px) !important;
2974
+ margin-top:clamp(2px, .45vmin, 4px) !important;
2975
+ }
2976
+
2977
+ body.jf-page-frame #aircraftCard .aircraftSep{
2978
+ margin:clamp(4px, .75vmin, 6px) 0 !important;
2979
+ }
2980
+
2981
+ body.jf-page-frame #airlineLogoImg,
2982
+ body.jf-page-frame #manufacturerLogoImg,
2983
+ body.jf-page-frame #manufacturerLogoText{
2984
+ width:clamp(20px, 4.2vmin, 28px) !important;
2985
+ height:clamp(20px, 4.2vmin, 28px) !important;
2986
+ }
2987
+
2988
+ body.jf-page-frame #airline,
2989
+ body.jf-page-frame #aircraftTypeText,
2990
+ body.jf-page-frame #aircraftSize{
2991
+ font-size:clamp(13px, 2.7vmin, 19px) !important;
2992
+ line-height:1 !important;
2993
+ }
2994
+
2995
+ body.jf-page-frame #aircraftCard #aircraftTypeText{
2996
+ margin-left:calc(clamp(20px, 4.2vmin, 28px) + 8px) !important;
2997
+ }
2998
+
2999
+ body.jf-page-frame .special{
3000
+ font-size:clamp(11px, 2.25vmin, 16px) !important;
3001
+ padding:clamp(4px, .8vmin, 6px) clamp(8px, 1.5vmin, 12px) !important;
3002
+ }
3003
+
3004
+ body.jf-page-frame .metrics,
3005
+ body.jf-page-frame .preMetrics{
3006
+ min-height:clamp(44px, 12vh, 58px) !important;
3007
+ height:clamp(44px, 12vh, 58px) !important;
3008
+ gap:clamp(6px, 1vmin, 10px) !important;
3009
+ }
3010
+
3011
+ body.jf-page-frame .metric,
3012
+ body.jf-page-frame .preMetric{
3013
+ min-height:clamp(44px, 12vh, 58px) !important;
3014
+ height:clamp(44px, 12vh, 58px) !important;
3015
+ border-radius:clamp(14px, 2.6vmin, 20px) !important;
3016
+ padding:3px !important;
3017
+ }
3018
+
3019
+ body.jf-page-frame .metricValue{
3020
+ font-size:clamp(19px, 4.7vmin, 32px) !important;
3021
+ line-height:.82 !important;
3022
+ }
3023
+
3024
+ body.jf-page-frame .metricLabel{
3025
+ font-size:clamp(6px, 1.35vmin, 9px) !important;
3026
+ letter-spacing:.18em !important;
3027
+ margin-top:2px !important;
3028
+ }
3029
+ }
3030
+
3031
+
3032
+ /* ======================================================
3033
+ FRAME PATCH: Warteanzeige erst nach Preload
3034
+ ====================================================== */
3035
+
3036
+ /* zweites "Warte auf Flug" unter dem Bild entfernen */
3037
+ body.jf-page-frame.jf-no-flight .info,
3038
+ body.jf-page-frame.jf-no-flight #mode{
3039
+ display:none !important;
3040
+ }
3041
+
3042
+ /* grüne Runway-Pille ebenfalls erst nach Preload zeigen */
3043
+ body.jf-page-frame.jf-preload .frameIdleRunwaySlot,
3044
+ body.jf-page-frame.jf-preload #idleRunwayText{
3045
+ display:none !important;
3046
+ }
3047
+
3048
+ /* während Preload KEINE Radar-/Warteanimation anzeigen */
3049
+ body.jf-page-frame.jf-preload.jf-no-flight #placeholder,
3050
+ body.jf-page-frame.jf-preload.jf-no-flight .radarCircle,
3051
+ body.jf-page-frame.jf-preload.jf-no-flight .radarSweep,
3052
+ body.jf-page-frame.jf-preload.jf-no-flight .idlePlane,
3053
+ body.jf-page-frame.jf-preload.jf-no-flight .idleFlyers,
3054
+ body.jf-page-frame.jf-preload.jf-no-flight .idleText{
3055
+ opacity:0 !important;
3056
+ visibility:hidden !important;
3057
+ }
3058
+
3059
+ /* nach Preload darf die Warteanimation sichtbar sein */
3060
+ body.jf-page-frame.jf-loaded.jf-no-flight #placeholder{
3061
+ opacity:1 !important;
3062
+ visibility:visible !important;
3063
+ }
3064
+
3065
+
3066
+ /* ======================================================
3067
+ FRAME PATCH: Querformat luftiger + Speaker kleiner
3068
+ ====================================================== */
3069
+
3070
+ /* Speaker wirklich passend zur Live-Pill */
3071
+ body.jf-page-frame #speechBtn,
3072
+ body.jf-page-frame #speechBtn.toggleBtn,
3073
+ body.jf-page-frame #speechBtn.speechBtn{
3074
+ width:clamp(34px, 4.0vmin, 44px) !important;
3075
+ min-width:clamp(34px, 4.0vmin, 44px) !important;
3076
+ height:clamp(34px, 4.0vmin, 44px) !important;
3077
+ min-height:clamp(34px, 4.0vmin, 44px) !important;
3078
+ padding:0 !important;
3079
+ border-radius:999px !important;
3080
+ font-size:clamp(15px, 1.9vmin, 21px) !important;
3081
+ display:grid !important;
3082
+ place-items:center !important;
3083
+ }
3084
+
3085
+ /* Querformat allgemein luftiger */
3086
+ @media (orientation:landscape){
3087
+
3088
+ body.jf-page-frame .jfFrameMain,
3089
+ body.jf-page-frame .jfPreloadOverlay{
3090
+ grid-template-columns:minmax(0, 46%) minmax(0, 1fr) !important;
3091
+ gap:clamp(14px, 2.2vmin, 26px) !important;
3092
+ }
3093
+
3094
+ body.jf-page-frame .info,
3095
+ body.jf-page-frame .preInfo{
3096
+ padding-left:clamp(4px, .8vmin, 12px) !important;
3097
+ gap:clamp(4px, .8vmin, 9px) !important;
3098
+ }
3099
+
3100
+ body.jf-page-frame .photoWrap,
3101
+ body.jf-page-frame .prePhoto{
3102
+ align-self:start !important;
3103
+ }
3104
+
3105
+ body.jf-page-frame #aircraftCard.aircraftCard{
3106
+ width:min(620px, 92%) !important;
3107
+ }
3108
+
3109
+ body.jf-page-frame .metrics,
3110
+ body.jf-page-frame .preMetrics{
3111
+ height:clamp(48px, 10vh, 68px) !important;
3112
+ min-height:clamp(48px, 10vh, 68px) !important;
3113
+ }
3114
+
3115
+ body.jf-page-frame .metric,
3116
+ body.jf-page-frame .preMetric{
3117
+ height:clamp(48px, 10vh, 68px) !important;
3118
+ min-height:clamp(48px, 10vh, 68px) !important;
3119
+ }
3120
+
3121
+ body.jf-page-frame .metricValue{
3122
+ font-size:clamp(22px, 4.1vmin, 38px) !important;
3123
+ }
3124
+
3125
+ body.jf-page-frame .metricLabel{
3126
+ font-size:clamp(7px, 1.05vmin, 10px) !important;
3127
+ }
3128
+ }
3129
+
3130
+ /* iPhone quer: nicht mehr so brutal zusammenpressen */
3131
+ @media (orientation:landscape) and (max-height: 520px){
3132
+
3133
+ body.jf-page-frame .jfFrameMain,
3134
+ body.jf-page-frame .jfPreloadOverlay{
3135
+ grid-template-columns:minmax(0, 47%) minmax(0, 1fr) !important;
3136
+ gap:clamp(10px, 1.8vmin, 18px) !important;
3137
+ }
3138
+
3139
+ body.jf-page-frame .mode{
3140
+ font-size:clamp(18px, 3.7vmin, 26px) !important;
3141
+ }
3142
+
3143
+ body.jf-page-frame .iataCallsign{
3144
+ font-size:clamp(30px, 6.6vmin, 46px) !important;
3145
+ }
3146
+
3147
+ body.jf-page-frame .routeCities{
3148
+ font-size:clamp(23px, 5.3vmin, 38px) !important;
3149
+ }
3150
+
3151
+ body.jf-page-frame #aircraftCard.aircraftCard{
3152
+ width:min(520px, 94%) !important;
3153
+ }
3154
+ }
3155
+
3156
+
3157
+ /* ======================================================
3158
+ FRAME PATCH: Querformat Höhe / Speaker final
3159
+ ====================================================== */
3160
+
3161
+ /* Speaker nochmal kleiner + optisch exakt Live-Pill */
3162
+ body.jf-page-frame #speechBtn,
3163
+ body.jf-page-frame #speechBtn.toggleBtn,
3164
+ body.jf-page-frame #speechBtn.speechBtn{
3165
+ width:clamp(30px, 3.5vmin, 40px) !important;
3166
+ min-width:clamp(30px, 3.5vmin, 40px) !important;
3167
+ height:clamp(30px, 3.5vmin, 40px) !important;
3168
+ min-height:clamp(30px, 3.5vmin, 40px) !important;
3169
+ font-size:clamp(13px, 1.55vmin, 18px) !important;
3170
+ padding:0 !important;
3171
+ border-radius:999px !important;
3172
+ display:grid !important;
3173
+ place-items:center !important;
3174
+ }
3175
+
3176
+ /* ------------------------------------------------------
3177
+ Querformat allgemein
3178
+ ------------------------------------------------------ */
3179
+ @media (orientation:landscape){
3180
+
3181
+ /* Bild wieder höher */
3182
+ body.jf-page-frame .jfFrameMain,
3183
+ body.jf-page-frame .jfPreloadOverlay{
3184
+ grid-template-rows:minmax(0, 1fr) clamp(54px, 9vh, 72px) !important;
3185
+ }
3186
+
3187
+ body.jf-page-frame .photoWrap,
3188
+ body.jf-page-frame .prePhoto{
3189
+ min-height:clamp(260px, 56vh, 560px) !important;
3190
+ max-height:none !important;
3191
+ }
3192
+
3193
+ /* Textspalte etwas entspannter */
3194
+ body.jf-page-frame .info,
3195
+ body.jf-page-frame .preInfo{
3196
+ padding-top:clamp(4px, .8vmin, 10px) !important;
3197
+ }
3198
+
3199
+ /* Route-Zeile NICHT mehr abschneiden */
3200
+ body.jf-page-frame .routeCities{
3201
+ line-height:1.02 !important;
3202
+ padding-bottom:.08em !important;
3203
+ overflow:visible !important;
3204
+ }
3205
+
3206
+ /* Callsign ebenfalls etwas luftiger */
3207
+ body.jf-page-frame .iataCallsign{
3208
+ line-height:.92 !important;
3209
+ padding-bottom:.03em !important;
3210
+ }
3211
+
3212
+ /* Aircraft Card minimal tiefer */
3213
+ body.jf-page-frame #aircraftCard.aircraftCard{
3214
+ margin-top:clamp(4px, .7vmin, 8px) !important;
3215
+ }
3216
+
3217
+ /* Metrics weiterhin kompakt */
3218
+ body.jf-page-frame .metrics,
3219
+ body.jf-page-frame .preMetrics{
3220
+ height:clamp(50px, 9vh, 68px) !important;
3221
+ min-height:clamp(50px, 9vh, 68px) !important;
3222
+ }
3223
+ }
3224
+
3225
+ /* ------------------------------------------------------
3226
+ iPhone Querformat
3227
+ ------------------------------------------------------ */
3228
+ @media (orientation:landscape) and (max-height: 520px){
3229
+
3230
+ /* Bild nochmal sichtbar höher */
3231
+ body.jf-page-frame .photoWrap,
3232
+ body.jf-page-frame .prePhoto{
3233
+ min-height:clamp(210px, 60vh, 360px) !important;
3234
+ }
3235
+
3236
+ /* Bangkok/Frankfurt etc sauber */
3237
+ body.jf-page-frame .routeCities{
3238
+ line-height:1.04 !important;
3239
+ padding-bottom:.10em !important;
3240
+ font-size:clamp(24px, 5.5vmin, 40px) !important;
3241
+ }
3242
+
3243
+ /* etwas mehr Luft unter Callsign */
3244
+ body.jf-page-frame .iataCallsign{
3245
+ line-height:.94 !important;
3246
+ margin-bottom:2px !important;
3247
+ }
3248
+
3249
+ /* Info insgesamt weniger gequetscht */
3250
+ body.jf-page-frame .info,
3251
+ body.jf-page-frame .preInfo{
3252
+ gap:clamp(5px, .9vmin, 10px) !important;
3253
+ }
3254
+
3255
+ /* Metrics unten etwas niedriger */
3256
+ body.jf-page-frame .metric,
3257
+ body.jf-page-frame .preMetric{
3258
+ height:clamp(46px, 10vh, 60px) !important;
3259
+ min-height:clamp(46px, 10vh, 60px) !important;
3260
+ }
3261
+ }
3262
+
3263
+
3264
+ /* ======================================================
3265
+ FRAME PATCH: Landscape Bild/Route/Speaker/Card
3266
+ ====================================================== */
3267
+
3268
+ /* Speaker exakt Live-Pill-Höhe */
3269
+ body.jf-page-frame #speechBtn,
3270
+ body.jf-page-frame #speechBtn.toggleBtn,
3271
+ body.jf-page-frame #speechBtn.speechBtn{
3272
+ height:var(--jf-live-pill-h, 44px) !important;
3273
+ min-height:var(--jf-live-pill-h, 44px) !important;
3274
+ width:var(--jf-live-pill-h, 44px) !important;
3275
+ min-width:var(--jf-live-pill-h, 44px) !important;
3276
+ padding:0 !important;
3277
+ border-radius:999px !important;
3278
+ aspect-ratio:1 / 1 !important;
3279
+ display:grid !important;
3280
+ place-items:center !important;
3281
+ font-size:calc(var(--jf-live-pill-h, 44px) * .43) !important;
3282
+ line-height:1 !important;
3283
+ }
3284
+
3285
+ body.jf-page-frame .livePill{
3286
+ --jf-live-pill-h: clamp(34px, 4.0vmin, 44px);
3287
+ height:var(--jf-live-pill-h) !important;
3288
+ }
3289
+
3290
+ /* Querformat */
3291
+ @media (orientation:landscape){
3292
+
3293
+ /* Bildbereich stärker strecken */
3294
+ body.jf-page-frame .jfFrameMain,
3295
+ body.jf-page-frame .jfPreloadOverlay{
3296
+ grid-template-columns:minmax(0, 48%) minmax(0, 1fr) !important;
3297
+ grid-template-rows:minmax(0, 1fr) clamp(48px, 8.5vh, 64px) !important;
3298
+ }
3299
+
3300
+ body.jf-page-frame .photoWrap,
3301
+ body.jf-page-frame .prePhoto{
3302
+ height:100% !important;
3303
+ min-height:clamp(280px, 62vh, 620px) !important;
3304
+ }
3305
+
3306
+ body.jf-page-frame #planePhoto{
3307
+ width:100% !important;
3308
+ height:100% !important;
3309
+ object-fit:cover !important;
3310
+ }
3311
+
3312
+ /* Route-Zeile sauber, kein abgeschnittenes g mehr */
3313
+ body.jf-page-frame .routeCities{
3314
+ line-height:1.16 !important;
3315
+ padding-bottom:.14em !important;
3316
+ margin-bottom:-.04em !important;
3317
+ overflow:visible !important;
3318
+ }
3319
+
3320
+ body.jf-page-frame .routeCodes{
3321
+ margin-top:-.10em !important;
3322
+ }
3323
+
3324
+ /* Aircraft-Card kompakter und weniger breit */
3325
+ body.jf-page-frame #aircraftCard.aircraftCard{
3326
+ width:max-content !important;
3327
+ min-width:min(360px, 76%) !important;
3328
+ max-width:min(520px, 82%) !important;
3329
+ padding-left:clamp(10px, 1.35vmin, 16px) !important;
3330
+ padding-right:clamp(10px, 1.35vmin, 16px) !important;
3331
+ }
3332
+
3333
+ body.jf-page-frame #aircraftCard #airline,
3334
+ body.jf-page-frame #aircraftCard #aircraftTypeText{
3335
+ max-width:clamp(180px, 24vw, 320px) !important;
3336
+ overflow:hidden !important;
3337
+ text-overflow:ellipsis !important;
3338
+ }
3339
+
3340
+ body.jf-page-frame #aircraftCard #aircraftSize{
3341
+ margin-left:clamp(12px, 1.8vmin, 22px) !important;
3342
+ }
3343
+ }
3344
+
3345
+ /* iPhone Querformat extra */
3346
+ @media (orientation:landscape) and (max-height:520px){
3347
+
3348
+ body.jf-page-frame .photoWrap,
3349
+ body.jf-page-frame .prePhoto{
3350
+ min-height:clamp(220px, 64vh, 380px) !important;
3351
+ }
3352
+
3353
+ body.jf-page-frame .routeCities{
3354
+ line-height:1.18 !important;
3355
+ padding-bottom:.16em !important;
3356
+ }
3357
+
3358
+ body.jf-page-frame #aircraftCard.aircraftCard{
3359
+ min-width:min(330px, 74%) !important;
3360
+ max-width:min(470px, 84%) !important;
3361
+ }
3362
+ }
3363
+
3364
+
3365
+ /* ======================================================
3366
+ FRAME PATCH: Speaker kleiner + Radar-Flieger dynamischer
3367
+ ====================================================== */
3368
+
3369
+ /* Speaker bewusst kleiner als Live-Pille */
3370
+ body.jf-page-frame #speechBtn,
3371
+ body.jf-page-frame #speechBtn.toggleBtn,
3372
+ body.jf-page-frame #speechBtn.speechBtn{
3373
+ width:clamp(30px, 3.4vmin, 38px) !important;
3374
+ min-width:clamp(30px, 3.4vmin, 38px) !important;
3375
+ height:clamp(30px, 3.4vmin, 38px) !important;
3376
+ min-height:clamp(30px, 3.4vmin, 38px) !important;
3377
+ font-size:clamp(13px, 1.55vmin, 17px) !important;
3378
+ padding:0 !important;
3379
+ border-radius:999px !important;
3380
+ display:grid !important;
3381
+ place-items:center !important;
3382
+ }
3383
+
3384
+ /* Live-Pille bleibt größer */
3385
+ body.jf-page-frame .livePill{
3386
+ min-height:clamp(34px, 4vmin, 44px) !important;
3387
+ }
3388
+
3389
+ /* mittleres Radar-Flugzeug lebendiger */
3390
+ body.jf-page-frame.jf-loaded.jf-no-flight .idlePlane{
3391
+ animation:jfIdlePlaneFloat 3.2s ease-in-out infinite !important;
3392
+ transform-origin:50% 55%;
3393
+ }
3394
+
3395
+ @keyframes jfIdlePlaneFloat{
3396
+ 0%{
3397
+ transform:translateY(0) rotate(-7deg) scale(1);
3398
+ }
3399
+ 35%{
3400
+ transform:translateY(-7px) rotate(-2deg) scale(1.04);
3401
+ }
3402
+ 70%{
3403
+ transform:translateY(4px) rotate(-10deg) scale(.99);
3404
+ }
3405
+ 100%{
3406
+ transform:translateY(0) rotate(-7deg) scale(1);
3407
+ }
3408
+ }
3409
+
3410
+ /* Radar-Sweep etwas lebendiger */
3411
+ body.jf-page-frame.jf-loaded.jf-no-flight .radarSweep{
3412
+ animation:jfRadarSpin2 2.35s linear infinite !important;
3413
+ opacity:.48 !important;
3414
+ }
3415
+
3416
+
3417
+ /* ======================================================
3418
+ FRAME PATCH: Portrait unten sicher + Special kürzen
3419
+ ====================================================== */
3420
+
3421
+ /* Special-Pille nie aus dem Frame laufen lassen */
3422
+ body.jf-page-frame .special{
3423
+ max-width:100% !important;
3424
+ overflow:hidden !important;
3425
+ text-overflow:ellipsis !important;
3426
+ white-space:nowrap !important;
3427
+ box-sizing:border-box !important;
3428
+ }
3429
+
3430
+ /* Portrait: alles minimal kompakter, damit Metrics unten nicht abgeschnitten werden */
3431
+ @media (orientation:portrait){
3432
+
3433
+ body.jf-page-frame #wall.jf-shell{
3434
+ padding-bottom:clamp(18px, 2.8vmin, 30px) !important;
3435
+ }
3436
+
3437
+ body.jf-page-frame .jfFrameMain,
3438
+ body.jf-page-frame .jfPreloadOverlay{
3439
+ grid-template-rows:minmax(190px, 34%) minmax(0, 1fr) clamp(54px, 7.6vh, 76px) !important;
3440
+ gap:clamp(6px, .9vmin, 10px) !important;
3441
+ }
3442
+
3443
+ body.jf-page-frame .photoWrap,
3444
+ body.jf-page-frame .prePhoto{
3445
+ max-height:clamp(250px, 34vh, 360px) !important;
3446
+ }
3447
+
3448
+ body.jf-page-frame .info,
3449
+ body.jf-page-frame .preInfo{
3450
+ gap:clamp(2px, .45vmin, 6px) !important;
3451
+ }
3452
+
3453
+ body.jf-page-frame .mode{
3454
+ font-size:clamp(20px, 2.8vmin, 34px) !important;
3455
+ }
3456
+
3457
+ body.jf-page-frame .iataCallsign{
3458
+ font-size:clamp(34px, 5.5vmin, 64px) !important;
3459
+ line-height:.88 !important;
3460
+ }
3461
+
3462
+ body.jf-page-frame .routeCities{
3463
+ font-size:clamp(27px, 4.4vmin, 52px) !important;
3464
+ line-height:1.02 !important;
3465
+ padding-bottom:.08em !important;
3466
+ }
3467
+
3468
+ body.jf-page-frame .operatorCallsign,
3469
+ body.jf-page-frame .routeCodes,
3470
+ body.jf-page-frame .reg{
3471
+ font-size:clamp(15px, 2.15vmin, 25px) !important;
3472
+ }
3473
+
3474
+ body.jf-page-frame #aircraftCard.aircraftCard{
3475
+ width:min(540px, 70%) !important;
3476
+ padding:clamp(7px, .95vmin, 11px) clamp(11px, 1.3vmin, 16px) !important;
3477
+ }
3478
+
3479
+ body.jf-page-frame #airline,
3480
+ body.jf-page-frame #aircraftTypeText,
3481
+ body.jf-page-frame #aircraftSize{
3482
+ font-size:clamp(15px, 2.05vmin, 25px) !important;
3483
+ }
3484
+
3485
+ body.jf-page-frame .special{
3486
+ max-width:min(680px, 92%) !important;
3487
+ font-size:clamp(13px, 1.75vmin, 21px) !important;
3488
+ padding:clamp(6px, .8vmin, 9px) clamp(12px, 1.4vmin, 18px) !important;
3489
+ margin-top:clamp(3px, .45vmin, 6px) !important;
3490
+ }
3491
+
3492
+ body.jf-page-frame .metrics,
3493
+ body.jf-page-frame .preMetrics{
3494
+ height:clamp(54px, 7.6vh, 76px) !important;
3495
+ min-height:clamp(54px, 7.6vh, 76px) !important;
3496
+ }
3497
+
3498
+ body.jf-page-frame .metric,
3499
+ body.jf-page-frame .preMetric{
3500
+ height:clamp(54px, 7.6vh, 76px) !important;
3501
+ min-height:clamp(54px, 7.6vh, 76px) !important;
3502
+ }
3503
+
3504
+ body.jf-page-frame .metricValue{
3505
+ font-size:clamp(23px, 3.7vmin, 42px) !important;
3506
+ }
3507
+
3508
+ body.jf-page-frame .metricLabel{
3509
+ font-size:clamp(7px, .95vmin, 11px) !important;
3510
+ }
3511
+ }
3512
+
3513
+
3514
+ /* ======================================================
3515
+ FRAME PATCH: Landscape Grid + Preload Sync
3516
+ ====================================================== */
3517
+
3518
+ @media (orientation:landscape){
3519
+
3520
+ body.jf-page-frame .jfFrameMain,
3521
+ body.jf-page-frame .jfPreloadOverlay{
3522
+ grid-template-rows:minmax(0, 1fr) clamp(54px, 9vh, 72px) !important;
3523
+ align-items:stretch !important;
3524
+ }
3525
+
3526
+ body.jf-page-frame .photoWrap,
3527
+ body.jf-page-frame .prePhoto{
3528
+ height:100% !important;
3529
+ min-height:0 !important;
3530
+ max-height:100% !important;
3531
+ align-self:stretch !important;
3532
+ overflow:hidden !important;
3533
+ }
3534
+
3535
+ body.jf-page-frame #planePhoto{
3536
+ width:100% !important;
3537
+ height:100% !important;
3538
+ object-fit:cover !important;
3539
+ display:block !important;
3540
+ }
3541
+
3542
+ body.jf-page-frame .metrics,
3543
+ body.jf-page-frame .preMetrics{
3544
+ height:clamp(54px, 9vh, 72px) !important;
3545
+ min-height:clamp(54px, 9vh, 72px) !important;
3546
+ align-self:end !important;
3547
+ z-index:5 !important;
3548
+ }
3549
+
3550
+ body.jf-page-frame .metric,
3551
+ body.jf-page-frame .preMetric{
3552
+ height:100% !important;
3553
+ min-height:0 !important;
3554
+ }
3555
+
3556
+ /* Preload-Info exakt an die echten kompakteren Textzeilen angleichen */
3557
+ body.jf-page-frame .preInfo{
3558
+ gap:clamp(4px, .8vmin, 9px) !important;
3559
+ padding-left:clamp(4px, .8vmin, 12px) !important;
3560
+ padding-top:clamp(4px, .8vmin, 10px) !important;
3561
+ overflow:hidden !important;
3562
+ }
3563
+
3564
+ body.jf-page-frame .skMode{
3565
+ height:clamp(18px, 3.2vmin, 30px) !important;
3566
+ width:min(330px, 46%) !important;
3567
+ }
3568
+
3569
+ body.jf-page-frame .prePillRow{
3570
+ gap:clamp(8px, 1.2vmin, 14px) !important;
3571
+ }
3572
+
3573
+ body.jf-page-frame .skPillA,
3574
+ body.jf-page-frame .skPillB{
3575
+ height:clamp(27px, 4.2vmin, 38px) !important;
3576
+ }
3577
+
3578
+ body.jf-page-frame .skPillA{
3579
+ width:clamp(180px, 23vw, 300px) !important;
3580
+ }
3581
+
3582
+ body.jf-page-frame .skPillB{
3583
+ width:clamp(110px, 12vw, 170px) !important;
3584
+ }
3585
+
3586
+ body.jf-page-frame .skCall{
3587
+ height:clamp(32px, 5.8vmin, 50px) !important;
3588
+ width:min(300px, 40%) !important;
3589
+ }
3590
+
3591
+ body.jf-page-frame .skSmall,
3592
+ body.jf-page-frame .skCodes,
3593
+ body.jf-page-frame .skReg{
3594
+ height:clamp(14px, 2.2vmin, 22px) !important;
3595
+ }
3596
+
3597
+ body.jf-page-frame .skRoute{
3598
+ height:clamp(28px, 5vmin, 44px) !important;
3599
+ width:min(620px, 82%) !important;
3600
+ }
3601
+
3602
+ body.jf-page-frame .preCard{
3603
+ width:max-content !important;
3604
+ min-width:min(360px, 76%) !important;
3605
+ max-width:min(520px, 82%) !important;
3606
+ padding:clamp(7px, 1vmin, 11px) clamp(10px, 1.35vmin, 16px) !important;
3607
+ border-radius:clamp(16px, 2.3vmin, 24px) !important;
3608
+ gap:clamp(5px, .8vmin, 9px) !important;
3609
+ }
3610
+
3611
+ body.jf-page-frame .preCardRow{
3612
+ grid-template-columns:clamp(22px, 3.6vmin, 34px) minmax(0, 1fr) auto !important;
3613
+ gap:clamp(8px, 1.1vmin, 12px) !important;
3614
+ }
3615
+
3616
+ body.jf-page-frame .preLogo{
3617
+ width:clamp(22px, 3.6vmin, 34px) !important;
3618
+ height:clamp(22px, 3.6vmin, 34px) !important;
3619
+ }
3620
+
3621
+ body.jf-page-frame .skAirline,
3622
+ body.jf-page-frame .skType{
3623
+ height:clamp(14px, 2.3vmin, 22px) !important;
3624
+ }
3625
+
3626
+ body.jf-page-frame .skAirline{
3627
+ width:clamp(150px, 22vw, 280px) !important;
3628
+ }
3629
+
3630
+ body.jf-page-frame .skType{
3631
+ width:clamp(140px, 20vw, 260px) !important;
3632
+ }
3633
+
3634
+ body.jf-page-frame .skSize{
3635
+ width:clamp(80px, 10vw, 130px) !important;
3636
+ height:clamp(14px, 2.3vmin, 22px) !important;
3637
+ }
3638
+
3639
+ body.jf-page-frame .preMetric .sk{
3640
+ width:45% !important;
3641
+ height:clamp(10px, 1.8vmin, 18px) !important;
3642
+ }
3643
+ }
3644
+
3645
+ @media (orientation:landscape) and (max-height:520px){
3646
+
3647
+ body.jf-page-frame .jfFrameMain,
3648
+ body.jf-page-frame .jfPreloadOverlay{
3649
+ grid-template-rows:minmax(0, 1fr) clamp(46px, 10vh, 60px) !important;
3650
+ }
3651
+
3652
+ body.jf-page-frame .metrics,
3653
+ body.jf-page-frame .preMetrics{
3654
+ height:clamp(46px, 10vh, 60px) !important;
3655
+ min-height:clamp(46px, 10vh, 60px) !important;
3656
+ }
3657
+
3658
+ body.jf-page-frame .preInfo{
3659
+ gap:clamp(3px, .65vmin, 7px) !important;
3660
+ }
3661
+
3662
+ body.jf-page-frame .skMode{
3663
+ height:clamp(16px, 3.1vmin, 24px) !important;
3664
+ }
3665
+
3666
+ body.jf-page-frame .skPillA,
3667
+ body.jf-page-frame .skPillB{
3668
+ height:clamp(23px, 4.4vmin, 32px) !important;
3669
+ }
3670
+
3671
+ body.jf-page-frame .skCall{
3672
+ height:clamp(28px, 5.5vmin, 42px) !important;
3673
+ }
3674
+
3675
+ body.jf-page-frame .skRoute{
3676
+ height:clamp(24px, 4.8vmin, 36px) !important;
3677
+ }
3678
+
3679
+ body.jf-page-frame .preCard{
3680
+ min-width:min(330px, 74%) !important;
3681
+ max-width:min(470px, 84%) !important;
3682
+ padding:clamp(5px, .9vmin, 8px) clamp(8px, 1.3vmin, 12px) !important;
3683
+ }
3684
+ }
3685
+
3686
+
3687
+
3688
+ /* ======================================================
3689
+ FRAME MINI FIX: Logo Badges final
3690
+ ====================================================== */
3691
+
3692
+ body.jf-page-frame #airlineLogoImg,
3693
+ body.jf-page-frame #manufacturerLogoImg{
3694
+ width:30px !important;
3695
+ height:30px !important;
3696
+ min-width:30px !important;
3697
+ min-height:30px !important;
3698
+ border-radius:999px !important;
3699
+ background:#fff !important;
3700
+ padding:0 !important;
3701
+ object-fit:contain !important;
3702
+ box-sizing:border-box !important;
3703
+ box-shadow:
3704
+ inset 0 0 0 1px rgba(0,0,0,.10),
3705
+ 0 2px 8px rgba(0,0,0,.16) !important;
3706
+ }
3707
+
3708
+ /* Fallback-Kreis standardmäßig AUS, sonst entsteht der dritte Kreis */
3709
+ body.jf-page-frame #manufacturerLogoText{
3710
+ display:none !important;
3711
+ }
3712
+
3713
+ body.jf-page-frame #manufacturerLogoText.isFallback{
3714
+ width:30px !important;
3715
+ height:30px !important;
3716
+ min-width:30px !important;
3717
+ min-height:30px !important;
3718
+ border-radius:999px !important;
3719
+ background:#fff !important;
3720
+ padding:0 !important;
3721
+ box-sizing:border-box !important;
3722
+ box-shadow:
3723
+ inset 0 0 0 1px rgba(0,0,0,.10),
3724
+ 0 2px 8px rgba(0,0,0,.16) !important;
3725
+ color:#132238 !important;
3726
+ font-weight:900 !important;
3727
+ font-size:13px !important;
3728
+ line-height:1 !important;
3729
+ display:grid !important;
3730
+ place-items:center !important;
3731
+ }
3732
+
3733
+
3734
+ /* ======================================================
3735
+ FRAME: Flight Switch Animation V2
3736
+ Mehrere kleine Flugzeuge mit Kurvenbahnen
3737
+ ====================================================== */
3738
+
3739
+ body.jf-page-frame .jfFlightSwitch{
3740
+ position:absolute;
3741
+ inset:0;
3742
+ z-index:29;
3743
+ pointer-events:none;
3744
+ display:grid;
3745
+ place-items:center;
3746
+ opacity:0;
3747
+ visibility:hidden;
3748
+ border-radius:inherit;
3749
+ overflow:hidden;
3750
+ background:
3751
+ radial-gradient(circle at 50% 44%, rgba(50,232,121,.16), transparent 34%),
3752
+ linear-gradient(135deg, rgba(255,255,255,.07), rgba(5,6,10,.20));
3753
+ backdrop-filter:blur(9px) saturate(135%);
3754
+ }
3755
+
3756
+ body.jf-page-frame.jf-flight-switch .jfFlightSwitch{
3757
+ visibility:visible;
3758
+ animation:jfSwitchV2Fade 1.75s ease forwards;
3759
+ }
3760
+
3761
+ body.jf-page-frame .jfSwitchRadar{
3762
+ position:absolute;
3763
+ width:min(48vmin, 380px);
3764
+ aspect-ratio:1;
3765
+ border-radius:999px;
3766
+ border:1px solid rgba(255,255,255,.18);
3767
+ box-shadow:
3768
+ 0 0 0 11vmin rgba(255,255,255,.018),
3769
+ 0 0 0 22vmin rgba(255,255,255,.012);
3770
+ opacity:.82;
3771
+ }
3772
+
3773
+ body.jf-page-frame .jfSwitchRadar::before,
3774
+ body.jf-page-frame .jfSwitchRadar::after{
3775
+ content:"";
3776
+ position:absolute;
3777
+ inset:0;
3778
+ border-radius:999px;
3779
+ }
3780
+
3781
+ body.jf-page-frame .jfSwitchRadar::before{
3782
+ border:1px solid rgba(255,255,255,.10);
3783
+ transform:scale(.58);
3784
+ }
3785
+
3786
+ body.jf-page-frame .jfSwitchRadar::after{
3787
+ background:conic-gradient(from 0deg, rgba(50,232,121,.36), transparent 18%, transparent);
3788
+ animation:jfSwitchV2Radar 1.15s linear infinite;
3789
+ }
3790
+
3791
+ body.jf-page-frame .jfSwitchPlane{
3792
+ position:absolute;
3793
+ left:-14%;
3794
+ top:50%;
3795
+ opacity:0;
3796
+ filter:drop-shadow(0 10px 22px rgba(0,0,0,.42));
3797
+ will-change:transform, opacity;
3798
+ }
3799
+
3800
+ body.jf-page-frame .jfSwitchPlaneA{
3801
+ font-size:clamp(28px, 5.2vmin, 56px);
3802
+ }
3803
+
3804
+ body.jf-page-frame .jfSwitchPlaneB{
3805
+ font-size:clamp(22px, 4.1vmin, 44px);
3806
+ }
3807
+
3808
+ body.jf-page-frame .jfSwitchPlaneC{
3809
+ font-size:clamp(20px, 3.7vmin, 40px);
3810
+ }
3811
+
3812
+ body.jf-page-frame .jfSwitchPlaneD{
3813
+ font-size:clamp(18px, 3.3vmin, 36px);
3814
+ }
3815
+
3816
+ body.jf-page-frame.jf-flight-switch .jfSwitchPlaneA{
3817
+ animation:jfSwitchV2FlyA 1.45s cubic-bezier(.22,.8,.22,1) forwards;
3818
+ }
3819
+
3820
+ body.jf-page-frame.jf-flight-switch .jfSwitchPlaneB{
3821
+ animation:jfSwitchV2FlyB 1.55s cubic-bezier(.22,.8,.22,1) .08s forwards;
3822
+ }
3823
+
3824
+ body.jf-page-frame.jf-flight-switch .jfSwitchPlaneC{
3825
+ animation:jfSwitchV2FlyC 1.62s cubic-bezier(.22,.8,.22,1) .16s forwards;
3826
+ }
3827
+
3828
+ body.jf-page-frame.jf-flight-switch .jfSwitchPlaneD{
3829
+ animation:jfSwitchV2FlyD 1.35s cubic-bezier(.22,.8,.22,1) .28s forwards;
3830
+ }
3831
+
3832
+ body.jf-page-frame .jfSwitchText{
3833
+ position:absolute;
3834
+ left:50%;
3835
+ bottom:clamp(42px, 7.5vmin, 86px);
3836
+ transform:translateX(-50%);
3837
+ text-align:center;
3838
+ opacity:0;
3839
+ }
3840
+
3841
+ body.jf-page-frame.jf-flight-switch .jfSwitchText{
3842
+ animation:jfSwitchV2Text 1.55s ease .08s forwards;
3843
+ }
3844
+
3845
+ body.jf-page-frame .jfSwitchLabel{
3846
+ font-size:clamp(15px, 2.2vmin, 26px);
3847
+ font-weight:900;
3848
+ color:rgba(255,255,255,.68);
3849
+ letter-spacing:-.03em;
3850
+ }
3851
+
3852
+ body.jf-page-frame .jfSwitchRoute{
3853
+ margin-top:3px;
3854
+ max-width:86vw;
3855
+ overflow:hidden;
3856
+ text-overflow:ellipsis;
3857
+ white-space:nowrap;
3858
+ font-size:clamp(24px, 4.1vmin, 50px);
3859
+ font-weight:950;
3860
+ color:#fff;
3861
+ letter-spacing:-.06em;
3862
+ text-shadow:0 12px 28px rgba(0,0,0,.45);
3863
+ }
3864
+
3865
+ @keyframes jfSwitchV2Fade{
3866
+ 0%{ opacity:0; }
3867
+ 14%{ opacity:1; }
3868
+ 82%{ opacity:1; }
3869
+ 100%{ opacity:0; }
3870
+ }
3871
+
3872
+ @keyframes jfSwitchV2Radar{
3873
+ to{ transform:rotate(360deg); }
3874
+ }
3875
+
3876
+ @keyframes jfSwitchV2Text{
3877
+ 0%{
3878
+ opacity:0;
3879
+ transform:translateX(-50%) translateY(18px) scale(.96);
3880
+ }
3881
+ 22%{
3882
+ opacity:1;
3883
+ transform:translateX(-50%) translateY(0) scale(1);
3884
+ }
3885
+ 78%{
3886
+ opacity:1;
3887
+ transform:translateX(-50%) translateY(0) scale(1);
3888
+ }
3889
+ 100%{
3890
+ opacity:0;
3891
+ transform:translateX(-50%) translateY(-10px) scale(.98);
3892
+ }
3893
+ }
3894
+
3895
+ @keyframes jfSwitchV2FlyA{
3896
+ 0%{
3897
+ transform:translate(0, 34px) rotate(13deg) scale(.72);
3898
+ opacity:0;
3899
+ }
3900
+ 12%{ opacity:.95; }
3901
+ 48%{
3902
+ transform:translate(48vw, -38px) rotate(-8deg) scale(1.02);
3903
+ opacity:1;
3904
+ }
3905
+ 100%{
3906
+ transform:translate(126vw, -4px) rotate(10deg) scale(.88);
3907
+ opacity:0;
3908
+ }
3909
+ }
3910
+
3911
+ @keyframes jfSwitchV2FlyB{
3912
+ 0%{
3913
+ transform:translate(0, -44px) rotate(-12deg) scale(.62);
3914
+ opacity:0;
3915
+ }
3916
+ 14%{ opacity:.78; }
3917
+ 52%{
3918
+ transform:translate(42vw, 26px) rotate(9deg) scale(.9);
3919
+ opacity:.9;
3920
+ }
3921
+ 100%{
3922
+ transform:translate(118vw, -34px) rotate(-7deg) scale(.72);
3923
+ opacity:0;
3924
+ }
3925
+ }
3926
+
3927
+ @keyframes jfSwitchV2FlyC{
3928
+ 0%{
3929
+ transform:translate(0, 5px) rotate(4deg) scale(.50);
3930
+ opacity:0;
3931
+ }
3932
+ 20%{ opacity:.65; }
3933
+ 55%{
3934
+ transform:translate(54vw, 58px) rotate(15deg) scale(.72);
3935
+ opacity:.78;
3936
+ }
3937
+ 100%{
3938
+ transform:translate(124vw, 34px) rotate(2deg) scale(.58);
3939
+ opacity:0;
3940
+ }
3941
+ }
3942
+
3943
+ @keyframes jfSwitchV2FlyD{
3944
+ 0%{
3945
+ transform:translate(0, -12px) rotate(18deg) scale(.42);
3946
+ opacity:0;
3947
+ }
3948
+ 22%{ opacity:.55; }
3949
+ 62%{
3950
+ transform:translate(38vw, -70px) rotate(-18deg) scale(.62);
3951
+ opacity:.7;
3952
+ }
3953
+ 100%{
3954
+ transform:translate(105vw, -44px) rotate(8deg) scale(.48);
3955
+ opacity:0;
3956
+ }
3957
+ }
3958
+
3959
+
3960
+ /* ======================================================
3961
+ FRAME MINI FIX: Switch-Reihenfolge + Portrait Luft + Header Buttons
3962
+ ====================================================== */
3963
+
3964
+ /* Header: Speaker exakt gleiche Höhe wie Live-Pille */
3965
+ body.jf-page-frame .frameHeaderActions{
3966
+ --jfHeaderPillH: clamp(38px, 4.8vmin, 50px);
3967
+ align-items:center !important;
3968
+ }
3969
+
3970
+ body.jf-page-frame .frameHeaderActions .livePill{
3971
+ height:var(--jfHeaderPillH) !important;
3972
+ min-height:var(--jfHeaderPillH) !important;
3973
+ }
3974
+
3975
+ body.jf-page-frame #speechBtn,
3976
+ body.jf-page-frame #speechBtn.toggleBtn,
3977
+ body.jf-page-frame #speechBtn.speechBtn,
3978
+ body.jf-page-frame #speechBtn.toggleBtn.on,
3979
+ body.jf-page-frame #speechBtn.speechBtn.on{
3980
+ width:var(--jfHeaderPillH) !important;
3981
+ min-width:var(--jfHeaderPillH) !important;
3982
+ height:var(--jfHeaderPillH) !important;
3983
+ min-height:var(--jfHeaderPillH) !important;
3984
+ padding:0 !important;
3985
+ border-radius:999px !important;
3986
+ display:grid !important;
3987
+ place-items:center !important;
3988
+ font-size:calc(var(--jfHeaderPillH) * .42) !important;
3989
+ line-height:1 !important;
3990
+ }
3991
+
3992
+ /* Hochkant: etwas luftiger, Preload synchron */
3993
+ @media (orientation:portrait){
3994
+ body.jf-page-frame .jfFrameMain,
3995
+ body.jf-page-frame .jfPreloadOverlay{
3996
+ grid-template-rows:minmax(185px, 31.5%) minmax(0, 1fr) clamp(54px, 7.3vh, 74px) !important;
3997
+ gap:clamp(11px, 1.45vmin, 17px) !important;
3998
+ }
3999
+
4000
+ body.jf-page-frame .info,
4001
+ body.jf-page-frame .preInfo{
4002
+ gap:clamp(7px, 1.05vmin, 13px) !important;
4003
+ }
4004
+
4005
+ body.jf-page-frame .flightInfoPillRow,
4006
+ body.jf-page-frame .prePillRow{
4007
+ margin-top:clamp(1px, .35vmin, 4px) !important;
4008
+ margin-bottom:clamp(1px, .35vmin, 4px) !important;
4009
+ }
4010
+
4011
+ body.jf-page-frame .routeCities{
4012
+ line-height:1.18 !important;
4013
+ padding-bottom:.14em !important;
4014
+ }
4015
+
4016
+ body.jf-page-frame .routeCodes{
4017
+ margin-top:-.05em !important;
4018
+ }
4019
+
4020
+ body.jf-page-frame #aircraftCard.aircraftCard,
4021
+ body.jf-page-frame .preCard{
4022
+ margin-top:clamp(8px, 1.1vmin, 14px) !important;
4023
+ }
4024
+
4025
+ body.jf-page-frame .reg{
4026
+ margin-top:clamp(2px, .45vmin, 6px) !important;
4027
+ }
4028
+
4029
+ body.jf-page-frame .special{
4030
+ margin-top:clamp(5px, .7vmin, 9px) !important;
4031
+ }
4032
+
4033
+ body.jf-page-frame .metrics,
4034
+ body.jf-page-frame .preMetrics{
4035
+ height:clamp(54px, 7.3vh, 74px) !important;
4036
+ min-height:clamp(54px, 7.3vh, 74px) !important;
4037
+ }
4038
+ }
4039
+
4040
+ /* Flight-Switch etwas deutlicher, damit er vor Flug 2 wahrgenommen wird */
4041
+ body.jf-page-frame.jf-flight-switch .jfFlightSwitch{
4042
+ z-index:80 !important;
4043
+ }
4044
+
4045
+ /* ======================================================
4046
+ FRAME MINI FIX: Flight-Switch Overlay umfasst Metrics
4047
+ ====================================================== */
4048
+
4049
+ /* Overlay deutlich größer als sichtbarer Frame, damit keine harte Kante entsteht */
4050
+ body.jf-page-frame .jfFlightSwitch{
4051
+ inset:-36px !important;
4052
+ border-radius:calc(clamp(26px, 4vmin, 44px) + 36px) !important;
4053
+ background:
4054
+ radial-gradient(circle at 50% 48%, rgba(50,232,121,.18), transparent 40%),
4055
+ linear-gradient(180deg, rgba(8,10,18,.22), rgba(8,10,18,.64)) !important;
4056
+ backdrop-filter:blur(12px) saturate(135%) !important;
4057
+ -webkit-backdrop-filter:blur(12px) saturate(135%) !important;
4058
+
4059
+ mask-image:radial-gradient(
4060
+ ellipse at center,
4061
+ #000 72%,
4062
+ rgba(0,0,0,.88) 84%,
4063
+ rgba(0,0,0,.35) 94%,
4064
+ transparent 100%
4065
+ );
4066
+ -webkit-mask-image:radial-gradient(
4067
+ ellipse at center,
4068
+ #000 72%,
4069
+ rgba(0,0,0,.88) 84%,
4070
+ rgba(0,0,0,.35) 94%,
4071
+ transparent 100%
4072
+ );
4073
+ }
4074
+
4075
+ /* Metrics NICHT ausblenden, sondern bewusst mit in den Glas-Effekt nehmen */
4076
+ body.jf-page-frame.jf-flight-switch .metrics{
4077
+ opacity:.42 !important;
4078
+ filter:blur(3px) saturate(.85) !important;
4079
+ transition:opacity .28s ease, filter .28s ease !important;
4080
+ }
4081
+
4082
+ /* Foto + Text ebenfalls weich darunter sichtbar */
4083
+ body.jf-page-frame.jf-flight-switch .photoWrap,
4084
+ body.jf-page-frame.jf-flight-switch .info{
4085
+ opacity:.36 !important;
4086
+ filter:blur(4px) saturate(.82) !important;
4087
+ transition:opacity .28s ease, filter .28s ease !important;
4088
+ }
4089
+
4090
+ /* weicher Fade statt harter Kasten */
4091
+ body.jf-page-frame.jf-flight-switch .jfFlightSwitch{
4092
+ animation:jfSwitchSoftFade2 1.75s ease forwards !important;
4093
+ }
4094
+
4095
+ @keyframes jfSwitchSoftFade2{
4096
+ 0%{ opacity:0; }
4097
+ 18%{ opacity:1; }
4098
+ 76%{ opacity:1; }
4099
+ 100%{ opacity:0; }
4100
+ }
4101
+
4102
+
4103
+ /* ======================================================
4104
+ FRAME MINI FIX: Overlay oben tiefer wegen Statusbar
4105
+ ====================================================== */
4106
+
4107
+ /* Overlay etwas weiter nach unten */
4108
+ body.jf-page-frame .jfFlightSwitch{
4109
+ top:42px !important;
4110
+ left:-36px !important;
4111
+ right:-36px !important;
4112
+ bottom:-36px !important;
4113
+ }
4114
+
4115
+ /* Radar ebenfalls minimal tiefer */
4116
+ body.jf-page-frame .jfFlightSwitchRadar{
4117
+ transform:translateY(22px) scale(1.02) !important;
4118
+ }
4119
+
4120
+ /* Text unten stabil */
4121
+ body.jf-page-frame .jfFlightSwitchNext{
4122
+ bottom:72px !important;
4123
+ }
4124
+
4125
+ /* weicher Verlauf oben */
4126
+ body.jf-page-frame .jfFlightSwitch::before{
4127
+ content:"";
4128
+ position:absolute;
4129
+ inset:-60px;
4130
+ background:
4131
+ linear-gradient(
4132
+ 180deg,
4133
+ transparent 0%,
4134
+ rgba(8,10,18,.10) 12%,
4135
+ rgba(8,10,18,.28) 22%,
4136
+ rgba(8,10,18,.52) 100%
4137
+ );
4138
+ pointer-events:none;
4139
+ }
4140
+
4141
+
4142
+
4143
+ /* ======================================================
4144
+ INDEX: Global Power Button
4145
+ ====================================================== */
4146
+
4147
+ html,
4148
+ body{
4149
+ touch-action:pan-x pan-y;
4150
+ overscroll-behavior:none;
4151
+ -webkit-text-size-adjust:100%;
4152
+ }
4153
+
4154
+ body.jf-page-home #globalPowerBtn.power{
4155
+ cursor:pointer;
4156
+ border-color:rgba(50,232,121,.28);
4157
+ background:
4158
+ linear-gradient(135deg, rgba(50,232,121,.18), rgba(255,255,255,.07));
4159
+ }
4160
+
4161
+ body.jf-page-home #globalPowerBtn.power.off{
4162
+ border-color:rgba(255,77,94,.32);
4163
+ background:
4164
+ linear-gradient(135deg, rgba(255,77,94,.18), rgba(255,255,255,.06));
4165
+ }
4166
+
4167
+ body.jf-page-home .powerState{
4168
+ min-width:58px;
4169
+ height:38px;
4170
+ border-radius:999px;
4171
+ display:grid;
4172
+ place-items:center;
4173
+ font-weight:950;
4174
+ letter-spacing:.03em;
4175
+ background:rgba(50,232,121,.18);
4176
+ border:1px solid rgba(50,232,121,.36);
4177
+ color:#dffff0;
4178
+ }
4179
+
4180
+ body.jf-page-home #globalPowerBtn.off .powerState{
4181
+ background:rgba(255,77,94,.18);
4182
+ border-color:rgba(255,77,94,.38);
4183
+ color:#ffd2d7;
4184
+ }
4185
+
4186
+ /* ======================================================
4187
+ FRAME MINI FIX: Airline/Manufacturer Row Alignment
4188
+ ====================================================== */
4189
+
4190
+ body.jf-page-frame #aircraftCard.aircraftCard{
4191
+ --jfLogoSize: 34px;
4192
+ --jfLogoGap: 14px;
4193
+ }
4194
+
4195
+ /* beide Zeilen identisch aufbauen */
4196
+ body.jf-page-frame #airlineMini,
4197
+ body.jf-page-frame #manufacturerLogo{
4198
+ display:grid !important;
4199
+ grid-template-columns:var(--jfLogoSize) minmax(0, 1fr) !important;
4200
+ align-items:center !important;
4201
+ column-gap:var(--jfLogoGap) !important;
4202
+ }
4203
+
4204
+ /* Logo-Kreise exakt gleich groß */
4205
+ body.jf-page-frame #airlineLogoImg,
4206
+ body.jf-page-frame #manufacturerLogoImg,
4207
+ body.jf-page-frame #manufacturerLogoText{
4208
+ width:var(--jfLogoSize) !important;
4209
+ height:var(--jfLogoSize) !important;
4210
+ min-width:var(--jfLogoSize) !important;
4211
+ min-height:var(--jfLogoSize) !important;
4212
+ max-width:var(--jfLogoSize) !important;
4213
+ max-height:var(--jfLogoSize) !important;
4214
+ border-radius:999px !important;
4215
+ object-fit:contain !important;
4216
+ box-sizing:border-box !important;
4217
+ }
4218
+
4219
+ /* Textstart bei Airline und Hersteller exakt gleich */
4220
+ body.jf-page-frame #airline{
4221
+ grid-column:2 !important;
4222
+ align-self:center !important;
4223
+ }
4224
+
4225
+ body.jf-page-frame #aircraftTypeText{
4226
+ grid-column:1 !important;
4227
+ margin-left:calc(var(--jfLogoSize) + var(--jfLogoGap)) !important;
4228
+ align-self:center !important;
4229
+ }
4230
+
4231
+ /* Größen harmonisieren */
4232
+ body.jf-page-frame #airline,
4233
+ body.jf-page-frame #aircraftTypeText,
4234
+ body.jf-page-frame #aircraftSize{
4235
+ font-size:clamp(16px, 2.15vmin, 26px) !important;
4236
+ line-height:1.05 !important;
4237
+ }
4238
+
4239
+ /* Size rechts sauber mittig */
4240
+ body.jf-page-frame #aircraftSize{
4241
+ align-self:center !important;
4242
+ justify-self:end !important;
4243
+ }
4244
+
4245
+ /* Querformat minimal kompakter, aber gleiches Raster */
4246
+ @media (orientation:landscape){
4247
+ body.jf-page-frame #aircraftCard.aircraftCard{
4248
+ --jfLogoSize: 30px;
4249
+ --jfLogoGap: 12px;
4250
+ }
4251
+
4252
+ body.jf-page-frame #airline,
4253
+ body.jf-page-frame #aircraftTypeText,
4254
+ body.jf-page-frame #aircraftSize{
4255
+ font-size:clamp(14px, 2.55vmin, 22px) !important;
4256
+ }
4257
+ }
4258
+
4259
+
4260
+
4261
+ /* ======================================================
4262
+ LANDSCAPE: alles etwas kleiner, damit Special reinpasst
4263
+ ====================================================== */
4264
+
4265
+ @media (orientation:landscape){
4266
+ body.jf-page-frame #aircraftCard.aircraftCard{
4267
+ --jfLogoSize: clamp(24px, 3.1vmin, 30px);
4268
+ --jfLogoGap: clamp(8px, 1.1vmin, 12px);
4269
+
4270
+ width:min(58%, 520px) !important;
4271
+ max-width:520px !important;
4272
+ row-gap:clamp(4px, .65vmin, 7px) !important;
4273
+ padding-top:clamp(7px, 1vmin, 10px) !important;
4274
+ padding-bottom:clamp(7px, 1vmin, 10px) !important;
4275
+ }
4276
+
4277
+ body.jf-page-frame #airline,
4278
+ body.jf-page-frame #aircraftTypeText,
4279
+ body.jf-page-frame #aircraftSize{
4280
+ font-size:clamp(13px, 2.05vmin, 19px) !important;
4281
+ line-height:1.02 !important;
4282
+ }
4283
+
4284
+ body.jf-page-frame .reg{
4285
+ font-size:clamp(12px, 1.75vmin, 17px) !important;
4286
+ margin-top:clamp(3px, .55vmin, 6px) !important;
4287
+ }
4288
+
4289
+ body.jf-page-frame .special{
4290
+ max-width:min(44%, 390px) !important;
4291
+ font-size:clamp(11px, 1.75vmin, 16px) !important;
4292
+ line-height:1.05 !important;
4293
+ padding:clamp(5px, .75vmin, 8px) clamp(10px, 1.2vmin, 14px) !important;
4294
+ margin-top:clamp(4px, .6vmin, 7px) !important;
4295
+ }
4296
+
4297
+ body.jf-page-frame .info{
4298
+ gap:clamp(3px, .55vmin, 7px) !important;
4299
+ }
4300
+
4301
+ body.jf-page-frame .routeCities{
4302
+ line-height:1.13 !important;
4303
+ padding-bottom:.08em !important;
4304
+ }
4305
+
4306
+ body.jf-page-frame .routeCodes{
4307
+ margin-top:-.08em !important;
4308
+ }
4309
+ }
4310
+
4311
+ /* ======================================================
4312
+ PRELOAD: Card-Blöcke an neue echte Card-Größe angleichen
4313
+ ====================================================== */
4314
+
4315
+ body.jf-page-frame.jf-preload .preCard,
4316
+ body.jf-page-frame.jf-preload .sk-card{
4317
+ width:min(70%, 560px) !important;
4318
+ max-width:560px !important;
4319
+ }
4320
+
4321
+ @media (orientation:landscape){
4322
+ body.jf-page-frame.jf-preload .preCard,
4323
+ body.jf-page-frame.jf-preload .sk-card{
4324
+ width:min(58%, 520px) !important;
4325
+ max-width:520px !important;
4326
+ }
4327
+
4328
+ body.jf-page-frame.jf-preload .preInfo,
4329
+ body.jf-page-frame.jf-preload .jfInfoSkeleton{
4330
+ gap:clamp(3px, .55vmin, 7px) !important;
4331
+ }
4332
+ }
4333
+
4334
+
4335
+
4336
+
4337
+ /* ======================================================
4338
+ FRAME CLEAN: Aircraft Card einheitlich
4339
+ ====================================================== */
4340
+
4341
+ body.jf-page-frame:not(.jf-preload) #aircraftCard.aircraftCard{
4342
+ --jfCardLogo: clamp(30px, 3.9vmin, 40px);
4343
+ --jfCardGap: clamp(10px, 1.2vmin, 14px);
4344
+
4345
+ display:grid !important;
4346
+ grid-template-columns:var(--jfCardLogo) minmax(0, 1fr) auto !important;
4347
+ grid-template-rows:auto auto auto !important;
4348
+ column-gap:var(--jfCardGap) !important;
4349
+ row-gap:clamp(6px, .85vmin, 10px) !important;
4350
+ align-items:center !important;
4351
+ width:min(70%, 560px) !important;
4352
+ max-width:560px !important;
4353
+ overflow:hidden !important;
4354
+ }
4355
+
4356
+ /* Airline-Zeile */
4357
+ body.jf-page-frame:not(.jf-preload) #airlineMini{
4358
+ grid-column:1 / 4 !important;
4359
+ grid-row:1 !important;
4360
+ display:grid !important;
4361
+ grid-template-columns:var(--jfCardLogo) minmax(0, 1fr) !important;
4362
+ column-gap:var(--jfCardGap) !important;
4363
+ align-items:center !important;
4364
+ min-width:0 !important;
4365
+ }
4366
+
4367
+ /* Divider */
4368
+ body.jf-page-frame:not(.jf-preload) #aircraftCard .aircraftSep{
4369
+ grid-column:1 / 4 !important;
4370
+ grid-row:2 !important;
4371
+ width:100% !important;
4372
+ height:1px !important;
4373
+ margin:0 !important;
4374
+ }
4375
+
4376
+ /* Hersteller-Zeile */
4377
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogo{
4378
+ grid-column:1 !important;
4379
+ grid-row:3 !important;
4380
+ width:var(--jfCardLogo) !important;
4381
+ height:var(--jfCardLogo) !important;
4382
+ min-width:var(--jfCardLogo) !important;
4383
+ min-height:var(--jfCardLogo) !important;
4384
+ display:grid !important;
4385
+ place-items:center !important;
4386
+ margin:0 !important;
4387
+ padding:0 !important;
4388
+ overflow:hidden !important;
4389
+ }
4390
+
4391
+ body.jf-page-frame:not(.jf-preload) #aircraftTypeText{
4392
+ grid-column:2 !important;
4393
+ grid-row:3 !important;
4394
+ margin:0 !important;
4395
+ padding:0 !important;
4396
+ min-width:0 !important;
4397
+ overflow:hidden !important;
4398
+ text-overflow:ellipsis !important;
4399
+ white-space:nowrap !important;
4400
+ align-self:center !important;
4401
+ }
4402
+
4403
+ body.jf-page-frame:not(.jf-preload) #aircraftSize{
4404
+ grid-column:3 !important;
4405
+ grid-row:3 !important;
4406
+ margin:0 !important;
4407
+ padding:0 !important;
4408
+ justify-self:end !important;
4409
+ align-self:center !important;
4410
+ white-space:nowrap !important;
4411
+ }
4412
+
4413
+ /* Logo-Badges exakt gleich */
4414
+ body.jf-page-frame:not(.jf-preload) #airlineLogoImg,
4415
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogoImg,
4416
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogoText{
4417
+ width:var(--jfCardLogo) !important;
4418
+ height:var(--jfCardLogo) !important;
4419
+ min-width:var(--jfCardLogo) !important;
4420
+ min-height:var(--jfCardLogo) !important;
4421
+ max-width:var(--jfCardLogo) !important;
4422
+ max-height:var(--jfCardLogo) !important;
4423
+ border-radius:999px !important;
4424
+ object-fit:contain !important;
4425
+ margin:0 !important;
4426
+ padding:0 !important;
4427
+ box-sizing:border-box !important;
4428
+ }
4429
+
4430
+ /* Fallback-Kreis nur anzeigen, wenn JS ihn wirklich braucht */
4431
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogoText{
4432
+ display:none !important;
4433
+ }
4434
+
4435
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogoText.isFallback{
4436
+ display:grid !important;
4437
+ place-items:center !important;
4438
+ }
4439
+
4440
+ /* Textgrößen in der Card harmonisieren */
4441
+ body.jf-page-frame:not(.jf-preload) #airline,
4442
+ body.jf-page-frame:not(.jf-preload) #aircraftTypeText,
4443
+ body.jf-page-frame:not(.jf-preload) #aircraftSize{
4444
+ font-size:clamp(16px, 2.15vmin, 25px) !important;
4445
+ line-height:1.06 !important;
4446
+ }
4447
+
4448
+ /* Special kompakt und nie über Metrics */
4449
+ body.jf-page-frame:not(.jf-preload) #special.special{
4450
+ max-width:min(70%, 520px) !important;
4451
+ overflow:hidden !important;
4452
+ text-overflow:ellipsis !important;
4453
+ white-space:nowrap !important;
4454
+ }
4455
+
4456
+ /* Querformat kompakter */
4457
+ @media (orientation:landscape){
4458
+ body.jf-page-frame:not(.jf-preload) #aircraftCard.aircraftCard{
4459
+ --jfCardLogo: clamp(24px, 3vmin, 30px);
4460
+ --jfCardGap: clamp(8px, 1vmin, 11px);
4461
+
4462
+ width:min(50%, 500px) !important;
4463
+ max-width:500px !important;
4464
+ row-gap:clamp(4px, .55vmin, 6px) !important;
4465
+ padding-top:clamp(7px, .85vmin, 10px) !important;
4466
+ padding-bottom:clamp(7px, .85vmin, 10px) !important;
4467
+ }
4468
+
4469
+ body.jf-page-frame:not(.jf-preload) #airline,
4470
+ body.jf-page-frame:not(.jf-preload) #aircraftTypeText,
4471
+ body.jf-page-frame:not(.jf-preload) #aircraftSize{
4472
+ font-size:clamp(13px, 1.75vmin, 18px) !important;
4473
+ line-height:1.02 !important;
4474
+ }
4475
+
4476
+ body.jf-page-frame:not(.jf-preload) #special.special{
4477
+ max-width:min(34%, 330px) !important;
4478
+ font-size:clamp(10px, 1.45vmin, 14px) !important;
4479
+ line-height:1.02 !important;
4480
+ padding:5px 11px !important;
4481
+ margin-top:3px !important;
4482
+ }
4483
+ }
4484
+
4485
+ /* ======================================================
4486
+ FRAME MINI FIX: Manufacturer/Airline Logos nicht abschneiden
4487
+ ====================================================== */
4488
+
4489
+ body.jf-page-frame:not(.jf-preload) #aircraftCard.aircraftCard{
4490
+ --jfCardLogo: clamp(34px, 4.1vmin, 42px) !important;
4491
+ row-gap:clamp(8px, 1vmin, 12px) !important;
4492
+ }
4493
+
4494
+ /* Logo-Zellen etwas Luft geben, damit runde Badges nicht beschnitten werden */
4495
+ body.jf-page-frame:not(.jf-preload) #airlineMini,
4496
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogo{
4497
+ overflow:visible !important;
4498
+ }
4499
+
4500
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogo{
4501
+ width:var(--jfCardLogo) !important;
4502
+ height:var(--jfCardLogo) !important;
4503
+ min-width:var(--jfCardLogo) !important;
4504
+ min-height:var(--jfCardLogo) !important;
4505
+ }
4506
+
4507
+ /* Bilder kleiner IN den Kreis setzen, Kreis bleibt gleich groß */
4508
+ body.jf-page-frame:not(.jf-preload) #airlineLogoImg,
4509
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogoImg,
4510
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogoText{
4511
+ width:var(--jfCardLogo) !important;
4512
+ height:var(--jfCardLogo) !important;
4513
+ min-width:var(--jfCardLogo) !important;
4514
+ min-height:var(--jfCardLogo) !important;
4515
+ max-width:var(--jfCardLogo) !important;
4516
+ max-height:var(--jfCardLogo) !important;
4517
+ padding:3px !important;
4518
+ object-fit:contain !important;
4519
+ object-position:center !important;
4520
+ overflow:hidden !important;
4521
+ }
4522
+
4523
+ /* Text bleibt sauber hinter dem Logo */
4524
+ body.jf-page-frame:not(.jf-preload) #aircraftTypeText{
4525
+ align-self:center !important;
4526
+ line-height:1.12 !important;
4527
+ }
4528
+
4529
+ body.jf-page-frame:not(.jf-preload) #airline{
4530
+ line-height:1.12 !important;
4531
+ }
4532
+
4533
+ /* Landscape wieder kompakter, aber nicht abschneiden */
4534
+ @media (orientation:landscape){
4535
+ body.jf-page-frame:not(.jf-preload) #aircraftCard.aircraftCard{
4536
+ --jfCardLogo: clamp(28px, 3.15vmin, 32px) !important;
4537
+ row-gap:clamp(5px, .7vmin, 8px) !important;
4538
+ }
4539
+
4540
+ body.jf-page-frame:not(.jf-preload) #airlineLogoImg,
4541
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogoImg,
4542
+ body.jf-page-frame:not(.jf-preload) #manufacturerLogoText{
4543
+ padding:2px !important;
4544
+ }
4545
+
4546
+ body.jf-page-frame:not(.jf-preload) #aircraftTypeText,
4547
+ body.jf-page-frame:not(.jf-preload) #airline{
4548
+ line-height:1.08 !important;
4549
+ }
4550
+ }
4551
+
4552
+
4553
+
4554
+
4555
+
4556
+ /* gleiche Kreisgröße wie die weißen Kreise */
4557
+ :root{
4558
+ --jfLogoCircle: 54px;
4559
+ }
4560
+
4561
+ /* Reihen sauber */
4562
+ .airlineMini,
4563
+ .manufacturerMini{
4564
+ display:flex !important;
4565
+ align-items:center !important;
4566
+ gap:16px !important;
4567
+ }
4568
+
4569
+ /* Logos exakt gleich */
4570
+ #airlineLogoImg,
4571
+ #manufacturerLogoImg,
4572
+ #manufacturerLogoText{
4573
+ width:var(--jfLogoCircle) !important;
4574
+ height:var(--jfLogoCircle) !important;
4575
+ min-width:var(--jfLogoCircle) !important;
4576
+ min-height:var(--jfLogoCircle) !important;
4577
+ max-width:var(--jfLogoCircle) !important;
4578
+ max-height:var(--jfLogoCircle) !important;
4579
+
4580
+ border-radius:999px !important;
4581
+ object-fit:contain !important;
4582
+ object-position:center !important;
4583
+
4584
+ display:flex !important;
4585
+ align-items:center !important;
4586
+ justify-content:center !important;
4587
+
4588
+ overflow:hidden !important;
4589
+ flex-shrink:0 !important;
4590
+ box-sizing:border-box !important;
4591
+ }
4592
+
4593
+ /* Airbus/Text NICHT verrutschen */
4594
+ #aircraftTypeText{
4595
+ margin-left:0 !important;
4596
+ padding-left:0 !important;
4597
+ position:relative !important;
4598
+ left:0 !important;
4599
+ transform:none !important;
4600
+ align-self:center !important;
4601
+ }
4602
+
4603
+ /* Airline ebenfalls */
4604
+ #airline{
4605
+ margin-left:0 !important;
4606
+ padding-left:0 !important;
4607
+ align-self:center !important;
4608
+ }
4609
+
4610
+ /* Landscape kompakter */
4611
+ @media (orientation:landscape){
4612
+
4613
+ :root{
4614
+ --jfLogoCircle: 44px;
4615
+ }
4616
+
4617
+ .airlineMini,
4618
+ .manufacturerMini{
4619
+ gap:12px !important;
4620
+ }
4621
+
4622
+ #aircraftTypeText,
4623
+ #airline{
4624
+ font-size:.92em !important;
4625
+ line-height:1.05 !important;
4626
+ }
4627
+ }
4628
+
4629
+
4630
+
4631
+
4632
+
4633
+ @media (orientation:landscape){
4634
+
4635
+ /* Zweite Reihe sauber */
4636
+ .manufacturerMini{
4637
+ display:grid !important;
4638
+ grid-template-columns: 44px minmax(0,1fr) auto !important;
4639
+ align-items:center !important;
4640
+ column-gap:14px !important;
4641
+ }
4642
+
4643
+ /* Airbus Text NICHT mittig/rechts */
4644
+ #aircraftTypeText{
4645
+ justify-self:start !important;
4646
+ text-align:left !important;
4647
+
4648
+ margin:0 !important;
4649
+ padding:0 !important;
4650
+
4651
+ width:auto !important;
4652
+ min-width:0 !important;
4653
+
4654
+ transform:none !important;
4655
+ left:auto !important;
4656
+ position:relative !important;
4657
+ }
4658
+
4659
+ /* Widebody rechts halten */
4660
+ #aircraftClass{
4661
+ justify-self:end !important;
4662
+ text-align:right !important;
4663
+ white-space:nowrap !important;
4664
+ }
4665
+ }
4666
+
4667
+
4668
+
4669
+ /* ======================================================
4670
+ SINGLE CLEAN AIRCRAFT ALIGN FIX
4671
+ ====================================================== */
4672
+
4673
+ :root{
4674
+ --jfLogoCircle: 44px;
4675
+ }
4676
+
4677
+ /* Reihen */
4678
+ .airlineMini,
4679
+ .manufacturerMini{
4680
+ display:grid !important;
4681
+ grid-template-columns: var(--jfLogoCircle) minmax(0,1fr) auto !important;
4682
+ align-items:center !important;
4683
+ column-gap:14px !important;
4684
+ }
4685
+
4686
+ /* Kreise */
4687
+ #airlineLogoImg,
4688
+ #manufacturerLogoImg,
4689
+ #manufacturerLogoText{
4690
+ width:var(--jfLogoCircle) !important;
4691
+ height:var(--jfLogoCircle) !important;
4692
+ min-width:var(--jfLogoCircle) !important;
4693
+ min-height:var(--jfLogoCircle) !important;
4694
+ max-width:var(--jfLogoCircle) !important;
4695
+ max-height:var(--jfLogoCircle) !important;
4696
+
4697
+ border-radius:999px !important;
4698
+ object-fit:contain !important;
4699
+ object-position:center !important;
4700
+
4701
+ overflow:hidden !important;
4702
+ flex-shrink:0 !important;
4703
+ }
4704
+
4705
+ /* Airline Text */
4706
+ #airline{
4707
+ margin:0 !important;
4708
+ padding:0 !important;
4709
+ line-height:1.05 !important;
4710
+ justify-self:start !important;
4711
+ text-align:left !important;
4712
+ }
4713
+
4714
+ /* Airbus Text */
4715
+ #aircraftTypeText{
4716
+ margin:0 !important;
4717
+ padding:0 !important;
4718
+ line-height:1.05 !important;
4719
+
4720
+ justify-self:start !important;
4721
+ text-align:left !important;
4722
+
4723
+ transform:none !important;
4724
+ left:auto !important;
4725
+ }
4726
+
4727
+ /* Klasse rechts */
4728
+ #aircraftClass{
4729
+ justify-self:end !important;
4730
+ text-align:right !important;
4731
+ white-space:nowrap !important;
4732
+ }
4733
+
4734
+ /* Landscape */
4735
+ @media (orientation:landscape){
4736
+
4737
+ :root{
4738
+ --jfLogoCircle: 40px;
4739
+ }
4740
+
4741
+ .airlineMini,
4742
+ .manufacturerMini{
4743
+ column-gap:12px !important;
4744
+ }
4745
+
4746
+ #airline,
4747
+ #aircraftTypeText{
4748
+ font-size:.95em !important;
4749
+ }
4750
+ }
4751
+
4752
+
4753
+
4754
+ /* ======================================================
4755
+ HARD LEFT AIRBUS FIX
4756
+ ====================================================== */
4757
+
4758
+ @media (orientation:landscape){
4759
+
4760
+ /* zweite Reihe exakt links/rechts */
4761
+ .manufacturerMini{
4762
+ display:flex !important;
4763
+ align-items:center !important;
4764
+ gap:14px !important;
4765
+ }
4766
+
4767
+ /* Airbus Text ganz links */
4768
+ #aircraftTypeText{
4769
+ flex:1 1 auto !important;
4770
+
4771
+ margin:0 !important;
4772
+ padding:0 !important;
4773
+
4774
+ text-align:left !important;
4775
+
4776
+ transform:none !important;
4777
+ left:0 !important;
4778
+ right:auto !important;
4779
+
4780
+ position:static !important;
4781
+ }
4782
+
4783
+ /* Widebody rechts fest */
4784
+ #aircraftClass{
4785
+ margin-left:auto !important;
4786
+ text-align:right !important;
4787
+ white-space:nowrap !important;
4788
+ }
4789
+ }
4790
+