@inventure71/paddockjs 0.2.0 → 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 (63) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/INSTALL_AND_UPDATE.md +165 -0
  3. package/README.md +217 -20
  4. package/docs/architecture.md +84 -15
  5. package/docs/concepts.md +20 -3
  6. package/docs/data_contract.md +412 -20
  7. package/docs/data_model.md +2 -1
  8. package/docs/index.md +1 -0
  9. package/docs/learnings.md +1 -1
  10. package/docs/rules.md +140 -19
  11. package/docs/system_specs.md +74 -20
  12. package/docs/training.md +206 -0
  13. package/examples/train-basic-policy.mjs +276 -0
  14. package/examples/trainingData.mjs +133 -0
  15. package/package.json +18 -8
  16. package/src/api/PaddockSimulatorController.js +39 -4
  17. package/src/app/BrowserExpertAdapter.js +32 -0
  18. package/src/app/F1SimulatorApp.js +1251 -146
  19. package/src/app/domBindings.js +10 -2
  20. package/src/config/defaultOptions.js +11 -3
  21. package/src/data/championship.js +13 -0
  22. package/src/data/normalizeDrivers.js +7 -2
  23. package/src/environment/actions.js +68 -0
  24. package/src/environment/episode.js +17 -0
  25. package/src/environment/evaluation.js +184 -0
  26. package/src/environment/events.js +17 -0
  27. package/src/environment/index.d.ts +521 -0
  28. package/src/environment/index.js +15 -0
  29. package/src/environment/observationOptions.js +12 -0
  30. package/src/environment/observations.js +284 -0
  31. package/src/environment/options.js +157 -0
  32. package/src/environment/recorder.js +28 -0
  33. package/src/environment/rewards.js +69 -0
  34. package/src/environment/runtime.js +175 -0
  35. package/src/environment/scenarios.js +220 -0
  36. package/src/environment/sensors.js +367 -0
  37. package/src/environment/specs.js +163 -0
  38. package/src/environment/workerProtocol.js +52 -0
  39. package/src/index.d.ts +405 -6
  40. package/src/index.js +27 -2
  41. package/src/rendering/proceduralTrackAsset.js +343 -24
  42. package/src/simulation/collisionGeometry.js +214 -0
  43. package/src/simulation/driverController.js +431 -65
  44. package/src/simulation/raceSimulation.js +2140 -171
  45. package/src/simulation/rules/collisionSteward.js +69 -0
  46. package/src/simulation/rules/penaltyLedger.js +153 -0
  47. package/src/simulation/rules/pitLaneSpeedingSteward.js +71 -0
  48. package/src/simulation/rules/tireRequirementSteward.js +29 -0
  49. package/src/simulation/rules/trackLimitsSteward.js +85 -0
  50. package/src/simulation/rulesConfig.js +352 -0
  51. package/src/simulation/trackModel.js +1154 -76
  52. package/src/simulation/units.js +6 -4
  53. package/src/simulation/vehicleGeometry.js +247 -0
  54. package/src/simulation/vehiclePhysics.js +82 -50
  55. package/src/simulation/wheelSurface.js +338 -0
  56. package/src/styles.css +369 -67
  57. package/src/ui/bannerTemplates.js +69 -0
  58. package/src/ui/componentTemplates.js +45 -81
  59. package/src/ui/raceControlStatusBanner.js +39 -0
  60. package/src/ui/shellTemplate.js +1 -1
  61. package/src/ui/templateUtils.js +23 -0
  62. package/AGENTS.md +0 -86
  63. package/src/standalone.js +0 -15
package/src/styles.css CHANGED
@@ -10,6 +10,7 @@
10
10
  --text: #f4f7fb;
11
11
  --muted: #8d97a7;
