diff --git a/src/app.js b/src/app.js index 3f53a02..796daa7 100644 --- a/src/app.js +++ b/src/app.js @@ -5907,10 +5907,10 @@ function renderOverlayLeaderboard(rows) {
- ${row.predictedRemainingMs !== null ? formatLap(row.predictedRemainingMs) : "-"} + ${formatPredictedLapDelta(row.predictedRemainingMs)}
-
+
@@ -7115,8 +7115,8 @@ function buildLeaderboard(session) { ? bestLapMs : null; const currentLapElapsedMs = lastPassingTs ? Math.max(0, nowTs - lastPassingTs) : 0; - const predictedRemainingMs = predictionBaseMs ? Math.max(0, predictionBaseMs - currentLapElapsedMs) : null; - const predictedProgress = predictionBaseMs ? Math.min(1.25, currentLapElapsedMs / predictionBaseMs) : 0; + const predictedRemainingMs = predictionBaseMs ? predictionBaseMs - currentLapElapsedMs : null; + const predictedProgress = predictionBaseMs ? currentLapElapsedMs / predictionBaseMs : 0; const predictionTone = !predictionBaseMs || predictedProgress <= 0.85 ? "good" @@ -7336,6 +7336,16 @@ function formatLap(ms) { return `${m}:${s}.${t}`; } +function formatPredictedLapDelta(ms) { + if (ms === null || ms === undefined || Number.isNaN(ms)) { + return "-"; + } + if (ms >= 0) { + return formatLap(ms); + } + return `+${formatLap(Math.abs(ms))}`; +} + function formatCountdown(ms) { const total = Math.max(0, Math.floor(ms)); const m = Math.floor(total / 60000) diff --git a/src/styles.css b/src/styles.css index fd27589..61c5c01 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1068,9 +1068,9 @@ select:focus { } .overlay-race-pos .pos-pill { - min-width: 22px; - height: 22px; - font-size: 0.68rem; + min-width: 20px; + height: 20px; + font-size: 0.62rem; } .overlay-shell-dense .pill { @@ -1176,10 +1176,10 @@ select:focus { .overlay-race-row { display: grid; - grid-template-columns: 34px minmax(160px, 1.7fr) repeat(4, minmax(78px, 0.54fr)) minmax(86px, 0.58fr); - gap: 5px; + grid-template-columns: 30px minmax(148px, 1.42fr) repeat(6, minmax(62px, 0.38fr)); + gap: 4px; align-items: center; - padding: 4px 6px; + padding: 4px 5px; border: 1px solid rgba(255, 255, 255, 0.06); border-radius: 8px; background: rgba(255, 255, 255, 0.03); @@ -1210,7 +1210,7 @@ select:focus { .overlay-race-metric label, .overlay-race-best label { color: var(--muted); - font-size: 0.5rem; + font-size: 0.46rem; text-transform: uppercase; letter-spacing: 0.06em; } @@ -1226,13 +1226,15 @@ select:focus { .overlay-prediction { margin-top: 1px; + max-width: 122px; } .overlay-prediction-meta { display: flex; justify-content: space-between; - gap: 6px; + gap: 4px; margin-bottom: 1px; + max-width: 122px; } .overlay-prediction-meta label, @@ -1245,6 +1247,7 @@ select:focus { .overlay-prediction-track { height: 2px; + max-width: 122px; border-radius: 999px; overflow: hidden; background: rgba(255, 255, 255, 0.08); @@ -1265,12 +1268,18 @@ select:focus { .overlay-prediction-late { background: linear-gradient(90deg, #ffd0d0, #e10600); + animation: overlayPredictionLatePulse 1.1s ease-in-out infinite; +} + +@keyframes overlayPredictionLatePulse { + 0%, 100% { opacity: 0.55; } + 50% { opacity: 1; } } .overlay-race-metric strong, .overlay-race-best strong { font-family: Orbitron, sans-serif; - font-size: clamp(1rem, 1.6vw, 1.35rem); + font-size: clamp(0.88rem, 1.2vw, 1.08rem); } .overlay-empty {