Files
box-box/documentations/refactor/screens/race-hub.html

848 lines
38 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>box-box — Race Hub · Monaco GP 2025</title>
<link rel="stylesheet" href="styles.css">
<style>
/* ── Race Hub sub-header ── */
.rh-header {
display: flex;
align-items: center;
gap: var(--s4);
padding: var(--s3) var(--s5);
background: var(--c-surface);
border-bottom: 1px solid var(--c-border);
flex-wrap: wrap;
flex-shrink: 0;
}
.rh-breadcrumb {
display: flex;
align-items: center;
gap: var(--s2);
font-size: 12px;
}
.rh-breadcrumb a { color: var(--c-text-3); }
.rh-breadcrumb a:hover { color: var(--c-text-2); }
.rh-breadcrumb .sep { color: var(--c-text-3); }
.rh-breadcrumb .cur { font-weight: 600; color: var(--c-text); }
.rh-session-btns {
display: flex;
gap: 2px;
margin-left: auto;
}
.rh-session-btn {
padding: 3px 8px;
background: none;
border: 1px solid var(--c-border);
border-radius: 2px;
font-size: 10px;
font-weight: 600;
letter-spacing: 0.05em;
color: var(--c-text-3);
text-transform: uppercase;
}
.rh-session-btn.active {
background: var(--c-surface-2);
border-color: var(--c-border-2);
color: var(--c-text);
}
/* ── Section tabs (in rh-main) ── */
.rh-section-tabs {
display: flex;
gap: 2px;
padding: var(--s3) var(--s5);
border-bottom: 1px solid var(--c-border);
overflow-x: auto;
flex-shrink: 0;
}
/* ── Main content area ── */
.rh-content {
padding: var(--s5);
display: flex;
flex-direction: column;
gap: var(--sec-gap);
max-width: 860px;
}
/* ── Classification ── */
.result-pos { font-family: var(--f-mono); font-size: 14px; font-weight: 700; text-align: center; width: 28px; }
/* ── Strategy ── */
#strategy-chart { width: 100%; min-height: 320px; }
.compound-legend {
display: flex;
gap: var(--s4);
margin-top: var(--s3);
flex-wrap: wrap;
}
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--c-text-3); }
.legend-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
/* ── Position Evolution ── */
#position-chart { width: 100%; }
/* ── Race Control ── */
.rc-event {
display: grid;
grid-template-columns: 52px 90px 1fr;
gap: var(--s3);
padding: 7px 0;
border-bottom: 1px solid var(--c-border);
font-size: 11px;
align-items: baseline;
}
.rc-event:last-child { border-bottom: none; }
.rc-event-lap { font-family: var(--f-mono); font-weight: 600; color: var(--c-text-3); }
.rc-event-type { font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
.rc-event-msg { color: var(--c-text-2); line-height: 1.4; }
.rc-event.sc .rc-event-type { color: var(--c-yellow); }
.rc-event.vsc .rc-event-type { color: var(--c-yellow); }
.rc-event.drs .rc-event-type { color: var(--c-green); }
.rc-event.flag .rc-event-type { color: var(--c-red); }
.rc-event.fl .rc-event-type { color: var(--c-purple); }
.rc-event.info .rc-event-type { color: var(--c-text-3); }
/* ── Weather ── */
.wx-row {
display: grid;
grid-template-columns: 50px repeat(6, 1fr);
gap: var(--s3);
padding: 5px 0;
border-bottom: 1px solid var(--c-border);
font-size: 11px;
font-family: var(--f-mono);
align-items: center;
}
.wx-row:last-child { border-bottom: none; }
.wx-hdr {
font-family: var(--f-ui);
font-size: 10px;
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--c-text-3);
}
/* ── Dataset ── */
.ds-grid-main {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 1px;
border: 1px solid var(--c-border);
margin-bottom: var(--s4);
}
.ds-cell {
display: flex;
align-items: center;
gap: var(--s2);
padding: var(--s3) var(--s4);
background: var(--c-surface);
font-size: 11px;
}
.ds-cell-name { flex: 1; color: var(--c-text-2); }
.ds-cell-time { font-family: var(--f-mono); font-size: 10px; color: var(--c-text-3); }
/* ── Aside: condensed RC ── */
.rc-condensed { display: flex; flex-direction: column; }
.rc-cond-row {
display: grid;
grid-template-columns: 44px 1fr;
gap: var(--s2);
padding: 5px 0;
border-bottom: 1px solid var(--c-border);
font-size: 11px;
}
.rc-cond-row:last-child { border-bottom: none; }
.rc-cond-lap { font-family: var(--f-mono); color: var(--c-text-3); font-size: 10px; }
.rc-cond-msg { color: var(--c-text-2); line-height: 1.4; }
.rc-cond-row.sc .rc-cond-msg { color: var(--c-yellow); }
.rc-cond-row.vsc .rc-cond-msg { color: var(--c-yellow); }
.rc-cond-row.drs .rc-cond-msg { color: var(--c-green); }
.rc-cond-row.fl .rc-cond-msg { color: var(--c-purple); }
.rc-cond-row.flag .rc-cond-msg { color: var(--c-red); }
/* ── Aside: dataset mini ── */
.ds-mini { display: flex; flex-direction: column; gap: 3px; }
.ds-mini-row {
display: flex;
align-items: center;
gap: var(--s2);
font-size: 10px;
font-family: var(--f-mono);
color: var(--c-text-3);
}
.ds-mini-row .dot { flex-shrink: 0; }
</style>
</head>
<body>
<nav class="app-nav">
<a href="index.html" class="nav-logo">box<em>-</em>box</a>
<div class="nav-links">
<a href="command-center.html">Command Center</a>
<a href="live-timing.html">Live</a>
<a href="race-hub.html" class="active">Race Hub</a>
<a href="data-library.html">Data Library</a>
</div>
<div class="nav-right">
<div class="density-toggle">
<button class="active" onclick="setDensity('default',this)">D</button>
<button onclick="setDensity('compact',this)">C</button>
</div>
</div>
</nav>
<!-- Sub-header -->
<div class="rh-header">
<div class="rh-breadcrumb">
<a href="command-center.html">2025</a>
<span class="sep"></span>
<a href="#">Monaco GP</a>
<span class="sep"></span>
<span class="cur">Race</span>
</div>
<div style="display:flex;align-items:center;gap:var(--s3);font-size:12px">
<span class="t3 mono">78 Laps · 260.286 km · 25 May 2025</span>
<span class="badge local">Local data</span>
</div>
<div class="rh-session-btns">
<button class="rh-session-btn">FP1</button>
<button class="rh-session-btn">FP2</button>
<button class="rh-session-btn">FP3</button>
<button class="rh-session-btn">Qual</button>
<button class="rh-session-btn active">Race</button>
</div>
</div>
<!-- ── 2-column body ── -->
<div class="rh-body">
<!-- Left: tabbed content -->
<div style="display:flex;flex-direction:column;overflow:hidden">
<!-- Section tabs -->
<div class="rh-section-tabs">
<button class="tab-btn active" onclick="showTab('classification',this)">Classification</button>
<button class="tab-btn" onclick="showTab('strategy',this)">Strategy</button>
<button class="tab-btn" onclick="showTab('positions',this)">Positions</button>
<button class="tab-btn" onclick="showTab('racecontrol',this)">Race Control</button>
<button class="tab-btn" onclick="showTab('weather',this)">Weather</button>
<button class="tab-btn" onclick="showTab('dataset',this)">Dataset</button>
</div>
<!-- Tab panels -->
<div class="rh-content">
<!-- CLASSIFICATION -->
<div id="tab-classification" class="tab-panel active">
<div class="sec-header">
<span class="sec-title">Final Classification</span>
<span class="sec-meta">78 laps · 1:32:14.456</span>
</div>
<div class="scroll-x">
<table class="data-table" style="min-width:620px">
<thead>
<tr>
<th class="center" style="width:28px">P</th>
<th>Driver</th>
<th>Team</th>
<th class="center">Grid</th>
<th class="center">Δ</th>
<th class="num">Time / Gap</th>
<th class="num">Fastest Lap</th>
<th class="num">Pts</th>
</tr>
</thead>
<tbody>
<tr>
<td class="center"><span class="pos-p1">1</span></td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-fer)"></div>
<span class="drv-code">LEC</span><span class="drv-num">16</span>
</div>
</td>
<td class="t2">Ferrari</td>
<td class="center t3 mono">3</td>
<td class="center"><span class="pos-gain">↑2</span></td>
<td class="num mono">1:32:14.456</td>
<td class="num mono t3">1:14.892</td>
<td class="num" style="font-weight:700">25</td>
</tr>
<tr>
<td class="center"><span class="pos-p2">2</span></td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-rb)"></div>
<span class="drv-code">VER</span><span class="drv-num">1</span>
</div>
</td>
<td class="t2">Red Bull</td>
<td class="center t3 mono">1</td>
<td class="center"><span class="pos-loss">↓1</span></td>
<td class="num mono t2">+3.456</td>
<td class="num mono t3">1:15.023</td>
<td class="num" style="font-weight:700">18</td>
</tr>
<tr>
<td class="center"><span class="pos-p3">3</span></td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-mcl)"></div>
<span class="drv-code">NOR</span><span class="drv-num">4</span>
</div>
</td>
<td class="t2">McLaren</td>
<td class="center t3 mono">4</td>
<td class="center"><span class="pos-gain">↑1</span></td>
<td class="num mono t2">+8.123</td>
<td class="num mono" style="color:var(--c-purple)">1:14.756 ●</td>
<td class="num" style="font-weight:700">15</td>
</tr>
<tr>
<td class="center t3 mono">4</td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-mcl)"></div>
<span class="drv-code">PIA</span><span class="drv-num">81</span>
</div>
</td>
<td class="t2">McLaren</td>
<td class="center t3 mono">6</td>
<td class="center"><span class="pos-gain">↑2</span></td>
<td class="num mono t2">+12.345</td>
<td class="num mono t3">1:15.234</td>
<td class="num t2">12</td>
</tr>
<tr>
<td class="center t3 mono">5</td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-mer)"></div>
<span class="drv-code">RUS</span><span class="drv-num">63</span>
</div>
</td>
<td class="t2">Mercedes</td>
<td class="center t3 mono">2</td>
<td class="center"><span class="pos-loss">↓3</span></td>
<td class="num mono t2">+15.678</td>
<td class="num mono t3">1:15.456</td>
<td class="num t2">10</td>
</tr>
<tr>
<td class="center t3 mono">6</td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-fer)"></div>
<span class="drv-code">HAM</span><span class="drv-num">44</span>
</div>
</td>
<td class="t2">Ferrari</td>
<td class="center t3 mono">5</td>
<td class="center"><span class="pos-loss">↓1</span></td>
<td class="num mono t2">+21.234</td>
<td class="num mono t3">1:15.890</td>
<td class="num t2">8</td>
</tr>
<tr>
<td class="center t3 mono">7</td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-am)"></div>
<span class="drv-code">ALO</span><span class="drv-num">14</span>
</div>
</td>
<td class="t2">Aston Martin</td>
<td class="center t3 mono">8</td>
<td class="center"><span class="pos-gain">↑1</span></td>
<td class="num mono t2">+28.456</td>
<td class="num mono t3">1:16.234</td>
<td class="num t2">6</td>
</tr>
<tr>
<td class="center t3 mono">8</td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-wil)"></div>
<span class="drv-code">SAI</span><span class="drv-num">55</span>
</div>
</td>
<td class="t2">Williams</td>
<td class="center t3 mono">7</td>
<td class="center"><span class="pos-loss">↓1</span></td>
<td class="num mono t2">+35.789</td>
<td class="num mono t3">1:16.567</td>
<td class="num t2">4</td>
</tr>
<tr>
<td class="center t3 mono">9</td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-alp)"></div>
<span class="drv-code t3">GAS</span><span class="drv-num">10</span>
</div>
</td>
<td class="t3">Alpine</td>
<td class="center t3 mono">9</td>
<td class="center"><span class="pos-same"></span></td>
<td class="num mono t3">+42.123</td>
<td class="num mono t3">1:16.890</td>
<td class="num t3">2</td>
</tr>
<tr>
<td class="center t3 mono">10</td>
<td>
<div class="drv-cell">
<div class="drv-bar" style="background:var(--t-haas)"></div>
<span class="drv-code t3">OCO</span><span class="drv-num">31</span>
</div>
</td>
<td class="t3">Haas</td>
<td class="center t3 mono">10</td>
<td class="center"><span class="pos-same"></span></td>
<td class="num mono t3">+48.456</td>
<td class="num mono t3">1:17.012</td>
<td class="num t3">1</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- STRATEGY -->
<div id="tab-strategy" class="tab-panel">
<div class="sec-header">
<span class="sec-title">Tyre Strategy</span>
<span class="sec-meta">78 laps · SC L2326 · VSC L5860</span>
</div>
<div id="strategy-chart"></div>
<div class="compound-legend">
<div class="legend-item"><div class="legend-dot" style="background:var(--tyre-s)"></div>Soft</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--tyre-m)"></div>Medium</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--tyre-h)"></div>Hard</div>
<div class="legend-item" style="margin-left:var(--s4)">
<div style="width:14px;height:2px;background:rgba(255,214,0,0.45);border-radius:1px"></div>
<span>SC / VSC period</span>
</div>
</div>
</div>
<!-- POSITIONS -->
<div id="tab-positions" class="tab-panel">
<div class="sec-header">
<span class="sec-title">Position Evolution</span>
<span class="sec-meta">Top 6 · SC L2326 · VSC L5860</span>
</div>
<div id="position-chart"></div>
<div class="compound-legend" style="margin-top:var(--s3)">
<div class="legend-item"><div class="legend-dot" style="background:var(--t-fer)"></div>LEC</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--t-rb)"></div>VER</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--t-mcl)"></div>NOR</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--t-mcl);opacity:.55"></div>PIA</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--t-mer)"></div>RUS</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--t-mer);opacity:.55"></div>HAM</div>
</div>
</div>
<!-- RACE CONTROL -->
<div id="tab-racecontrol" class="tab-panel">
<div class="sec-header">
<span class="sec-title">Race Control</span>
<span class="sec-meta">14 messages</span>
</div>
<div>
<div class="rc-event info">
<span class="rc-event-lap">L1</span>
<span class="rc-event-type">Start</span>
<span class="rc-event-msg">RACE START — Track Clear</span>
</div>
<div class="rc-event drs">
<span class="rc-event-lap">L3</span>
<span class="rc-event-type">DRS</span>
<span class="rc-event-msg">DRS ENABLED</span>
</div>
<div class="rc-event info">
<span class="rc-event-lap">L18</span>
<span class="rc-event-type">Incident</span>
<span class="rc-event-msg">ALB/STR at T10 under investigation</span>
</div>
<div class="rc-event sc">
<span class="rc-event-lap">L23</span>
<span class="rc-event-type">Safety Car</span>
<span class="rc-event-msg">SAFETY CAR DEPLOYED — Incident T10 (ALB retirement)</span>
</div>
<div class="rc-event sc">
<span class="rc-event-lap">L26</span>
<span class="rc-event-type">Safety Car</span>
<span class="rc-event-msg">SAFETY CAR IN THIS LAP</span>
</div>
<div class="rc-event drs">
<span class="rc-event-lap">L27</span>
<span class="rc-event-type">DRS</span>
<span class="rc-event-msg">DRS ENABLED — Lap 27</span>
</div>
<div class="rc-event info">
<span class="rc-event-lap">L35</span>
<span class="rc-event-type">Penalty</span>
<span class="rc-event-msg">5-SECOND PENALTY — RUS · Unsafe release pit lane</span>
</div>
<div class="rc-event fl">
<span class="rc-event-lap">L38</span>
<span class="rc-event-type">Fastest Lap</span>
<span class="rc-event-msg">NOR · 1:14.756</span>
</div>
<div class="rc-event vsc">
<span class="rc-event-lap">L58</span>
<span class="rc-event-type">VSC</span>
<span class="rc-event-msg">VIRTUAL SAFETY CAR DEPLOYED — Debris T6</span>
</div>
<div class="rc-event vsc">
<span class="rc-event-lap">L60</span>
<span class="rc-event-type">VSC</span>
<span class="rc-event-msg">VIRTUAL SAFETY CAR ENDING</span>
</div>
<div class="rc-event drs">
<span class="rc-event-lap">L61</span>
<span class="rc-event-type">DRS</span>
<span class="rc-event-msg">DRS ENABLED — Lap 61</span>
</div>
<div class="rc-event flag">
<span class="rc-event-lap">L78</span>
<span class="rc-event-type">Finish</span>
<span class="rc-event-msg">CHEQUERED FLAG — Race complete</span>
</div>
</div>
</div>
<!-- WEATHER -->
<div id="tab-weather" class="tab-panel">
<div class="sec-header">
<span class="sec-title">Weather</span>
<span class="sec-meta">Race · sampled every 5 laps · highlighted = SC/VSC</span>
</div>
<div class="scroll-x">
<div class="wx-row"><span class="wx-hdr">Lap</span><span class="wx-hdr">Air °C</span><span class="wx-hdr">Track °C</span><span class="wx-hdr">Humid %</span><span class="wx-hdr">Wind km/h</span><span class="wx-hdr">Dir</span><span class="wx-hdr">Rain</span></div>
<div class="wx-row"><span class="t3">1</span><span>22.4</span><span>32.1</span><span>65</span><span>6</span><span class="t3">NW</span><span class="t-green">0%</span></div>
<div class="wx-row"><span class="t3">10</span><span>23.1</span><span>34.2</span><span>63</span><span>7</span><span class="t3">NW</span><span class="t-green">0%</span></div>
<div class="wx-row"><span class="t3">20</span><span>23.8</span><span>35.6</span><span>62</span><span>6</span><span class="t3">N</span><span class="t-green">1%</span></div>
<div class="wx-row" style="background:rgba(255,214,0,0.05)"><span class="t-yellow">23</span><span>24.0</span><span>36.0</span><span>62</span><span>7</span><span class="t3">N</span><span class="t-green">1%</span></div>
<div class="wx-row"><span class="t3">30</span><span>24.3</span><span>36.8</span><span>61</span><span>8</span><span class="t3">NW</span><span class="t-green">2%</span></div>
<div class="wx-row"><span class="t3">40</span><span>24.9</span><span>37.4</span><span>60</span><span>8</span><span class="t3">NW</span><span class="t-green">2%</span></div>
<div class="wx-row"><span class="t3">50</span><span>25.2</span><span>38.1</span><span>59</span><span>9</span><span class="t3">W</span><span class="t-green">3%</span></div>
<div class="wx-row" style="background:rgba(255,214,0,0.05)"><span class="t-yellow">58</span><span>25.5</span><span>38.3</span><span>59</span><span>8</span><span class="t3">W</span><span class="t-green">3%</span></div>
<div class="wx-row"><span class="t3">70</span><span>25.8</span><span>38.6</span><span>58</span><span>7</span><span class="t3">W</span><span class="t-green">4%</span></div>
<div class="wx-row"><span class="t3">78</span><span>26.1</span><span>38.8</span><span>57</span><span>7</span><span class="t3">NW</span><span class="t-green">4%</span></div>
</div>
</div>
<!-- DATASET -->
<div id="tab-dataset" class="tab-panel">
<div class="sec-header">
<span class="sec-title">Dataset Status</span>
<span class="sec-meta">session_key 9158 · Monaco GP Race</span>
</div>
<div class="ds-grid-main">
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">session_results</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">starting_grid</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">laps</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">stints</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">pit_stops</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">positions</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">race_control</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">weather</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">overtakes</span><span class="ds-cell-time">3h ago</span></div>
<div class="ds-cell"><span class="dot local"></span><span class="ds-cell-name">track_outline</span><span class="ds-cell-time">cached</span></div>
<div class="ds-cell"><span class="dot missing"></span><span class="ds-cell-name">car_data_samples</span><span class="ds-cell-time t3">not ingested</span></div>
<div class="ds-cell"><span class="dot missing"></span><span class="ds-cell-name">location_samples</span><span class="ds-cell-time t3">not ingested</span></div>
<div class="ds-cell"><span class="dot missing"></span><span class="ds-cell-name">team_radio</span><span class="ds-cell-time t3">not ingested</span></div>
</div>
<div class="cli-block">
<div class="comment"># Ingest telemetry (high-volume, explicit only)</div>
<div class="cmd">box-box --ingest-session 9158 --datasets car_data,location</div>
<br>
<div class="comment"># Refresh all datasets for this session</div>
<div class="cmd">box-box --ingest-session 9158 --refresh</div>
</div>
</div>
</div><!-- /rh-content -->
</div><!-- /rh-main -->
<!-- ── Persistent right aside ── -->
<aside class="rh-aside">
<!-- Podium -->
<div>
<div class="sec-header">
<span class="sec-title">Podium</span>
</div>
<div class="podium-list">
<div class="podium-item">
<span class="podium-p pos-p1">P1</span>
<div class="drv-cell" style="gap:var(--s2)">
<div class="drv-bar" style="background:var(--t-fer);height:16px"></div>
<span class="drv-code" style="font-size:13px">LEC</span>
</div>
<span class="podium-gap-val">1:32:14.456</span>
</div>
<div class="podium-item">
<span class="podium-p pos-p2">P2</span>
<div class="drv-cell" style="gap:var(--s2)">
<div class="drv-bar" style="background:var(--t-rb);height:16px"></div>
<span class="drv-code" style="font-size:13px">VER</span>
</div>
<span class="podium-gap-val">+3.456</span>
</div>
<div class="podium-item">
<span class="podium-p pos-p3">P3</span>
<div class="drv-cell" style="gap:var(--s2)">
<div class="drv-bar" style="background:var(--t-mcl);height:16px"></div>
<span class="drv-code" style="font-size:13px">NOR</span>
</div>
<span class="podium-gap-val">+8.123</span>
</div>
</div>
</div>
<!-- Race Stats -->
<div>
<div class="sec-header">
<span class="sec-title">Race Stats</span>
</div>
<div>
<div class="summary-stat-row">
<span class="sstat-label">Fastest Lap</span>
<span class="sstat-val" style="color:var(--c-purple)">NOR 1:14.756 L38</span>
</div>
<div class="summary-stat-row">
<span class="sstat-label">Pole Position</span>
<span class="sstat-val">VER</span>
</div>
<div class="summary-stat-row">
<span class="sstat-label">Safety Car</span>
<span class="sstat-val t-yellow">L2326 (4 laps)</span>
</div>
<div class="summary-stat-row">
<span class="sstat-label">VSC</span>
<span class="sstat-val t-yellow">L5860 (3 laps)</span>
</div>
<div class="summary-stat-row">
<span class="sstat-label">Total Pit Stops</span>
<span class="sstat-val">22</span>
</div>
<div class="summary-stat-row">
<span class="sstat-label">DNF</span>
<span class="sstat-val">ALB (T10 crash)</span>
</div>
<div class="summary-stat-row">
<span class="sstat-label">Penalties</span>
<span class="sstat-val">RUS +5s</span>
</div>
</div>
</div>
<!-- Condensed RC -->
<div>
<div class="sec-header">
<span class="sec-title">Key Events</span>
</div>
<div class="rc-condensed">
<div class="rc-cond-row flag">
<span class="rc-cond-lap">L78</span>
<span class="rc-cond-msg">Chequered flag</span>
</div>
<div class="rc-cond-row drs">
<span class="rc-cond-lap">L61</span>
<span class="rc-cond-msg">DRS enabled</span>
</div>
<div class="rc-cond-row vsc">
<span class="rc-cond-lap">L5860</span>
<span class="rc-cond-msg">VSC — debris T6</span>
</div>
<div class="rc-cond-row fl">
<span class="rc-cond-lap">L38</span>
<span class="rc-cond-msg">FL: NOR 1:14.756</span>
</div>
<div class="rc-cond-row drs">
<span class="rc-cond-lap">L27</span>
<span class="rc-cond-msg">DRS enabled</span>
</div>
<div class="rc-cond-row sc">
<span class="rc-cond-lap">L2326</span>
<span class="rc-cond-msg">SC — ALB retirement T10</span>
</div>
</div>
</div>
<!-- Dataset mini -->
<div>
<div class="sec-header">
<span class="sec-title">Data</span>
<span class="t3" style="font-size:10px;margin-left:auto">10/13 datasets</span>
</div>
<div class="ds-mini">
<div class="ds-mini-row"><span class="dot local"></span>session_results · laps · stints</div>
<div class="ds-mini-row"><span class="dot local"></span>pit_stops · positions · race_control</div>
<div class="ds-mini-row"><span class="dot local"></span>weather · overtakes · track_outline</div>
<div class="ds-mini-row"><span class="dot missing"></span>car_data · location · team_radio</div>
</div>
</div>
</aside><!-- /rh-aside -->
</div><!-- /rh-body -->
<script>
function setDensity(mode, btn) {
document.querySelectorAll('.density-toggle button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.documentElement.classList.toggle('compact', mode === 'compact');
renderCharts();
}
function showTab(id, btn) {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
btn.classList.add('active');
document.getElementById('tab-' + id).classList.add('active');
if (id === 'strategy' || id === 'positions') renderCharts();
}
/* ── Strategy Chart ── */
function renderStrategyChart() {
const el = document.getElementById('strategy-chart');
if (!el) return;
const TOTAL = 78;
const compounds = {
S: { fill: '#e8002d', text: '#fff' },
M: { fill: '#c8b400', text: '#000' },
H: { fill: '#909090', text: '#fff' }
};
const drivers = [
{ code: 'LEC', color: '#e8002d', stints: [{c:'S',s:1,e:20},{c:'M',s:21,e:55},{c:'H',s:56,e:78}] },
{ code: 'VER', color: '#3671c6', stints: [{c:'M',s:1,e:28},{c:'H',s:29,e:60},{c:'M',s:61,e:78}] },
{ code: 'NOR', color: '#ff8000', stints: [{c:'S',s:1,e:18},{c:'M',s:19,e:52},{c:'H',s:53,e:78}] },
{ code: 'PIA', color: '#cc6600', stints: [{c:'S',s:1,e:22},{c:'M',s:23,e:50},{c:'H',s:51,e:78}] },
{ code: 'RUS', color: '#27f4d2', stints: [{c:'M',s:1,e:30},{c:'H',s:31,e:62},{c:'S',s:63,e:78}] },
{ code: 'HAM', color: '#1abfa8', stints: [{c:'S',s:1,e:15},{c:'M',s:16,e:55},{c:'H',s:56,e:78}] },
{ code: 'ALO', color: '#229971', stints: [{c:'M',s:1,e:35},{c:'H',s:36,e:78}] },
{ code: 'SAI', color: '#64c4ff', stints: [{c:'S',s:1,e:20},{c:'M',s:21,e:58},{c:'S',s:59,e:78}] },
{ code: 'GAS', color: '#cc6699', stints: [{c:'M',s:1,e:28},{c:'H',s:29,e:65},{c:'S',s:66,e:78}] },
{ code: 'OCO', color: '#909090', stints: [{c:'S',s:1,e:20},{c:'M',s:21,e:55},{c:'H',s:56,e:78}] },
];
const ROW_H = 26, ROW_GAP = 7, LBL = 48, PAD = 8;
const W = el.clientWidth || 720;
const CHART_W = W - LBL - PAD;
const H = drivers.length * (ROW_H + ROW_GAP) + 24;
const lx = l => LBL + ((l - 1) / TOTAL) * CHART_W;
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${W} ${H}" width="${W}" height="${H}">`;
svg += `<rect x="${lx(23)}" y="0" width="${lx(27)-lx(23)}" height="${drivers.length*(ROW_H+ROW_GAP)}" fill="rgba(255,214,0,0.07)"/>`;
svg += `<rect x="${lx(58)}" y="0" width="${lx(61)-lx(58)}" height="${drivers.length*(ROW_H+ROW_GAP)}" fill="rgba(255,214,0,0.05)"/>`;
[1,10,20,30,40,50,60,70,78].forEach(l => {
svg += `<text x="${lx(l)}" y="${H-4}" text-anchor="middle" font-size="9" fill="#4a4a4a" font-family="monospace">L${l}</text>`;
});
drivers.forEach((d, i) => {
const y = i * (ROW_H + ROW_GAP);
svg += `<text x="${LBL-5}" y="${y+ROW_H/2+4}" text-anchor="end" font-size="11" font-weight="700" fill="${d.color}" font-family="monospace">${d.code}</text>`;
d.stints.forEach(st => {
const x1 = lx(st.s), x2 = lx(st.e+1), w = x2 - x1 - 1;
const laps = st.e - st.s + 1, c = compounds[st.c];
svg += `<rect x="${x1}" y="${y}" width="${w}" height="${ROW_H}" fill="${c.fill}" rx="1"/>`;
if (w > 28) svg += `<text x="${x1+w/2}" y="${y+ROW_H/2+4}" text-anchor="middle" font-size="10" font-weight="700" fill="${c.text}" font-family="monospace">${st.c} ${laps}</text>`;
else if (w > 10) svg += `<text x="${x1+w/2}" y="${y+ROW_H/2+4}" text-anchor="middle" font-size="9" font-weight="700" fill="${c.text}" font-family="monospace">${st.c}</text>`;
});
});
svg += '</svg>';
el.innerHTML = svg;
}
/* ── Position Evolution ── */
function renderPositionChart() {
const el = document.getElementById('position-chart');
if (!el) return;
const W = el.clientWidth || 720, H = 200;
const PAD = { t: 12, r: 40, b: 28, l: 28 };
const CW = W - PAD.l - PAD.r, CH = H - PAD.t - PAD.b;
const LAPS = 78, POSITIONS = 8;
const xp = l => PAD.l + (l / LAPS) * CW;
const yp = p => PAD.t + ((p - 1) / (POSITIONS - 1)) * CH;
const drivers = [
{ code: 'LEC', color: '#e8002d', dash: false, pts: [{l:0,p:3},{l:2,p:1},{l:78,p:1}] },
{ code: 'VER', color: '#3671c6', dash: false, pts: [{l:0,p:1},{l:2,p:2},{l:78,p:2}] },
{ code: 'NOR', color: '#ff8000', dash: false, pts: [{l:0,p:4},{l:6,p:3},{l:78,p:3}] },
{ code: 'PIA', color: '#ff8000', dash: true, pts: [{l:0,p:6},{l:10,p:4},{l:78,p:4}] },
{ code: 'RUS', color: '#27f4d2', dash: false, pts: [{l:0,p:2},{l:2,p:5},{l:78,p:5}] },
{ code: 'HAM', color: '#27f4d2', dash: true, pts: [{l:0,p:5},{l:78,p:6}] },
];
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${W} ${H}" width="${W}" height="${H}">`;
svg += `<rect x="${xp(23)}" y="${PAD.t}" width="${xp(26)-xp(23)}" height="${CH}" fill="rgba(255,214,0,0.08)"/>`;
svg += `<rect x="${xp(58)}" y="${PAD.t}" width="${xp(60)-xp(58)}" height="${CH}" fill="rgba(255,214,0,0.05)"/>`;
svg += `<text x="${xp(24.5)}" y="${PAD.t+10}" text-anchor="middle" font-size="8" fill="#6a5800" font-family="sans-serif" font-weight="700">SC</text>`;
svg += `<text x="${xp(59)}" y="${PAD.t+10}" text-anchor="middle" font-size="8" fill="#6a5800" font-family="sans-serif" font-weight="700">VSC</text>`;
for (let p = 1; p <= POSITIONS; p++) {
svg += `<line x1="${PAD.l}" y1="${yp(p)}" x2="${W-PAD.r}" y2="${yp(p)}" stroke="#1e1e1e" stroke-width="1"/>`;
svg += `<text x="${PAD.l-4}" y="${yp(p)+3}" text-anchor="end" font-size="9" fill="#4a4a4a" font-family="monospace">P${p}</text>`;
}
[0,10,20,30,40,50,60,70,78].forEach(l => {
svg += `<text x="${xp(l)}" y="${H-4}" text-anchor="middle" font-size="9" fill="#4a4a4a" font-family="monospace">L${l||1}</text>`;
});
drivers.forEach(d => {
const pts = d.pts.map(p => `${xp(p.l)},${yp(p.p)}`).join(' ');
const dash = d.dash ? 'stroke-dasharray="5,3"' : '';
svg += `<polyline points="${pts}" stroke="${d.color}" stroke-width="1.5" fill="none" ${dash} stroke-opacity="0.9"/>`;
const last = d.pts[d.pts.length - 1];
svg += `<text x="${xp(last.l)+4}" y="${yp(last.p)+4}" font-size="9" fill="${d.color}" font-family="monospace" font-weight="700">${d.code}</text>`;
});
svg += '</svg>';
el.innerHTML = svg;
}
function renderCharts() {
renderStrategyChart();
renderPositionChart();
}
document.addEventListener('DOMContentLoaded', renderCharts);
window.addEventListener('resize', renderCharts);
</script>
</body>
</html>