Min varvtid (sek)
Max varvtid (sek)
This commit is contained in:
101
src/app.js
101
src/app.js
@@ -207,6 +207,10 @@ const TRANSLATIONS = {
|
|||||||
"events.finals_from_qualifying": "Kval-ranking",
|
"events.finals_from_qualifying": "Kval-ranking",
|
||||||
"events.finals_from_practice": "Practice-ranking",
|
"events.finals_from_practice": "Practice-ranking",
|
||||||
"events.finals_source_hint": "Välj om finalerna ska seedas från practice eller kval.",
|
"events.finals_source_hint": "Välj om finalerna ska seedas från practice eller kval.",
|
||||||
|
"events.min_lap_time": "Min varvtid (sek)",
|
||||||
|
"events.min_lap_time_hint": "Varv snabbare än detta ignoreras som shortcut eller felträff.",
|
||||||
|
"events.max_lap_time": "Max varvtid (sek)",
|
||||||
|
"events.max_lap_time_hint": "Varv långsammare än detta räknas inte som giltigt varv och bryter lap-basen för nästa varv.",
|
||||||
"events.race_driver_scope": "Race i denna klass använder alla förare i vald klass om sessionen inte har egen deltagarlista.",
|
"events.race_driver_scope": "Race i denna klass använder alla förare i vald klass om sessionen inte har egen deltagarlista.",
|
||||||
"events.reserve_bump_slots_hint": "Reserverar tomma platser i högre finaler så bumpade förare kan flyttas in utan att skriva över seedade platser.",
|
"events.reserve_bump_slots_hint": "Reserverar tomma platser i högre finaler så bumpade förare kan flyttas in utan att skriva över seedade platser.",
|
||||||
"events.team_race": "Lagrace",
|
"events.team_race": "Lagrace",
|
||||||
@@ -724,6 +728,10 @@ const TRANSLATIONS = {
|
|||||||
"events.finals_from_qualifying": "Qualifying standings",
|
"events.finals_from_qualifying": "Qualifying standings",
|
||||||
"events.finals_from_practice": "Practice standings",
|
"events.finals_from_practice": "Practice standings",
|
||||||
"events.finals_source_hint": "Choose whether finals should be seeded from practice or qualifying.",
|
"events.finals_source_hint": "Choose whether finals should be seeded from practice or qualifying.",
|
||||||
|
"events.min_lap_time": "Min lap time (sec)",
|
||||||
|
"events.min_lap_time_hint": "Laps faster than this are ignored as shortcuts or false hits.",
|
||||||
|
"events.max_lap_time": "Max lap time (sec)",
|
||||||
|
"events.max_lap_time_hint": "Laps slower than this are not counted as valid laps and reset the lap base for the next lap.",
|
||||||
"events.race_driver_scope": "Race mode uses all drivers in the event class unless a session has its own participant list.",
|
"events.race_driver_scope": "Race mode uses all drivers in the event class unless a session has its own participant list.",
|
||||||
"events.reserve_bump_slots_hint": "Reserve empty slots in higher finals so bumped drivers can be inserted without overwriting seeded spots.",
|
"events.reserve_bump_slots_hint": "Reserve empty slots in higher finals so bumped drivers can be inserted without overwriting seeded spots.",
|
||||||
"events.team_race": "Team Race",
|
"events.team_race": "Team Race",
|
||||||
@@ -1570,6 +1578,8 @@ function normalizeEvent(event) {
|
|||||||
countedFinalLegs: Math.max(1, Number(event?.raceConfig?.countedFinalLegs || 1) || 1),
|
countedFinalLegs: Math.max(1, Number(event?.raceConfig?.countedFinalLegs || 1) || 1),
|
||||||
finalDurationMin: Math.max(1, Number(event?.raceConfig?.finalDurationMin || 5) || 5),
|
finalDurationMin: Math.max(1, Number(event?.raceConfig?.finalDurationMin || 5) || 5),
|
||||||
finalStartMode: normalizeStartMode(event?.raceConfig?.finalStartMode || "position"),
|
finalStartMode: normalizeStartMode(event?.raceConfig?.finalStartMode || "position"),
|
||||||
|
minLapMs: Math.max(0, Number(event?.raceConfig?.minLapMs || 0) || 0),
|
||||||
|
maxLapMs: Math.max(0, Number(event?.raceConfig?.maxLapMs || 60000) || 60000),
|
||||||
bumpCount: Math.max(0, Number(event?.raceConfig?.bumpCount || 0) || 0),
|
bumpCount: Math.max(0, Number(event?.raceConfig?.bumpCount || 0) || 0),
|
||||||
reserveBumpSlots: event?.raceConfig?.reserveBumpSlots !== false,
|
reserveBumpSlots: event?.raceConfig?.reserveBumpSlots !== false,
|
||||||
driverIds: Array.isArray(event?.raceConfig?.driverIds) ? event.raceConfig.driverIds : [],
|
driverIds: Array.isArray(event?.raceConfig?.driverIds) ? event.raceConfig.driverIds : [],
|
||||||
@@ -3118,6 +3128,16 @@ function renderEventManager(eventId) {
|
|||||||
<option value="staggered" ${event.raceConfig.finalStartMode === "staggered" ? "selected" : ""}>${t("events.start_mode_staggered")}</option>
|
<option value="staggered" ${event.raceConfig.finalStartMode === "staggered" ? "selected" : ""}>${t("events.start_mode_staggered")}</option>
|
||||||
</select>`
|
</select>`
|
||||||
)}
|
)}
|
||||||
|
${renderRaceFormatField(
|
||||||
|
"events.min_lap_time",
|
||||||
|
"events.min_lap_time_hint",
|
||||||
|
`<input type="number" min="0" step="0.1" name="minLapSec" value="${((event.raceConfig.minLapMs || 0) / 1000).toFixed(1)}" />`
|
||||||
|
)}
|
||||||
|
${renderRaceFormatField(
|
||||||
|
"events.max_lap_time",
|
||||||
|
"events.max_lap_time_hint",
|
||||||
|
`<input type="number" min="1" step="0.1" name="maxLapSec" value="${((event.raceConfig.maxLapMs || 60000) / 1000).toFixed(1)}" />`
|
||||||
|
)}
|
||||||
${renderRaceFormatField(
|
${renderRaceFormatField(
|
||||||
"events.bump_count",
|
"events.bump_count",
|
||||||
"events.bump_count_hint",
|
"events.bump_count_hint",
|
||||||
@@ -3672,6 +3692,8 @@ function renderEventManager(eventId) {
|
|||||||
countedFinalLegs: Math.max(1, Number(form.get("countedFinalLegs") || 1) || 1),
|
countedFinalLegs: Math.max(1, Number(form.get("countedFinalLegs") || 1) || 1),
|
||||||
finalDurationMin: Math.max(1, Number(form.get("finalDurationMin") || 5) || 5),
|
finalDurationMin: Math.max(1, Number(form.get("finalDurationMin") || 5) || 5),
|
||||||
finalStartMode: normalizeStartMode(String(form.get("finalStartMode") || "position")),
|
finalStartMode: normalizeStartMode(String(form.get("finalStartMode") || "position")),
|
||||||
|
minLapMs: Math.max(0, Math.round((Number(form.get("minLapSec") || 0) || 0) * 1000)),
|
||||||
|
maxLapMs: Math.max(1000, Math.round((Number(form.get("maxLapSec") || 60) || 60) * 1000)),
|
||||||
bumpCount: Math.max(0, Number(form.get("bumpCount") || 0) || 0),
|
bumpCount: Math.max(0, Number(form.get("bumpCount") || 0) || 0),
|
||||||
reserveBumpSlots: form.get("reserveBumpSlots") === "on",
|
reserveBumpSlots: form.get("reserveBumpSlots") === "on",
|
||||||
driverIds: event.raceConfig.driverIds || [],
|
driverIds: event.raceConfig.driverIds || [],
|
||||||
@@ -3950,7 +3972,7 @@ function renderTiming() {
|
|||||||
<article class="timing-session-stat"><span>${t("timing.started")}</span><strong>${active.startedAt ? new Date(active.startedAt).toLocaleTimeString() : "-"}</strong></article>
|
<article class="timing-session-stat"><span>${t("timing.started")}</span><strong>${active.startedAt ? new Date(active.startedAt).toLocaleTimeString() : "-"}</strong></article>
|
||||||
<article class="timing-session-stat"><span>${t("table.start_mode")}</span><strong>${escapeHtml(getStartModeLabel(active.startMode))}</strong></article>
|
<article class="timing-session-stat"><span>${t("table.start_mode")}</span><strong>${escapeHtml(getStartModeLabel(active.startMode))}</strong></article>
|
||||||
<article class="timing-session-stat"><span>${t("timing.seeding_mode")}</span><strong>${active.seedBestLapCount > 0 ? `${active.seedBestLapCount}` : "-"}</strong></article>
|
<article class="timing-session-stat"><span>${t("timing.seeding_mode")}</span><strong>${active.seedBestLapCount > 0 ? `${active.seedBestLapCount}` : "-"}</strong></article>
|
||||||
<article class="timing-session-stat"><span>${t("timing.total_passings")}</span><strong>${result.passings.length}</strong></article>
|
<article class="timing-session-stat"><span>${t("timing.total_passings")}</span><strong>${getVisiblePassings(result).length}</strong></article>
|
||||||
</div>
|
</div>
|
||||||
${
|
${
|
||||||
active.type === "free_practice"
|
active.type === "free_practice"
|
||||||
@@ -4381,7 +4403,7 @@ function renderOverlay() {
|
|||||||
const overlayClock = sessionTiming?.untimed
|
const overlayClock = sessionTiming?.untimed
|
||||||
? formatElapsedClock(sessionTiming?.elapsedMs ?? 0)
|
? formatElapsedClock(sessionTiming?.elapsedMs ?? 0)
|
||||||
: formatCountdown(sessionTiming?.remainingMs ?? 0);
|
: formatCountdown(sessionTiming?.remainingMs ?? 0);
|
||||||
const recent = active && result ? result.passings.slice(-8).reverse() : [];
|
const recent = active && result ? getVisiblePassings(result).slice(-8).reverse() : [];
|
||||||
const event = active ? state.events.find((item) => item.id === active.eventId) : null;
|
const event = active ? state.events.find((item) => item.id === active.eventId) : null;
|
||||||
const branding = resolveEventBranding(event);
|
const branding = resolveEventBranding(event);
|
||||||
const practiceRows = event ? buildPracticeStandings(event) : [];
|
const practiceRows = event ? buildPracticeStandings(event) : [];
|
||||||
@@ -4442,7 +4464,7 @@ function renderOverlay() {
|
|||||||
(passing) => `
|
(passing) => `
|
||||||
<div class="overlay-passing">
|
<div class="overlay-passing">
|
||||||
<strong>${escapeHtml(passing.displayName || passing.teamName || passing.driverName || t("common.unknown_driver"))}</strong>
|
<strong>${escapeHtml(passing.displayName || passing.teamName || passing.driverName || t("common.unknown_driver"))}</strong>
|
||||||
<span>${new Date(passing.timestamp).toLocaleTimeString()}</span>
|
<span>${formatLap(passing.lapMs)}</span>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
@@ -4503,7 +4525,7 @@ function renderOverlay() {
|
|||||||
<strong>${formatLap(fastestRow?.bestLapMs)}</strong>
|
<strong>${formatLap(fastestRow?.bestLapMs)}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="overlay-fastest-driver">${escapeHtml(fastestRow?.displayName || fastestRow?.driverName || "-")}</div>
|
<div class="overlay-fastest-driver">${escapeHtml(fastestRow?.displayName || fastestRow?.driverName || "-")}</div>
|
||||||
<div class="overlay-fastest-meta">${t("table.laps")}: ${topRow?.laps || 0} | ${t("timing.total_passings")}: ${result?.passings.length || 0}</div>
|
<div class="overlay-fastest-meta">${t("table.laps")}: ${topRow?.laps || 0} | ${t("timing.total_passings")}: ${getVisiblePassings(result).length || 0}</div>
|
||||||
</section>
|
</section>
|
||||||
<div class="overlay-leaderboard-card overlay-leaderboard-card-tv overlay-leaderboard-card-dense">
|
<div class="overlay-leaderboard-card overlay-leaderboard-card-tv overlay-leaderboard-card-dense">
|
||||||
${renderOverlayLeaderboard(leaderboard)}
|
${renderOverlayLeaderboard(leaderboard)}
|
||||||
@@ -4563,7 +4585,7 @@ function buildOverlayPanels(active, recent) {
|
|||||||
(passing) => `
|
(passing) => `
|
||||||
<div class="overlay-passing">
|
<div class="overlay-passing">
|
||||||
<strong>${escapeHtml(passing.displayName || passing.teamName || passing.driverName || passing.transponder || t("common.unknown_driver"))}</strong>
|
<strong>${escapeHtml(passing.displayName || passing.teamName || passing.driverName || passing.transponder || t("common.unknown_driver"))}</strong>
|
||||||
<span>${new Date(passing.timestamp).toLocaleTimeString()}</span>
|
<span>${formatLap(passing.lapMs)}</span>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
@@ -4840,7 +4862,7 @@ function renderTeamOverlay(rows, result, sessionTiming) {
|
|||||||
</article>
|
</article>
|
||||||
<article class="overlay-stat-card">
|
<article class="overlay-stat-card">
|
||||||
<span>${t("timing.total_passings")}</span>
|
<span>${t("timing.total_passings")}</span>
|
||||||
<strong>${result?.passings.length || 0}</strong>
|
<strong>${getVisiblePassings(result).length || 0}</strong>
|
||||||
<small>${sessionTiming?.untimed ? t("timing.elapsed") : t("timing.remaining")}</small>
|
<small>${sessionTiming?.untimed ? t("timing.elapsed") : t("timing.remaining")}</small>
|
||||||
</article>
|
</article>
|
||||||
<article class="overlay-stat-card">
|
<article class="overlay-stat-card">
|
||||||
@@ -4868,7 +4890,7 @@ function renderRecentPassings(session) {
|
|||||||
return `<p>${t("timing.no_session_selected")}</p>`;
|
return `<p>${t("timing.no_session_selected")}</p>`;
|
||||||
}
|
}
|
||||||
const result = ensureSessionResult(session.id);
|
const result = ensureSessionResult(session.id);
|
||||||
const items = result.passings.slice(-20).reverse();
|
const items = getVisiblePassings(result).slice(-20).reverse();
|
||||||
if (!items.length) {
|
if (!items.length) {
|
||||||
return `<p>${t("timing.no_passings")}</p>`;
|
return `<p>${t("timing.no_passings")}</p>`;
|
||||||
}
|
}
|
||||||
@@ -5245,6 +5267,25 @@ function getSessionTargetMs(session) {
|
|||||||
return Math.max(1, Number(session?.durationMin || 0)) * 60 * 1000;
|
return Math.max(1, Number(session?.durationMin || 0)) * 60 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSessionLapWindow(session) {
|
||||||
|
const event = state.events.find((item) => item.id === session?.eventId);
|
||||||
|
if (event?.mode !== "race") {
|
||||||
|
return { minLapMs: 0, maxLapMs: Number.POSITIVE_INFINITY };
|
||||||
|
}
|
||||||
|
const minLapMs = Math.max(0, Number(event?.raceConfig?.minLapMs || 0) || 0);
|
||||||
|
const configuredMaxLapMs = Math.max(0, Number(event?.raceConfig?.maxLapMs || 60000) || 60000);
|
||||||
|
const maxLapMs = configuredMaxLapMs > 0 ? Math.max(configuredMaxLapMs, minLapMs || 0) : Number.POSITIVE_INFINITY;
|
||||||
|
return { minLapMs, maxLapMs };
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCountedPassing(passing) {
|
||||||
|
return passing?.validLap !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVisiblePassings(result) {
|
||||||
|
return Array.isArray(result?.passings) ? result.passings.filter((passing) => isCountedPassing(passing)) : [];
|
||||||
|
}
|
||||||
|
|
||||||
function getSessionTiming(session, nowTs = Date.now()) {
|
function getSessionTiming(session, nowTs = Date.now()) {
|
||||||
const targetMs = getSessionTargetMs(session);
|
const targetMs = getSessionTargetMs(session);
|
||||||
const startedAt = Number(session?.startedAt || 0);
|
const startedAt = Number(session?.startedAt || 0);
|
||||||
@@ -5439,13 +5480,15 @@ function processDecoderMessage(msg) {
|
|||||||
|
|
||||||
const baseTs = entry.lastTimestamp || entry.startTimestamp || session.startedAt || timestamp;
|
const baseTs = entry.lastTimestamp || entry.startTimestamp || session.startedAt || timestamp;
|
||||||
const lapMs = Math.max(0, timestamp - baseTs);
|
const lapMs = Math.max(0, timestamp - baseTs);
|
||||||
|
const { minLapMs, maxLapMs } = getSessionLapWindow(session);
|
||||||
entry.laps += 1;
|
let validLap = true;
|
||||||
entry.lastLapMs = lapMs;
|
let invalidReason = "";
|
||||||
entry.lastTimestamp = timestamp;
|
if (minLapMs > 0 && lapMs > 0 && lapMs < minLapMs) {
|
||||||
|
validLap = false;
|
||||||
if (lapMs > 500 && (!entry.bestLapMs || lapMs < entry.bestLapMs)) {
|
invalidReason = "below_min";
|
||||||
entry.bestLapMs = lapMs;
|
} else if (Number.isFinite(maxLapMs) && maxLapMs > 0 && lapMs > maxLapMs) {
|
||||||
|
validLap = false;
|
||||||
|
invalidReason = "above_max";
|
||||||
}
|
}
|
||||||
|
|
||||||
const passing = {
|
const passing = {
|
||||||
@@ -5461,11 +5504,31 @@ function processDecoderMessage(msg) {
|
|||||||
carName: entry.carName,
|
carName: entry.carName,
|
||||||
competitorKey: key,
|
competitorKey: key,
|
||||||
lapMs,
|
lapMs,
|
||||||
|
validLap,
|
||||||
|
invalidReason,
|
||||||
strength: msg.strength,
|
strength: msg.strength,
|
||||||
loopId: String(msg.loop_id || ""),
|
loopId: String(msg.loop_id || ""),
|
||||||
resend: Boolean(msg.resend),
|
resend: Boolean(msg.resend),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!validLap) {
|
||||||
|
result.passings.push(passing);
|
||||||
|
if (invalidReason === "above_max") {
|
||||||
|
entry.lastTimestamp = timestamp;
|
||||||
|
}
|
||||||
|
persistPassingToBackend(session.id, passing);
|
||||||
|
saveState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.laps += 1;
|
||||||
|
entry.lastLapMs = lapMs;
|
||||||
|
entry.lastTimestamp = timestamp;
|
||||||
|
|
||||||
|
if (lapMs > 500 && (!entry.bestLapMs || lapMs < entry.bestLapMs)) {
|
||||||
|
entry.bestLapMs = lapMs;
|
||||||
|
}
|
||||||
|
|
||||||
result.passings.push(passing);
|
result.passings.push(passing);
|
||||||
persistPassingToBackend(session.id, passing);
|
persistPassingToBackend(session.id, passing);
|
||||||
pushOverlayEvent("passing", `${entry.displayName || entry.driverName} • ${formatLap(entry.lastLapMs)}`);
|
pushOverlayEvent("passing", `${entry.displayName || entry.driverName} • ${formatLap(entry.lastLapMs)}`);
|
||||||
@@ -5887,10 +5950,13 @@ function getCompetitorElapsedMs(session, row) {
|
|||||||
return Math.max(0, row.lastTimestamp - startTs);
|
return Math.max(0, row.lastTimestamp - startTs);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCompetitorPassings(session, row) {
|
function getCompetitorPassings(session, row, options = {}) {
|
||||||
const result = ensureSessionResult(session.id);
|
const result = ensureSessionResult(session.id);
|
||||||
return result.passings
|
return result.passings
|
||||||
.filter((passing) => {
|
.filter((passing) => {
|
||||||
|
if (!options.includeInvalid && !isCountedPassing(passing)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (passing.competitorKey) {
|
if (passing.competitorKey) {
|
||||||
return passing.competitorKey === row.key;
|
return passing.competitorKey === row.key;
|
||||||
}
|
}
|
||||||
@@ -6121,13 +6187,16 @@ function buildTeamStintLog(session, row) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { maxLapMs } = getSessionLapWindow(session);
|
||||||
|
const stintGapMs = Number.isFinite(maxLapMs) ? maxLapMs : Number.POSITIVE_INFINITY;
|
||||||
const stints = [];
|
const stints = [];
|
||||||
let current = null;
|
let current = null;
|
||||||
|
|
||||||
passings.forEach((passing) => {
|
passings.forEach((passing) => {
|
||||||
const memberLabel = formatTeamActiveMemberLabel(passing);
|
const memberLabel = formatTeamActiveMemberLabel(passing);
|
||||||
const memberKey = `${passing.driverId || passing.driverName || "-"}|${passing.carId || passing.carName || "-"}`;
|
const memberKey = `${passing.driverId || passing.driverName || "-"}|${passing.carId || passing.carName || "-"}`;
|
||||||
if (!current || current.memberKey !== memberKey) {
|
const gapBreak = current && Number.isFinite(stintGapMs) && Math.max(0, passing.timestamp - current.endTs) > stintGapMs;
|
||||||
|
if (!current || current.memberKey !== memberKey || gapBreak) {
|
||||||
current = {
|
current = {
|
||||||
memberKey,
|
memberKey,
|
||||||
memberLabel,
|
memberLabel,
|
||||||
|
|||||||
@@ -861,8 +861,8 @@ select:focus {
|
|||||||
|
|
||||||
.overlay-board {
|
.overlay-board {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1.7fr) minmax(260px, 0.55fr);
|
grid-template-columns: minmax(0, 1.85fr) minmax(210px, 0.38fr);
|
||||||
gap: 12px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay-board-tv {
|
.overlay-board-tv {
|
||||||
@@ -1105,27 +1105,28 @@ select:focus {
|
|||||||
|
|
||||||
.overlay-side {
|
.overlay-side {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 10px;
|
gap: 8px;
|
||||||
|
font-size: 0.84rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay-side-card {
|
.overlay-side-card {
|
||||||
padding: 10px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay-rotating-card {
|
.overlay-rotating-card {
|
||||||
min-height: 240px;
|
min-height: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay-side-card h3 {
|
.overlay-side-card h3 {
|
||||||
margin: 0 0 6px;
|
margin: 0 0 4px;
|
||||||
font-size: 0.95rem;
|
font-size: 0.86rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay-passing {
|
.overlay-passing {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 8px;
|
gap: 6px;
|
||||||
padding: 5px 0;
|
padding: 4px 0;
|
||||||
border-bottom: 1px solid var(--line);
|
border-bottom: 1px solid var(--line);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1133,6 +1134,23 @@ select:focus {
|
|||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overlay-side-card .overlay-passing strong {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-side-card .overlay-passing span {
|
||||||
|
font-family: Orbitron, sans-serif;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
color: var(--text);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-side-card .pill {
|
||||||
|
padding: 3px 7px;
|
||||||
|
font-size: 0.58rem;
|
||||||
|
}
|
||||||
|
|
||||||
.overlay-race-list {
|
.overlay-race-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
|||||||
Reference in New Issue
Block a user