/* ================================================================ box-box design system — F1 Ops Room ================================================================ */ :root { /* Backgrounds */ --c-bg: #0a0a0a; --c-surface: #111111; --c-surface-2: #181818; --c-surface-3: #202020; /* Borders */ --c-border: #242424; --c-border-2: #303030; /* Text */ --c-text: #ebebeb; --c-text-2: #9c9c9c; --c-text-3: #6c6c6c; --c-text-inv: #0a0a0a; /* Signal colors */ --c-red: #e10600; --c-yellow: #ffd600; --c-green: #00cc6a; --c-purple: #b06fff; --c-blue: #4499ff; --c-orange: #ff8833; /* Tyre compounds */ --tyre-s: #e8002d; --tyre-m: #c8b400; --tyre-h: #b8b8b8; --tyre-i: #39b54a; --tyre-w: #0067ff; /* Team colors */ --t-rb: #3671c6; --t-mcl: #ff8000; --t-fer: #e8002d; --t-mer: #27f4d2; --t-am: #229971; --t-alp: #ff87bc; --t-wil: #64c4ff; --t-vcarb: #6692ff; --t-haas: #b6babd; --t-ks: #52e252; /* Spacing */ --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 24px; --s8: 32px; /* Typography */ --f-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', sans-serif; --f-mono: 'SF Mono', ui-monospace, 'Fira Code', 'Courier New', monospace; /* Density — comfortable default */ --row-h: 34px; --pad-v: 6px; --pad-h: 10px; --sec-gap: 28px; } html.compact { --row-h: 26px; --pad-v: 3px; --pad-h: 8px; --sec-gap: 18px; } /* ── Reset ──────────────────────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html { font-size: 13px; background: var(--c-bg); color: var(--c-text); scroll-behavior: smooth; } body { font-family: var(--f-ui); line-height: 1.4; min-height: 100vh; } a { color: inherit; text-decoration: none; } button { cursor: pointer; font-family: var(--f-ui); } /* ── App Nav ────────────────────────────────────────────────────── */ .app-nav { display: flex; align-items: center; gap: var(--s2); height: 44px; padding: 0 var(--s5); background: var(--c-surface); border-bottom: 1px solid var(--c-border); position: sticky; top: 0; z-index: 200; } .nav-logo { font-size: 13px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--c-text); margin-right: var(--s3); } .nav-logo em { color: var(--c-red); font-style: normal; } .nav-links { display: flex; gap: 2px; flex: 1; } .nav-links a { padding: 4px var(--s3); border-radius: 3px; font-size: 12px; color: var(--c-text-3); letter-spacing: 0.02em; transition: color 0.1s, background 0.1s; } .nav-links a:hover { color: var(--c-text-2); background: var(--c-surface-2); } .nav-links a.active { color: var(--c-text); } .nav-right { display: flex; align-items: center; gap: var(--s3); } .live-badge { display: flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; letter-spacing: 0.06em; color: var(--c-red); } .live-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--c-red); animation: blink 1.4s ease-in-out infinite; } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } } .density-toggle { display: flex; gap: 2px; } .density-toggle button { padding: 2px 7px; background: none; border: 1px solid var(--c-border); color: var(--c-text-3); font-size: 10px; border-radius: 2px; letter-spacing: 0.04em; } .density-toggle button.active { background: var(--c-surface-2); border-color: var(--c-border-2); color: var(--c-text-2); } /* ── Section Headers ────────────────────────────────────────────── */ .sec-header { display: flex; align-items: baseline; gap: var(--s3); padding-bottom: var(--s2); border-bottom: 1px solid var(--c-border); margin-bottom: var(--s4); } .sec-title { font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--c-text-2); } .sec-meta { font-size: 11px; color: var(--c-text-3); font-family: var(--f-mono); } /* ── Data Table ─────────────────────────────────────────────────── */ .data-table { width: 100%; border-collapse: collapse; font-size: 12px; } .data-table th { padding: var(--s1) var(--pad-h); text-align: left; font-size: 10px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-text-3); border-bottom: 1px solid var(--c-border); white-space: nowrap; } .data-table td { padding: var(--pad-v) var(--pad-h); border-bottom: 1px solid var(--c-border); height: var(--row-h); white-space: nowrap; } .data-table tbody tr:hover { background: var(--c-surface-2); } .data-table tbody tr:last-child td { border-bottom: none; } .data-table .num { font-family: var(--f-mono); text-align: right; } .data-table .center { text-align: center; } /* ── Driver Identity Cell ───────────────────────────────────────── */ .drv-cell { display: flex; align-items: center; gap: var(--s2); } .drv-bar { width: 3px; height: 20px; border-radius: 1px; flex-shrink: 0; } .drv-code { font-size: 13px; font-weight: 700; letter-spacing: 0.03em; } .drv-num { font-family: var(--f-mono); font-size: 10px; color: var(--c-text-3); } /* ── Tyre Badge ─────────────────────────────────────────────────── */ .tyre { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; font-size: 9px; font-weight: 800; font-family: var(--f-mono); flex-shrink: 0; } .tyre.S { background: var(--tyre-s); color: #fff; } .tyre.M { background: var(--tyre-m); color: #000; } .tyre.H { background: var(--tyre-h); color: #333; } .tyre.I { background: var(--tyre-i); color: #fff; } .tyre.W { background: var(--tyre-w); color: #fff; } /* ── Status Dot ─────────────────────────────────────────────────── */ .dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; } .dot.live { background: var(--c-red); } .dot.local { background: var(--c-green); } .dot.partial { background: var(--c-yellow); } .dot.missing { background: var(--c-text-3); } .dot.stale { background: var(--c-orange); } .dot.upcoming{ background: var(--c-border-2); } /* ── Status Badge (inline) ──────────────────────────────────────── */ .badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 2px; font-size: 10px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; white-space: nowrap; } .badge.local { background: rgba(0,204,106,0.12); color: var(--c-green); } .badge.live { background: rgba(225,6,0,0.12); color: var(--c-red); } .badge.partial { background: rgba(255,214,0,0.12); color: var(--c-yellow); } .badge.missing { background: rgba(85,85,85,0.12); color: var(--c-text-3); } .badge.stale { background: rgba(255,136,51,0.12); color: var(--c-orange); } /* ── Source Strip ───────────────────────────────────────────────── */ .source-strip { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s4); background: var(--c-surface); border: 1px solid var(--c-border); font-size: 11px; color: var(--c-text-2); } /* ── Countdown ──────────────────────────────────────────────────── */ .countdown { display: flex; align-items: baseline; gap: var(--s3); } .cd-unit { display: flex; flex-direction: column; align-items: center; gap: 2px; } .cd-num { font-family: var(--f-mono); font-size: 36px; font-weight: 700; color: var(--c-text); line-height: 1; } .cd-label { font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--c-text-3); } .cd-sep { font-family: var(--f-mono); font-size: 30px; color: var(--c-border-2); padding-bottom: 4px; } /* ── Session Banner (Live Timing) ───────────────────────────────── */ .session-banner { display: flex; align-items: center; gap: var(--s5); height: 40px; padding: 0 var(--s5); background: var(--c-surface); border-bottom: 2px solid var(--c-border); font-family: var(--f-mono); font-size: 12px; overflow-x: auto; overflow-y: hidden; flex-shrink: 0; } .banner-item { display: flex; align-items: center; gap: var(--s2); flex-shrink: 0; } .banner-label { font-size: 9px; font-family: var(--f-ui); letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-text-3); } .banner-val { font-weight: 600; } .banner-sep { color: var(--c-border-2); padding: 0 var(--s1); } .track-green { color: var(--c-green); } .track-yellow { color: var(--c-yellow); } .track-red { color: var(--c-red); } /* ── Race Control Messages ──────────────────────────────────────── */ .rc-list { display: flex; flex-direction: column; } .rc-msg { display: grid; grid-template-columns: 56px 1fr; gap: var(--s2); padding: 6px var(--s3); border-bottom: 1px solid var(--c-border); font-size: 11px; line-height: 1.4; } .rc-msg:last-child { border-bottom: none; } .rc-lap { font-family: var(--f-mono); color: var(--c-text-3); padding-top: 1px; } .rc-text { color: var(--c-text-2); } .rc-msg.sc .rc-text { color: var(--c-yellow); font-weight: 600; } .rc-msg.vsc .rc-text { color: var(--c-yellow); } .rc-msg.drs .rc-text { color: var(--c-green); } .rc-msg.flag .rc-text { color: var(--c-red); font-weight: 600; } .rc-msg.fl .rc-text { color: var(--c-purple); } /* ── Position Indicators ────────────────────────────────────────── */ .pos-gain { color: var(--c-green); font-weight: 600; } .pos-loss { color: var(--c-red); } .pos-same { color: var(--c-text-3); } /* ── Timing Tower specific ──────────────────────────────────────── */ .timing-table .pos-col { width: 30px; } .timing-table .drv-col { min-width: 120px; } .timing-table .gap-col { width: 80px; } .timing-table .int-col { width: 70px; } .timing-table .tyre-col { width: 40px; text-align: center; } .timing-table .age-col { width: 36px; } .timing-table .last-col { width: 78px; } .timing-table .best-col { width: 78px; } .timing-table tr.fastest-lap td { background: rgba(176,111,255,0.06); } .timing-table tr.pit-in td { background: rgba(255,214,0,0.05); } .timing-table tr.dnf td { opacity: 0.45; } /* ── Section Tabs ───────────────────────────────────────────────── */ .section-tabs { display: flex; gap: 2px; padding: var(--s3) var(--s5); border-bottom: 1px solid var(--c-border); overflow-x: auto; } .tab-btn { padding: 4px var(--s3); background: none; border: 1px solid transparent; border-radius: 2px; font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--c-text-3); white-space: nowrap; transition: color 0.1s; } .tab-btn:hover { color: var(--c-text-2); } .tab-btn.active { color: var(--c-text); border-color: var(--c-border-2); background: var(--c-surface-2); } .tab-panel { display: none; } .tab-panel.active { display: block; } /* ── Panels / Boxes ─────────────────────────────────────────────── */ .panel { background: var(--c-surface); border: 1px solid var(--c-border); } /* ── Strategy Chart Container ───────────────────────────────────── */ .strategy-chart { width: 100%; overflow: hidden; } .strategy-chart svg { display: block; width: 100%; height: auto; } /* ── CLI Block ──────────────────────────────────────────────────── */ .cli-block { background: var(--c-surface-2); border: 1px solid var(--c-border); border-left: 3px solid var(--c-border-2); padding: var(--s3) var(--s4); font-family: var(--f-mono); font-size: 11px; color: var(--c-text-2); line-height: 1.8; } .cli-block .comment { color: var(--c-text-3); } .cli-block .cmd { color: var(--c-green); } /* ── Dataset Status Row ─────────────────────────────────────────── */ .dataset-row { display: flex; align-items: center; gap: var(--s3); padding: var(--pad-v) 0; border-bottom: 1px solid var(--c-border); font-size: 11px; } .dataset-row:last-child { border-bottom: none; } .ds-name { flex: 1; color: var(--c-text-2); } .ds-status { font-family: var(--f-mono); font-size: 10px; } .ds-time { font-family: var(--f-mono); font-size: 10px; color: var(--c-text-3); min-width: 80px; text-align: right; } /* ── Utilities ──────────────────────────────────────────────────── */ .mono { font-family: var(--f-mono); } .t2 { color: var(--c-text-2); } .t3 { color: var(--c-text-3); } .t-green { color: var(--c-green); } .t-red { color: var(--c-red); } .t-yellow { color: var(--c-yellow); } .t-purple { color: var(--c-purple); } .t-orange { color: var(--c-orange); } .t-blue { color: var(--c-blue); } .flex { display: flex; } .flex-col { display: flex; flex-direction: column; } .ai-c { align-items: center; } .gap-1 { gap: var(--s1); } .gap-2 { gap: var(--s2); } .gap-3 { gap: var(--s3); } .gap-4 { gap: var(--s4); } .divider { height: 1px; background: var(--c-border); margin: var(--sec-gap) 0; } .scroll-y { overflow-y: auto; } .scroll-x { overflow-x: auto; } /* ── Responsive ─────────────────────────────────────────────────── */ @media (max-width: 768px) { .nav-links a { font-size: 11px; padding: 4px var(--s2); } .hide-mobile { display: none !important; } } @media (max-width: 480px) { .nav-links { gap: 0; } .hide-sm { display: none !important; } } /* ── Podium row accents ──────────────────────────────────────────── */ .pos-p1 { color: #d4a93a; font-size: 15px; font-weight: 800; } .pos-p2 { color: #a8a8a8; font-size: 14px; font-weight: 700; } .pos-p3 { color: #b07840; font-size: 14px; font-weight: 700; } /* ── Race Hub 2-column body ─────────────────────────────────────── */ .rh-body { display: grid; grid-template-columns: 1fr 290px; align-items: start; min-height: calc(100vh - 88px); } .rh-aside { border-left: 1px solid var(--c-border); position: sticky; top: 44px; max-height: calc(100vh - 44px); overflow-y: auto; padding: var(--s4); display: flex; flex-direction: column; gap: var(--s5); } @media (max-width: 980px) { .rh-body { grid-template-columns: 1fr; } .rh-aside { position: static; max-height: none; border-left: none; border-top: 2px solid var(--c-border); padding: var(--s5); } } /* ── Race Summary (aside) ────────────────────────────────────────── */ .podium-list { display: flex; flex-direction: column; gap: 1px; } .podium-item { display: grid; grid-template-columns: 22px 1fr auto; align-items: center; gap: var(--s2); padding: 6px 0; border-bottom: 1px solid var(--c-border); } .podium-item:last-child { border-bottom: none; } .podium-p { font-family: var(--f-mono); font-size: 12px; font-weight: 700; color: var(--c-text-3); } .podium-gap-val { font-family: var(--f-mono); font-size: 11px; color: var(--c-text-2); } .summary-stat-row { display: flex; align-items: baseline; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid var(--c-border); font-size: 11px; } .summary-stat-row:last-child { border-bottom: none; } .sstat-label { color: var(--c-text-3); } .sstat-val { font-family: var(--f-mono); color: var(--c-text-2); font-size: 11px; } /* ── Pit Window ─────────────────────────────────────────────────── */ .pit-row { display: flex; align-items: center; gap: var(--s2); padding: 5px var(--s3); border-bottom: 1px solid var(--c-border); font-size: 11px; } .pit-row:last-child { border-bottom: none; } .pit-driver { flex: 1; } .pit-tyre-age { font-family: var(--f-mono); font-size: 11px; color: var(--c-text-2); min-width: 32px; text-align: right; } .pit-status { font-size: 10px; font-weight: 700; letter-spacing: 0.04em; min-width: 56px; text-align: right; } .pit-status.open { color: var(--c-green); } .pit-status.soon { color: var(--c-yellow); } .pit-status.overdue { color: var(--c-orange); } .pit-status.done { color: var(--c-text-3); } /* ── Pinned Driver Cards ─────────────────────────────────────────── */ .pinned-strip { display: flex; gap: var(--s2); padding: var(--s2) var(--s4); background: var(--c-surface); border-bottom: 1px solid var(--c-border); overflow-x: auto; flex-shrink: 0; } .pin-card { display: flex; align-items: center; gap: var(--s2); padding: 5px var(--s3); background: var(--c-surface-2); border: 1px solid var(--c-border); border-radius: 2px; flex-shrink: 0; } .pin-pos { font-family: var(--f-mono); font-size: 11px; color: var(--c-text-3); min-width: 16px; } .pin-gap { font-family: var(--f-mono); font-size: 11px; color: var(--c-text-2); } /* ── Phone bottom tab bar ────────────────────────────────────────── */ .phone-tab-bar { display: none; position: fixed; bottom: 0; left: 0; right: 0; height: 54px; background: var(--c-surface); border-top: 2px solid var(--c-border); z-index: 300; } .phone-tab-bar button { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; background: none; border: none; color: var(--c-text-3); font-size: 9px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; padding-bottom: 4px; transition: color 0.1s; } .phone-tab-bar button.active { color: var(--c-text); } .phone-tab-bar button .tab-icon { font-size: 17px; line-height: 1; } /* Phone panel system */ .lt-phone-panel { } @media (max-width: 768px) { .phone-tab-bar { display: flex; } .has-phone-tabs { padding-bottom: 58px; overflow: hidden; height: calc(100vh - 44px - 40px); } .lt-phone-panel { display: none !important; } .lt-phone-panel.phone-active { display: flex !important; } /* Override grid for phone */ .lt-body-phone { display: block !important; } } /* ── Responsive: iPad intermediate ─────────────────────────────── */ @media (min-width: 769px) and (max-width: 1024px) { .rh-body { grid-template-columns: 1fr 240px; } } /* ── Gap sparkline ──────────────────────────────────────────────── */ .gap-spark { display: inline-flex; align-items: flex-end; gap: 1px; height: 12px; margin-left: 4px; vertical-align: middle; opacity: 0.7; } .gap-spark span { width: 3px; background: currentColor; border-radius: 1px; }