12
12
  --red: var(--paddock-accent-color, #e10600);
13
+ --race-control-red: #e10600;
13
14
  --green: var(--paddock-green-color, #14c784);
14
15
  --yellow: var(--paddock-yellow-color, #ffd166);
15
16
  --blue: #39a7ff;
@@ -68,6 +69,8 @@
68
69
 
69
70
  .sim-backlink,
70
71
  .sim-control {
72
+ min-width: 0;
73
+ overflow: hidden;
71
74
  border: 1px solid var(--line-strong);
72
75
  color: var(--text);
73
76
  background: rgba(255, 255, 255, 0.05);
@@ -77,6 +80,8 @@
77
80
  font-size: 0.76rem;
78
81
  font-weight: 800;
79
82
  padding: 0.75rem 0.9rem;
83
+ text-overflow: ellipsis;
84
+ white-space: nowrap;
80
85
  cursor: pointer;
81
86
  }
82
87
 
@@ -92,7 +97,8 @@
92
97
  border-color: var(--yellow);
93
98
  }
94
99
 
95
- .camera-controls button.is-active {
100
+ .camera-controls button.is-active,
101
+ .camera-controls button[aria-pressed='true'] {
96
102
  color: #08090b;
97
103
  background: var(--text);
98
104
  border-color: var(--text);
@@ -121,6 +127,7 @@
121
127
  }
122
128
 
123
129
  .sim-controls {
130
+ min-width: 0;
124
131
  display: flex;
125
132
  gap: 0.6rem;
126
133
  justify-content: flex-end;
@@ -128,7 +135,7 @@
128
135
 
129
136
  .sim-external-camera-controls {
130
137
  display: flex;
131
- justify-content: flex-end;
138
+ justify-content: flex-start;
132
139
  }
133
140
 
134
141
  .sim-grid {
@@ -136,7 +143,7 @@
136
143
  min-height: 0;
137
144
  position: relative;
138
145
  display: grid;
139
- grid-template-columns: minmax(255px, 0.78fr) minmax(500px, 3fr) minmax(270px, 0.9fr);
146
+ grid-template-columns: minmax(0, 0.78fr) minmax(0, 3fr) minmax(0, 0.9fr);
140
147
  gap: 0.9rem;
141
148
  }
142
149
 
@@ -229,12 +236,12 @@
229
236
  }
230
237
 
231
238
  .sim-shell--left-tower-overlay .race-data-panel {
232
- z-index: 8;
239
+ z-index: 12;
233
240
  grid-template-columns: clamp(4.6rem, 7.5cqw, 7rem) minmax(0, 1fr) auto;
234
241
  }
235
242
 
236
243
  .sim-canvas-panel--with-timing-tower .race-data-panel {
237
- z-index: 8;
244
+ z-index: 12;
238
245
  grid-template-columns: clamp(4.6rem, 7.5cqw, 7rem) minmax(0, 1fr) auto;
239
246
  }
240
247
 
@@ -296,8 +303,13 @@
296
303
 
297
304
  .telemetry-stack {
298
305
  display: grid;
306
+ grid-auto-rows: max-content;
307
+ align-content: start;
299
308
  gap: 0.72rem;
300
309
  min-height: 0;
310
+ max-height: 100%;
311
+ overflow-y: auto;
312
+ scrollbar-width: thin;
301
313
  }
302
314
 
303
315
  .telemetry-stack > .sim-telemetry {
@@ -360,7 +372,7 @@
360
372
 
361
373
  .broadcast-brand,
362
374
  .broadcast-lap,
363
- .broadcast-safety-banner,
375
+ .broadcast-race-control-banner,
364
376
  .broadcast-column-head,
365
377
  .timing-list {
366
378
  position: relative;
@@ -409,21 +421,31 @@
409
421
  letter-spacing: -0.04em;
410
422
  }
411
423
 
412
- .broadcast-safety-banner {
424
+ .broadcast-race-control-banner {
413
425
  display: grid;
414
426
  grid-template-columns: 3.4rem minmax(0, 1fr);
415
427
  align-items: center;
416
428
  margin: 0;
429
+ background: rgba(255, 255, 255, 0.16);
430
+ color: #fff;
431
+ text-transform: uppercase;
432
+ }
433
+
434
+ .broadcast-race-control-banner.is-safety-car {
417
435
  background: #e0ce00;
418
436
  color: #0a0b0d;
419
- text-transform: uppercase;
420
437
  }
421
438
 
422
- .broadcast-safety-banner[hidden] {
439
+ .broadcast-race-control-banner.is-red-flag {
440
+ background: var(--race-control-red);
441
+ color: #fff;
442
+ }
443
+
444
+ .broadcast-race-control-banner[hidden] {
423
445
  display: none;
424
446
  }
425
447
 
426
- .broadcast-safety-banner span {
448
+ .broadcast-race-control-banner span {
427
449
  display: grid;
428
450
  place-items: center;
429
451
  min-height: 2.65rem;
@@ -434,7 +456,7 @@
434
456
  letter-spacing: -0.06em;
435
457
  }
436
458
 
437
- .broadcast-safety-banner strong {
459
+ .broadcast-race-control-banner strong {
438
460
  padding: 0 0.65rem;
439
461
  font-size: 1.1rem;
440
462
  font-weight: 900;
@@ -562,6 +584,11 @@
562
584
  scrollbar-width: thin;
563
585
  }
564
586
 
587
+ .timing-list > li {
588
+ min-width: 0;
589
+ overflow: hidden;
590
+ }
591
+
565
592
  .sim-shell--left-tower-overlay .timing-list {
566
593
  overflow-x: hidden;
567
594
  overflow-y: auto;
@@ -603,6 +630,10 @@
603
630
  min-width: 0;
604
631
  }
605
632
 
633
+ .timing-row > * {
634
+ min-width: 0;
635
+ }
636
+
606
637
  .sim-shell--left-tower-overlay .timing-row {
607
638
  min-width: 0;
608
639
  }
@@ -668,7 +699,9 @@
668
699
 
669
700
  .timing-name {
670
701
  min-width: 0;
671
- display: block;
702
+ display: flex;
703
+ align-items: center;
704
+ gap: 0.26rem;
672
705
  overflow: hidden;
673
706
  padding-inline: 0.45rem;
674
707
  font-size: 0.76rem;
@@ -680,11 +713,37 @@
680
713
  text-transform: uppercase;
681
714
  }
682
715
 
716
+ .timing-name > span:first-child {
717
+ min-width: 0;
718
+ overflow: hidden;
719
+ text-overflow: ellipsis;
720
+ }
721
+
722
+ .timing-penalty-badge {
723
+ flex: 0 0 auto;
724
+ display: grid;
725
+ place-items: center;
726
+ width: 1rem;
727
+ height: 1rem;
728
+ color: #fff;
729
+ background: #e10600;
730
+ border: 1px solid rgba(255, 220, 220, 0.78);
731
+ border-radius: 0.18rem;
732
+ font-family: var(--font-mono);
733
+ font-size: 0.66rem;
734
+ font-weight: 900;
735
+ line-height: 1;
736
+ box-shadow: 0 0 14px rgba(225, 6, 0, 0.42);
737
+ }
738
+
683
739
  .timing-gap {
684
740
  color: rgba(244, 247, 251, 0.76);
685
741
  font-size: 0.66rem;
742
+ overflow: hidden;
686
743
  padding-right: 0.25rem;
687
744
  text-align: right;
745
+ text-overflow: ellipsis;
746
+ white-space: nowrap;
688
747
  }
689
748
 
690
749
  .timing-row.is-selected .timing-gap {
@@ -728,6 +787,11 @@
728
787
  .track-canvas {
729
788
  position: absolute;
730
789
  inset: 0;
790
+ z-index: 0;
791
+ background: #2e7d32;
792
+ cursor: default;
793
+ user-select: none;
794
+ touch-action: auto;
731
795
  }
732
796
 
733
797
  .track-canvas canvas {
@@ -738,18 +802,41 @@
738
802
 
739
803
  .race-telemetry-drawer {
740
804
  --telemetry-drawer-width: min(390px, max(300px, 30cqw));
805
+ --race-toolbar-height: 3.4rem;
741
806
  position: relative;
742
- display: block;
807
+ display: flex;
808
+ flex-direction: column;
743
809
  container-type: inline-size;
744
- min-height: var(--paddock-race-view-min-height, 620px);
810
+ inline-size: 100%;
811
+ max-inline-size: 100%;
812
+ height: var(--paddock-race-view-height, var(--paddock-race-view-min-height, 620px));
813
+ min-height: min(100%, var(--paddock-race-view-min-height, 620px));
745
814
  overflow: hidden;
746
815
  background: #000;
747
816
  }
748
817
 
818
+ .race-telemetry-drawer__toolbar {
819
+ position: relative;
820
+ z-index: 13;
821
+ display: flex;
822
+ align-items: center;
823
+ justify-content: space-between;
824
+ gap: 0.7rem;
825
+ min-height: var(--race-toolbar-height);
826
+ padding: 0.45rem;
827
+ background: #090b0d;
828
+ border-bottom: 1px solid var(--line);
829
+ }
830
+
831
+ .race-telemetry-drawer__toolbar .camera-controls--external {
832
+ flex: 1 1 auto;
833
+ }
834
+
749
835
  .race-telemetry-drawer__race {
750
836
  min-width: 0;
751
837
  display: flex;
752
- min-height: inherit;
838
+ flex: 1 1 auto;
839
+ min-height: 0;
753
840
  margin-right: 0;
754
841
  transition: margin-right 320ms cubic-bezier(0.2, 0.8, 0.2, 1);
755
842
  }
@@ -760,15 +847,12 @@
760
847
 
761
848
  .race-telemetry-drawer__race > .sim-canvas-panel {
762
849
  flex: 1 1 auto;
763
- min-height: inherit;
764
- height: auto;
850
+ min-height: 0;
851
+ height: 100%;
765
852
  }
766
853
 
767
854
  .race-telemetry-drawer__controls {
768
- position: absolute;
769
- z-index: 12;
770
- top: 1rem;
771
- right: 1rem;
855
+ min-width: 0;
772
856
  display: flex;
773
857
  flex-wrap: wrap;
774
858
  justify-content: flex-end;
@@ -779,7 +863,6 @@
779
863
  .race-telemetry-drawer__controls .telemetry-drawer-toggle {
780
864
  min-height: 2.45rem;
781
865
  padding: 0.62rem 0.72rem;
782
- box-shadow: 0 14px 34px rgba(0, 0, 0, 0.3);
783
866
  }
784
867
 
785
868
  .telemetry-drawer-toggle {
@@ -797,73 +880,46 @@
797
880
  .telemetry-drawer {
798
881
  position: absolute;
799
882
  z-index: 11;
800
- top: 0;
883
+ top: var(--race-toolbar-height);
801
884
  right: 0;
802
885
  bottom: 0;
803
886
  width: var(--telemetry-drawer-width);
804
887
  min-width: 0;
805
- height: 100%;
888
+ height: calc(100% - var(--race-toolbar-height));
806
889
  overflow: hidden;
807
890
  color: var(--text);
808
891
  background:
809
892
  linear-gradient(180deg, rgba(255, 255, 255, 0.075), transparent 22%),
810
893
  rgba(8, 9, 11, 0.97);
811
894
  border-left: 1px solid var(--line);
812
- transform: translate3d(100%, 0, 0);
895
+ clip-path: inset(0 0 0 100%);
896
+ transform: translate3d(0, 0, 0);
813
897
  opacity: 0;
814
898
  pointer-events: none;
815
899
  will-change: transform, opacity;
816
900
  transition:
817
- transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1),
901
+ clip-path 320ms cubic-bezier(0.2, 0.8, 0.2, 1),
818
902
  opacity 180ms ease;
819
903
  }
820
904
 
821
905
  .race-telemetry-drawer.is-telemetry-open .telemetry-drawer {
822
- transform: translate3d(0, 0, 0);
906
+ clip-path: inset(0);
823
907
  opacity: 1;
824
908
  pointer-events: auto;
825
909
  }
826
910
 
827
- .telemetry-drawer__header {
828
- display: flex;
829
- align-items: center;
830
- justify-content: space-between;
831
- gap: 0.75rem;
832
- padding: 0.8rem 0.85rem;
833
- border-bottom: 1px solid var(--line);
834
- text-transform: uppercase;
835
- }
836
-
837
- .telemetry-drawer__header span {
838
- color: var(--green);
839
- font-family: var(--font-mono);
840
- font-size: 0.72rem;
841
- font-weight: 900;
842
- letter-spacing: 0.16em;
843
- }
844
-
845
- .telemetry-drawer__header button {
846
- border: 1px solid rgba(255, 255, 255, 0.18);
847
- color: var(--text);
848
- background: rgba(255, 255, 255, 0.06);
849
- font-family: var(--font-mono);
850
- font-size: 0.62rem;
851
- font-weight: 900;
852
- letter-spacing: 0.1em;
853
- text-transform: uppercase;
854
- padding: 0.45rem 0.54rem;
855
- cursor: pointer;
856
- }
857
-
858
911
  .telemetry-drawer__content {
859
- display: grid;
860
- gap: 0.72rem;
861
- height: calc(100% - 3.4rem);
912
+ height: 100%;
862
913
  padding: 0.72rem;
863
- overflow-y: auto;
914
+ min-height: 0;
915
+ overflow: hidden;
864
916
  scrollbar-width: thin;
865
917
  }
866
918
 
919
+ .telemetry-drawer__content > .telemetry-stack {
920
+ height: 100%;
921
+ }
922
+
867
923
  .camera-controls {
868
924
  position: absolute;
869
925
  top: 1rem;
@@ -880,6 +936,8 @@
880
936
 
881
937
  .camera-controls--external {
882
938
  position: relative;
939
+ top: auto;
940
+ left: auto;
883
941
  max-width: 100%;
884
942
  justify-content: flex-end;
885
943
  background: rgba(8, 9, 11, 0.84);
@@ -902,6 +960,89 @@
902
960
  border-color: var(--text);
903
961
  }
904
962
 
963
+ .steward-message {
964
+ --steward-panel-bg: rgba(8, 9, 11, 0.92);
965
+ --steward-chip-bg: color-mix(in srgb, var(--steward-color, var(--yellow)) 18%, rgba(8, 9, 11, 0.94));
966
+ --steward-chip-color: var(--steward-color, var(--yellow));
967
+ position: absolute;
968
+ top: 1rem;
969
+ left: 50%;
970
+ z-index: 8;
971
+ display: grid;
972
+ grid-template-columns: auto minmax(0, 1fr);
973
+ gap: 0.16rem 0.7rem;
974
+ min-width: min(28rem, calc(100% - 2rem));
975
+ max-width: min(34rem, calc(100% - 2rem));
976
+ padding: 0.62rem 0.75rem;
977
+ color: var(--text);
978
+ background: var(--steward-panel-bg);
979
+ border: 1px solid color-mix(in srgb, var(--steward-color, var(--yellow)) 70%, transparent);
980
+ box-shadow:
981
+ inset 0 3px 0 var(--steward-color, var(--yellow)),
982
+ 0 16px 40px rgba(0, 0, 0, 0.34);
983
+ transform: translate(-50%, 0);
984
+ opacity: 1;
985
+ pointer-events: none;
986
+ transition:
987
+ opacity 160ms ease,
988
+ transform 160ms ease;
989
+ }
990
+
991
+ .steward-message.is-penalty {
992
+ --steward-panel-bg: linear-gradient(110deg, rgba(68, 6, 8, 0.96), rgba(8, 9, 11, 0.94) 58%);
993
+ --steward-chip-bg: #e10600;
994
+ --steward-chip-color: #fff;
995
+ }
996
+
997
+ .steward-message.is-warning {
998
+ --steward-panel-bg: linear-gradient(110deg, rgba(70, 56, 8, 0.96), rgba(8, 9, 11, 0.94) 58%);
999
+ --steward-chip-bg: var(--yellow);
1000
+ --steward-chip-color: #111318;
1001
+ }
1002
+
1003
+ .steward-message.is-hidden {
1004
+ opacity: 0;
1005
+ transform: translate(-50%, -0.55rem);
1006
+ }
1007
+
1008
+ .steward-message__kicker {
1009
+ grid-row: span 2;
1010
+ align-self: center;
1011
+ min-width: 4.9rem;
1012
+ padding: 0.48rem 0.62rem;
1013
+ color: var(--steward-chip-color);
1014
+ background: var(--steward-chip-bg);
1015
+ border: 1px solid color-mix(in srgb, var(--steward-chip-color) 34%, transparent);
1016
+ font-family: var(--font-mono);
1017
+ font-size: 1.05rem;
1018
+ font-weight: 900;
1019
+ letter-spacing: 0.02em;
1020
+ line-height: 1;
1021
+ text-align: center;
1022
+ text-transform: uppercase;
1023
+ }
1024
+
1025
+ .steward-message strong {
1026
+ min-width: 0;
1027
+ overflow-wrap: anywhere;
1028
+ overflow: hidden;
1029
+ color: var(--text);
1030
+ font-size: 0.92rem;
1031
+ line-height: 1.08;
1032
+ text-transform: uppercase;
1033
+ white-space: normal;
1034
+ }
1035
+
1036
+ .steward-message span:last-child {
1037
+ min-width: 0;
1038
+ overflow-wrap: anywhere;
1039
+ overflow: hidden;
1040
+ color: var(--muted);
1041
+ font-size: 0.7rem;
1042
+ text-overflow: ellipsis;
1043
+ white-space: normal;
1044
+ }
1045
+
905
1046
  .fps-counter {
906
1047
  position: absolute;
907
1048
  top: 1rem;
@@ -1158,11 +1299,13 @@
1158
1299
  left: var(--race-data-banner-left);
1159
1300
  bottom: 1.2rem;
1160
1301
  transform: translateX(var(--race-data-banner-translate-x));
1161
- z-index: 8;
1302
+ z-index: 12;
1162
1303
  display: grid;
1163
- grid-template-columns: clamp(6.5rem, 12vw, 9.6rem) minmax(280px, 1fr) auto;
1304
+ grid-template-columns: clamp(6.5rem, 12vw, 9.6rem) minmax(0, 1fr) auto;
1164
1305
  align-items: center;
1165
1306
  width: var(--race-data-banner-width);
1307
+ max-width: calc(100% - 1.5rem);
1308
+ min-width: 0;
1166
1309
  min-height: 104px;
1167
1310
  color: var(--text);
1168
1311
  background:
@@ -1212,15 +1355,78 @@
1212
1355
 
1213
1356
  .race-data-copy,
1214
1357
  .race-data-number,
1215
- .race-data-link {
1358
+ .race-data-link,
1359
+ .race-data-dismiss {
1216
1360
  position: relative;
1217
1361
  z-index: 1;
1218
1362
  }
1219
1363
 
1364
+ .race-data-dismiss {
1365
+ --race-data-dismiss-icon-color: rgba(244, 247, 251, 0.9);
1366
+ position: absolute;
1367
+ top: 0.44rem;
1368
+ right: 0.48rem;
1369
+ display: grid;
1370
+ place-items: center;
1371
+ width: 0.95rem;
1372
+ height: 0.95rem;
1373
+ padding: 0;
1374
+ overflow: hidden;
1375
+ color: transparent;
1376
+ background: rgba(8, 10, 16, 0.62);
1377
+ border: 1px solid rgba(244, 247, 251, 0.24);
1378
+ border-radius: 999px;
1379
+ font-family: var(--font-mono);
1380
+ font-size: 0;
1381
+ font-weight: 900;
1382
+ line-height: 0;
1383
+ text-transform: none;
1384
+ white-space: nowrap;
1385
+ z-index: 4;
1386
+ }
1387
+
1388
+ .race-data-dismiss::before,
1389
+ .race-data-dismiss::after {
1390
+ content: "";
1391
+ position: absolute;
1392
+ left: 50%;
1393
+ top: 50%;
1394
+ width: 0.48rem;
1395
+ height: 0.1rem;
1396
+ background: var(--race-data-dismiss-icon-color);
1397
+ border-radius: 999px;
1398
+ }
1399
+
1400
+ .race-data-dismiss::before {
1401
+ transform: translate(-50%, -50%) rotate(45deg);
1402
+ }
1403
+
1404
+ .race-data-dismiss::after {
1405
+ transform: translate(-50%, -50%) rotate(-45deg);
1406
+ }
1407
+
1408
+ .race-data-dismiss:hover {
1409
+ --race-data-dismiss-icon-color: #fff;
1410
+ color: transparent;
1411
+ border-color: color-mix(in srgb, var(--driver-color, var(--red)) 70%, #ffffff);
1412
+ background: color-mix(in srgb, var(--driver-color, var(--red)) 52%, rgba(8, 10, 16, 0.72));
1413
+ }
1414
+
1415
+ .race-data-dismiss:focus-visible {
1416
+ outline: 2px solid var(--driver-color, var(--red));
1417
+ outline-offset: 2px;
1418
+ }
1419
+
1420
+ .race-data-panel--with-telemetry .race-data-dismiss,
1421
+ .race-data-panel.is-radio-mode .race-data-dismiss {
1422
+ z-index: 4;
1423
+ }
1424
+
1220
1425
  .race-data-copy {
1221
1426
  grid-column: 2;
1222
1427
  grid-row: 1;
1223
1428
  min-width: 0;
1429
+ overflow: hidden;
1224
1430
  padding: 0.92rem 1.45rem 0.98rem 0.55rem;
1225
1431
  }
1226
1432
 
@@ -1248,6 +1454,9 @@
1248
1454
 
1249
1455
  .race-data-subtitle {
1250
1456
  display: block;
1457
+ overflow: hidden;
1458
+ text-overflow: ellipsis;
1459
+ white-space: nowrap;
1251
1460
  margin-top: 0.28rem;
1252
1461
  color: rgba(244, 247, 251, 0.72);
1253
1462
  font-family: var(--font-mono);
@@ -1283,8 +1492,57 @@
1283
1492
  transform: translateX(-8px);
1284
1493
  }
1285
1494
 
1495
+ .race-data-panel--with-telemetry {
1496
+ grid-template-columns: clamp(6.5rem, 11vw, 8.7rem) minmax(0, 1fr) minmax(150px, 0.48fr) auto;
1497
+ min-height: 112px;
1498
+ }
1499
+
1500
+ .race-data-telemetry {
1501
+ position: relative;
1502
+ z-index: 1;
1503
+ grid-column: 3;
1504
+ grid-row: 1;
1505
+ align-self: stretch;
1506
+ display: grid;
1507
+ grid-template-rows: auto minmax(0, 1fr);
1508
+ gap: 0.4rem;
1509
+ min-width: 0;
1510
+ padding: 0.85rem 0.65rem;
1511
+ border-left: 1px solid rgba(255, 255, 255, 0.13);
1512
+ }
1513
+
1514
+ .race-data-telemetry__label {
1515
+ color: var(--driver-color, var(--red));
1516
+ font-family: var(--font-mono);
1517
+ font-size: 0.58rem;
1518
+ font-weight: 900;
1519
+ letter-spacing: 0.14em;
1520
+ line-height: 1;
1521
+ text-transform: uppercase;
1522
+ }
1523
+
1524
+ .race-data-telemetry__bars {
1525
+ display: grid;
1526
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1527
+ gap: 0.28rem;
1528
+ min-width: 0;
1529
+ }
1530
+
1531
+ .race-data-sector-bar {
1532
+ min-height: 3.85rem;
1533
+ padding: 0.52rem 0.42rem;
1534
+ }
1535
+
1536
+ .race-data-panel--with-telemetry .race-data-link {
1537
+ grid-column: 4;
1538
+ }
1539
+
1540
+ .race-data-panel.is-radio-mode .race-data-telemetry {
1541
+ display: none;
1542
+ }
1543
+
1286
1544
  .race-data-panel.is-radio-mode {
1287
- grid-template-columns: minmax(280px, 1fr);
1545
+ grid-template-columns: minmax(0, 1fr);
1288
1546
  }
1289
1547
 
1290
1548
  .race-data-panel.is-radio-mode .race-data-copy {
@@ -1336,9 +1594,13 @@
1336
1594
  place-items: center;
1337
1595
  align-self: center;
1338
1596
  min-width: clamp(132px, 13vw, 176px);
1597
+ max-width: calc(100% - 0.85rem);
1339
1598
  min-height: 3.1rem;
1340
1599
  margin-right: 0.85rem;
1341
1600
  padding: 0 1.05rem;
1601
+ overflow: hidden;
1602
+ text-overflow: ellipsis;
1603
+ white-space: nowrap;
1342
1604
  color: #f6f8fb;
1343
1605
  background: color-mix(in srgb, var(--driver-color, var(--red)) 88%, #111318);
1344
1606
  border: 1px solid color-mix(in srgb, var(--driver-color, var(--red)) 72%, #ffffff);
@@ -1358,6 +1620,9 @@
1358
1620
 
1359
1621
  .telemetry-grid dt {
1360
1622
  display: block;
1623
+ min-width: 0;
1624
+ overflow: hidden;
1625
+ text-overflow: ellipsis;
1361
1626
  margin-bottom: 0.22rem;
1362
1627
  color: var(--muted);
1363
1628
  font-family: var(--font-mono);
@@ -1368,6 +1633,10 @@
1368
1633
  }
1369
1634
 
1370
1635
  .telemetry-grid dd {
1636
+ min-width: 0;
1637
+ overflow: hidden;
1638
+ text-overflow: ellipsis;
1639
+ white-space: nowrap;
1371
1640
  margin: 0;
1372
1641
  font-family: var(--font-mono);
1373
1642
  font-size: clamp(0.86rem, 1.6vw, 1.15rem);
@@ -1393,9 +1662,10 @@
1393
1662
  }
1394
1663
 
1395
1664
  .telemetry-grid > div {
1665
+ min-width: 0;
1396
1666
  display: flex;
1397
1667
  justify-content: space-between;
1398
- gap: 1rem;
1668
+ gap: 0.55rem;
1399
1669
  padding: 0.82rem 0.7rem;
1400
1670
  background: var(--surface-panel);
1401
1671
  }
@@ -1597,6 +1867,8 @@
1597
1867
  .telemetry-lap-table,
1598
1868
  .telemetry-sector-table {
1599
1869
  width: 100%;
1870
+ min-width: 0;
1871
+ table-layout: fixed;
1600
1872
  border-collapse: collapse;
1601
1873
  overflow: hidden;
1602
1874
  background: rgba(255, 255, 255, 0.045);
@@ -1617,10 +1889,13 @@
1617
1889
  .telemetry-lap-table td,
1618
1890
  .telemetry-sector-table th,
1619
1891
  .telemetry-sector-table td {
1892
+ overflow: hidden;
1620
1893
  padding: 0.55rem 0.5rem;
1621
1894
  font-size: 0.68rem;
1622
1895
  line-height: 1;
1623
1896
  text-align: right;
1897
+ text-overflow: ellipsis;
1898
+ white-space: nowrap;
1624
1899
  }
1625
1900
 
1626
1901
  .telemetry-lap-table th,
@@ -2135,11 +2410,31 @@
2135
2410
  grid-template-columns: minmax(0, 1fr);
2136
2411
  }
2137
2412
 
2413
+ .race-data-panel--with-telemetry {
2414
+ grid-template-columns: minmax(4.8rem, auto) minmax(0, 1fr);
2415
+ }
2416
+
2138
2417
  .race-data-copy {
2139
2418
  grid-column: 2;
2140
2419
  padding: 0.78rem 0.95rem 0.85rem;
2141
2420
  }
2142
2421
 
2422
+ .race-data-panel--with-telemetry .race-data-copy {
2423
+ grid-column: 2;
2424
+ padding-bottom: 0.35rem;
2425
+ }
2426
+
2427
+ .race-data-telemetry {
2428
+ grid-column: 1 / -1;
2429
+ grid-row: 2;
2430
+ padding: 0 0.95rem 0.75rem;
2431
+ border-left: 0;
2432
+ }
2433
+
2434
+ .race-data-panel--with-telemetry .race-data-link {
2435
+ grid-column: 1 / -1;
2436
+ }
2437
+
2143
2438
  .race-data-panel.is-radio-mode .race-data-copy {
2144
2439
  grid-column: 1;
2145
2440
  padding-left: 0.95rem;
@@ -2158,6 +2453,13 @@
2158
2453
  min-height: 48px;
2159
2454
  }
2160
2455
 
2456
+ .race-data-dismiss {
2457
+ top: 0.38rem;
2458
+ right: 0.42rem;
2459
+ width: 0.95rem;
2460
+ height: 0.95rem;
2461
+ }
2462
+
2161
2463
  .sim-telemetry {
2162
2464
  display: block;
2163
2465
  }