feat(ui): Velocity redesign — foundations (tokens, theme, chrome)
Re-skin the app into the "Velocity" neo-brutalist direction: acid-lime accent, hard offset shadows, slammed uppercase headlines, rounded brutalist blocks. Light "paper" chassis + a warm-charcoal dark mode, both keeping the lime accent and a constant black appbar; the light/dark toggle is preserved. - Type is Cyrillic-complete (the mockup's Anton/DM Sans/Space Mono are not, and this product is Russian-first): Oswald (display) + Manrope (body) + JetBrains Mono (numerals), loaded via the existing Google Fonts CDN. - app.css: Velocity token palette (light+dark) + brutalist shared components (cards, kicker chips, stat blocks, nav, segmented, sections, anomaly badge); diagonal-hatch texture; electric-blue focus rings. - MarathonTheme + Tokens.cs: Mud palette / typography / radius retargeted so every Mud component follows; appbar black, drawer flipped to paper. - MainLayout + NavBody chrome: black appbar, lime capture chip, paper drawer with brutalist nav blocks (fixes the old white-on-paper brand). - OddsTimeline + SportIcon recoloured to the Velocity palette (chart lines now read on both themes; dropped the off-brand purple sport hue). Foundations only — build clean, all 568 tests green. Page-level polish (Results winner colours, bespoke page styles) rolls out next.
This commit is contained in:
@@ -8,17 +8,17 @@
|
|||||||
|
|
||||||
<!-- Prevent flash of unthemed content -->
|
<!-- Prevent flash of unthemed content -->
|
||||||
<style>
|
<style>
|
||||||
html, body { background: #f5f4ef; margin: 0; }
|
html, body { background: #f3f1e9; margin: 0; }
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
html, body { background: #0c0a09; }
|
html, body { background: #141310; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Fonts: IBM Plex Sans / Serif / Mono + JetBrains Mono. Full Cyrillic coverage. -->
|
<!-- Fonts: Oswald (display) + Manrope (body) + JetBrains Mono (numerals). Full Cyrillic coverage. -->
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=IBM+Plex+Serif:wght@300;400;500;600&family=IBM+Plex+Mono:wght@400;500&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;600;700&family=Manrope:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700;800&display=swap"
|
||||||
rel="stylesheet" />
|
rel="stylesheet" />
|
||||||
|
|
||||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
||||||
@@ -26,13 +26,13 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<div style="padding: 64px; font-family: 'IBM Plex Serif', Georgia, serif; color: #475569;">
|
<div style="padding: 64px; font-family: 'Manrope', system-ui, sans-serif; color: #6b6757;">
|
||||||
<span style="font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: #d97706;">Booting</span>
|
<span style="font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: #0a0a0a; background: #c6f400; border: 2px solid #0a0a0a; border-radius: 8px; padding: 4px 9px;">Booting</span>
|
||||||
<div style="font-size: 32px; font-weight: 300; margin-top: 8px;">Marathon Odds Lab</div>
|
<div style="font-family: 'Oswald', sans-serif; font-size: 42px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.01em; margin-top: 14px; color: #0a0a0a;">Marathon Odds Lab</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="blazor-error-ui" style="display:none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000; padding: 12px 24px; background: #dc2626; color: #fafaf7; font-family: 'IBM Plex Sans', sans-serif;">
|
<div id="blazor-error-ui" style="display:none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000; padding: 12px 24px; background: #ff3b30; color: #fffef8; font-family: 'Manrope', system-ui, sans-serif;">
|
||||||
<span>An unhandled error has occurred.</span>
|
<span>An unhandled error has occurred.</span>
|
||||||
<a href="" class="reload" style="color: #fff; text-decoration: underline; margin-left: 12px;">Reload</a>
|
<a href="" class="reload" style="color: #fff; text-decoration: underline; margin-left: 12px;">Reload</a>
|
||||||
<a class="dismiss" style="float: right; cursor: pointer; padding: 0 8px;">×</a>
|
<a class="dismiss" style="float: right; cursor: pointer; padding: 0 8px;">×</a>
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
@inject AnomalyBrowsingState AnomalyState
|
@inject AnomalyBrowsingState AnomalyState
|
||||||
|
|
||||||
<nav class="m-nav" aria-label="primary">
|
<nav class="m-nav" aria-label="primary">
|
||||||
<div style="padding: var(--m-space-5) var(--m-space-4) var(--m-space-3); border-bottom: 1px solid rgba(231,229,228,0.10);">
|
<div style="padding: var(--m-space-5) var(--m-space-4) var(--m-space-4); border-bottom: 2px solid var(--m-c-ink);">
|
||||||
<div style="font-family: var(--m-font-display); font-size: 1.25rem; color: #fafaf7;">
|
<div style="font-family: var(--m-font-display); font-weight: 700; font-size: 1.5rem; text-transform: uppercase; letter-spacing: 0.01em; color: var(--m-c-ink);">
|
||||||
<span style="color: var(--m-c-accent);">M</span>arathon
|
<span style="background: var(--m-c-accent); color: var(--m-c-on-accent); padding: 0 5px; border-radius: 5px;">M</span>arathon
|
||||||
</div>
|
</div>
|
||||||
<div style="font-family: var(--m-font-mono); font-size: 0.6875rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(231,229,228,0.55); margin-top: 4px;">
|
<div style="font-family: var(--m-font-mono); font-size: 0.625rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--m-c-ink-soft); margin-top: 4px;">
|
||||||
Odds Lab · v0.1
|
Odds Lab · v0.1
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,18 +78,20 @@
|
|||||||
<style>
|
<style>
|
||||||
.m-nav__badge {
|
.m-nav__badge {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
min-width: 18px;
|
box-sizing: border-box;
|
||||||
|
min-width: 20px;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
background: var(--m-c-anomaly);
|
background: var(--m-c-anomaly);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-family: var(--m-font-mono);
|
font-family: var(--m-font-mono);
|
||||||
font-size: 0.625rem;
|
font-size: 0.625rem;
|
||||||
font-weight: 600;
|
font-weight: 700;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
line-height: 18px;
|
line-height: 16px;
|
||||||
height: 18px;
|
height: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: var(--m-radius-xs);
|
border: 2px solid var(--m-c-ink);
|
||||||
|
border-radius: var(--m-radius-sm);
|
||||||
animation: m-pulse 1.6s ease-in-out infinite;
|
animation: m-pulse 1.6s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
@@media (prefers-reduced-motion: reduce) {
|
@@media (prefers-reduced-motion: reduce) {
|
||||||
|
|||||||
@@ -152,9 +152,9 @@
|
|||||||
var times = points.Select(p => (object)p.At.UtcDateTime).ToList();
|
var times = points.Select(p => (object)p.At.UtcDateTime).ToList();
|
||||||
return new List<ITrace>
|
return new List<ITrace>
|
||||||
{
|
{
|
||||||
BuildSeries("Win 1", "#0f172a", points.Select(p => (object?)p.Win1Rate).ToList(), times),
|
BuildSeries("Win 1", "#244bff", points.Select(p => (object?)p.Win1Rate).ToList(), times),
|
||||||
BuildSeries("Draw", "#d97706", points.Select(p => (object?)p.DrawRate).ToList(), times),
|
BuildSeries("Draw", "#ff8a00", points.Select(p => (object?)p.DrawRate).ToList(), times),
|
||||||
BuildSeries("Win 2", "#dc2626", points.Select(p => (object?)p.Win2Rate).ToList(), times),
|
BuildSeries("Win 2", "#ff3b30", points.Select(p => (object?)p.Win2Rate).ToList(), times),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,13 +178,13 @@
|
|||||||
{
|
{
|
||||||
AutoSize = true,
|
AutoSize = true,
|
||||||
Margin = new Plotly.Blazor.LayoutLib.Margin { L = 56, R = 24, T = 24, B = 48 },
|
Margin = new Plotly.Blazor.LayoutLib.Margin { L = 56, R = 24, T = 24, B = 48 },
|
||||||
PaperBgColor = dark ? "#1c1917" : "#fafaf7",
|
PaperBgColor = dark ? "#1e1c15" : "#fffef8",
|
||||||
PlotBgColor = dark ? "#0c0a09" : "#fafaf7",
|
PlotBgColor = dark ? "#141310" : "#fffef8",
|
||||||
Font = new Plotly.Blazor.LayoutLib.Font
|
Font = new Plotly.Blazor.LayoutLib.Font
|
||||||
{
|
{
|
||||||
Family = "JetBrains Mono, IBM Plex Mono, Consolas, monospace",
|
Family = "JetBrains Mono, IBM Plex Mono, Consolas, monospace",
|
||||||
Size = 11,
|
Size = 11,
|
||||||
Color = dark ? "#f5f5f4" : "#0f172a",
|
Color = dark ? "#f5f3ea" : "#0a0a0a",
|
||||||
},
|
},
|
||||||
XAxis = new List<XAxis>
|
XAxis = new List<XAxis>
|
||||||
{
|
{
|
||||||
@@ -192,14 +192,14 @@
|
|||||||
{
|
{
|
||||||
Title = new Plotly.Blazor.LayoutLib.XAxisLib.Title { Text = string.Empty },
|
Title = new Plotly.Blazor.LayoutLib.XAxisLib.Title { Text = string.Empty },
|
||||||
ShowGrid = true,
|
ShowGrid = true,
|
||||||
GridColor = dark ? "#292524" : "#e7e5e4",
|
GridColor = dark ? "#2a2820" : "#e7e3d6",
|
||||||
ZeroLine = false,
|
ZeroLine = false,
|
||||||
LineColor = dark ? "#292524" : "#e7e5e4",
|
LineColor = dark ? "#2a2820" : "#e7e3d6",
|
||||||
TickFont = new Plotly.Blazor.LayoutLib.XAxisLib.TickFont
|
TickFont = new Plotly.Blazor.LayoutLib.XAxisLib.TickFont
|
||||||
{
|
{
|
||||||
Family = "JetBrains Mono, IBM Plex Mono, Consolas, monospace",
|
Family = "JetBrains Mono, IBM Plex Mono, Consolas, monospace",
|
||||||
Size = 10,
|
Size = 10,
|
||||||
Color = dark ? "#a8a29e" : "#475569",
|
Color = dark ? "#9c9784" : "#6b6757",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -209,14 +209,14 @@
|
|||||||
{
|
{
|
||||||
Title = new Plotly.Blazor.LayoutLib.YAxisLib.Title { Text = string.Empty },
|
Title = new Plotly.Blazor.LayoutLib.YAxisLib.Title { Text = string.Empty },
|
||||||
ShowGrid = true,
|
ShowGrid = true,
|
||||||
GridColor = dark ? "#292524" : "#e7e5e4",
|
GridColor = dark ? "#2a2820" : "#e7e3d6",
|
||||||
ZeroLine = false,
|
ZeroLine = false,
|
||||||
LineColor = dark ? "#292524" : "#e7e5e4",
|
LineColor = dark ? "#2a2820" : "#e7e3d6",
|
||||||
TickFont = new Plotly.Blazor.LayoutLib.YAxisLib.TickFont
|
TickFont = new Plotly.Blazor.LayoutLib.YAxisLib.TickFont
|
||||||
{
|
{
|
||||||
Family = "JetBrains Mono, IBM Plex Mono, Consolas, monospace",
|
Family = "JetBrains Mono, IBM Plex Mono, Consolas, monospace",
|
||||||
Size = 10,
|
Size = 10,
|
||||||
Color = dark ? "#a8a29e" : "#475569",
|
Color = dark ? "#9c9784" : "#6b6757",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -232,7 +232,7 @@
|
|||||||
{
|
{
|
||||||
Family = "JetBrains Mono, IBM Plex Mono, Consolas, monospace",
|
Family = "JetBrains Mono, IBM Plex Mono, Consolas, monospace",
|
||||||
Size = 11,
|
Size = 11,
|
||||||
Color = dark ? "#e7e5e4" : "#1e293b",
|
Color = dark ? "#d8d4c6" : "#26241e",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -20,10 +20,10 @@
|
|||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
.m-sport svg { width: 100%; height: 100%; display: block; }
|
.m-sport svg { width: 100%; height: 100%; display: block; }
|
||||||
.m-sport[data-sport="6"] { color: #d97706; }
|
.m-sport[data-sport="6"] { color: #ff8a00; } /* basketball — amber */
|
||||||
.m-sport[data-sport="11"] { color: #15803d; }
|
.m-sport[data-sport="11"] { color: #1f9e3d; } /* football — green */
|
||||||
.m-sport[data-sport="22723"] { color: #0369a1; }
|
.m-sport[data-sport="22723"] { color: #0d9488; } /* tennis — teal */
|
||||||
.m-sport[data-sport="43658"] { color: #6d28d9; }
|
.m-sport[data-sport="43658"] { color: #244bff; } /* hockey — electric blue */
|
||||||
[data-theme="dark"] .m-sport { filter: brightness(1.1); }
|
[data-theme="dark"] .m-sport { filter: brightness(1.1); }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@
|
|||||||
<div class="m-appbar__tools m-rise m-rise-2">
|
<div class="m-appbar__tools m-rise m-rise-2">
|
||||||
<span class="m-capture-pill" data-test="capture-pill"
|
<span class="m-capture-pill" data-test="capture-pill"
|
||||||
aria-label="@L["Scraping.Aria"]" title="@L["Scraping.Aria"]"
|
aria-label="@L["Scraping.Aria"]" title="@L["Scraping.Aria"]"
|
||||||
style="display:inline-flex; align-items:center; gap:7px; font-family:var(--m-font-mono); font-size:0.6875rem; text-transform:uppercase; letter-spacing:0.12em; color:@(Capturing ? "var(--m-c-positive)" : "var(--m-c-ink-soft)");">
|
style="display:inline-flex; align-items:center; gap:7px; font-family:var(--m-font-mono); font-size:0.6875rem; font-weight:700; text-transform:uppercase; letter-spacing:0.1em; padding:6px 10px; border-radius:8px; border:2px solid @(Capturing ? "#0a0a0a" : "rgba(255,254,248,0.4)"); background:@(Capturing ? "var(--m-c-accent)" : "transparent"); color:@(Capturing ? "var(--m-c-on-accent)" : "rgba(255,254,248,0.72)");">
|
||||||
<span style="width:8px; height:8px; border-radius:50%; background:@(Capturing ? "var(--m-c-positive)" : "var(--m-c-ink-soft)");"></span>
|
<span style="width:8px; height:8px; border-radius:50%; background:@(Capturing ? "#0a0a0a" : "rgba(255,254,248,0.72)");"></span>
|
||||||
@(Capturing ? L["Scraping.On"] : L["Scraping.Off"])
|
@(Capturing ? L["Scraping.On"] : L["Scraping.Off"])
|
||||||
</span>
|
</span>
|
||||||
<LocaleSwitcher />
|
<LocaleSwitcher />
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
ClipMode="DrawerClipMode.Always"
|
ClipMode="DrawerClipMode.Always"
|
||||||
Elevation="0"
|
Elevation="0"
|
||||||
Width="248px"
|
Width="248px"
|
||||||
Color="Color.Dark">
|
Color="Color.Surface">
|
||||||
<NavBody />
|
<NavBody />
|
||||||
</MudDrawer>
|
</MudDrawer>
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
<footer class="m-footer">
|
<footer class="m-footer">
|
||||||
<span class="m-kicker">Marathon Odds Lab</span>
|
<span class="m-kicker">Marathon Odds Lab</span>
|
||||||
<span style="font-family: var(--m-font-mono); font-size: 0.6875rem; color: var(--m-c-ink-soft); letter-spacing: 0.16em; text-transform: uppercase;">
|
<span style="font-family: var(--m-font-mono); font-size: 0.6875rem; color: var(--m-c-ink-soft); letter-spacing: 0.16em; text-transform: uppercase;">
|
||||||
Phase 5 · Editorial-Quant · v0.1
|
Velocity · v0.1
|
||||||
</span>
|
</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,8 +76,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--m-space-3);
|
gap: var(--m-space-3);
|
||||||
padding: 0 clamp(var(--m-space-3), 2vw, var(--m-space-5));
|
padding: 0 clamp(var(--m-space-3), 2vw, var(--m-space-5));
|
||||||
border-bottom: 1px solid var(--m-c-rule);
|
border-bottom: 2px solid var(--m-c-accent);
|
||||||
background: var(--m-c-paper);
|
background: #0a0a0a;
|
||||||
|
color: #fffef8;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,15 +117,12 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 clamp(var(--m-space-3), 2vw, var(--m-space-5));
|
padding: 0 clamp(var(--m-space-3), 2vw, var(--m-space-5));
|
||||||
border-top: 1px solid var(--m-c-rule);
|
border-top: 2px solid var(--m-c-ink);
|
||||||
background: var(--m-c-paper);
|
background: var(--m-c-paper);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .m-appbar,
|
/* The appbar is a constant black bar in both themes (set above); only the
|
||||||
[data-theme="dark"] .m-footer {
|
footer follows the paper/charcoal surface token. */
|
||||||
background: var(--m-c-paper-2);
|
|
||||||
border-color: var(--m-c-rule);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ namespace Marathon.UI.Theme;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Marathon design system, expressed as a MudBlazor theme.
|
/// The Marathon design system, expressed as a MudBlazor theme.
|
||||||
///
|
///
|
||||||
/// Aesthetic direction: editorial-quant. Inspired by Bloomberg terminals,
|
/// Aesthetic direction: "Velocity" — neo-brutalist sportsbook. Acid lime
|
||||||
/// FT.com long-reads, and Quartz dashboards. Confident, information-dense,
|
/// accent, hard offset shadows, slammed uppercase headlines. Pairs Oswald
|
||||||
/// reveals patterns. Pairs IBM Plex Sans (Cyrillic-capable display + body)
|
/// (Cyrillic-capable condensed display) and Manrope (body) with JetBrains
|
||||||
/// with JetBrains Mono for tabular numerals. Anomaly accent is a load-bearing
|
/// Mono for tabular numerals — the mockup's Anton/DM Sans/Space Mono lack
|
||||||
/// signal red so Phase 7 can hang the entire anomaly visual language off
|
/// Cyrillic, which this Russian-first product requires. Anomaly accent is a
|
||||||
/// <c>palette.Error</c> without coupling to a hard-coded hex.
|
/// load-bearing signal red so the anomaly visual language hangs off
|
||||||
|
/// <c>palette.Error</c> without coupling to a hard-coded hex. Light "paper"
|
||||||
|
/// chassis with a warm-charcoal dark mode; the black appbar is constant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class MarathonTheme
|
public static class MarathonTheme
|
||||||
{
|
{
|
||||||
@@ -27,103 +29,105 @@ public static class MarathonTheme
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// Palettes — single accent (amber #d97706), single signal (red #ef4444)
|
// Palettes — acid lime accent + signal red on a "paper" chassis
|
||||||
// on a deep navy/parchment chassis. No purple gradients, no cliche.
|
// (warm-charcoal in dark). Primary is the boldest structural colour
|
||||||
|
// per mode: ink in light, lime in dark. The appbar is black in both.
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
private static readonly PaletteLight LightPalette = new()
|
private static readonly PaletteLight LightPalette = new()
|
||||||
{
|
{
|
||||||
Primary = "#0f172a", // deep navy / ink
|
Primary = "#0a0a0a", // ink — brutalist black actions
|
||||||
PrimaryContrastText = "#fafaf7",
|
PrimaryContrastText = "#fffef8",
|
||||||
Secondary = "#334155", // slate
|
Secondary = "#26241e", // warm ink
|
||||||
SecondaryContrastText = "#fafaf7",
|
SecondaryContrastText = "#fffef8",
|
||||||
Tertiary = "#d97706", // amber accent
|
Tertiary = "#c6f400", // acid lime accent
|
||||||
TertiaryContrastText = "#1c1917",
|
TertiaryContrastText = "#0a0a0a",
|
||||||
Info = "#0369a1",
|
Info = "#244bff", // electric blue
|
||||||
Success = "#15803d",
|
Success = "#1f9e3d",
|
||||||
Warning = "#b45309",
|
Warning = "#ff8a00",
|
||||||
Error = "#dc2626", // anomaly signal
|
Error = "#ff3b30", // anomaly signal
|
||||||
ErrorContrastText = "#fff7ed",
|
ErrorContrastText = "#fffef8",
|
||||||
|
|
||||||
Black = "#1c1917",
|
Black = "#0a0a0a",
|
||||||
White = "#fafaf7",
|
White = "#fffef8",
|
||||||
Surface = "#fafaf7", // warm parchment
|
Surface = "#fffef8", // card paper
|
||||||
Background = "#f5f4ef", // a half-step warmer than surface
|
Background = "#f3f1e9", // page paper
|
||||||
BackgroundGray = "#ebe9e1",
|
BackgroundGray = "#e7e3d6",
|
||||||
DrawerBackground = "#0f172a", // dark drawer on light app — editorial contrast
|
DrawerBackground = "#fffef8", // paper drawer — brutalist light nav
|
||||||
DrawerText = "#e7e5e4",
|
DrawerText = "#26241e",
|
||||||
DrawerIcon = "#d6d3d1",
|
DrawerIcon = "#6b6757",
|
||||||
AppbarBackground = "#fafaf7",
|
AppbarBackground = "#0a0a0a", // constant black bar
|
||||||
AppbarText = "#0f172a",
|
AppbarText = "#fffef8",
|
||||||
|
|
||||||
TextPrimary = "#0f172a",
|
TextPrimary = "#0a0a0a",
|
||||||
TextSecondary = "#475569",
|
TextSecondary = "#6b6757",
|
||||||
TextDisabled = "#94a3b8",
|
TextDisabled = "#a8a293",
|
||||||
ActionDefault = "#334155",
|
ActionDefault = "#26241e",
|
||||||
ActionDisabled = "#cbd5e1",
|
ActionDisabled = "#cbc7b8",
|
||||||
ActionDisabledBackground = "#e2e8f0",
|
ActionDisabledBackground = "#e7e3d6",
|
||||||
|
|
||||||
LinesDefault = "#e7e5e4",
|
LinesDefault = "#d8d4c4",
|
||||||
LinesInputs = "#cbd5e1",
|
LinesInputs = "#0a0a0a", // bold black input borders
|
||||||
TableLines = "#e7e5e4",
|
TableLines = "#e7e3d6",
|
||||||
TableStriped = "#f5f4ef",
|
TableStriped = "#f3f1e9",
|
||||||
TableHover = "#ebe9e1",
|
TableHover = "#e7e3d6",
|
||||||
Divider = "#e7e5e4",
|
Divider = "#d8d4c4",
|
||||||
DividerLight = "#f1f5f9",
|
DividerLight = "#ebe7da",
|
||||||
|
|
||||||
OverlayDark = new MudColor("#0f172a99").Value,
|
OverlayDark = new MudColor("#0a0a0a99").Value,
|
||||||
OverlayLight = new MudColor("#fafaf7cc").Value,
|
OverlayLight = new MudColor("#fffef8cc").Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly PaletteDark DarkPalette = new()
|
private static readonly PaletteDark DarkPalette = new()
|
||||||
{
|
{
|
||||||
Primary = "#fbbf24", // amber, promoted in dark mode
|
Primary = "#c6f400", // lime, promoted in dark mode
|
||||||
PrimaryContrastText = "#0c0a09",
|
PrimaryContrastText = "#0a0a0a",
|
||||||
Secondary = "#94a3b8",
|
Secondary = "#d8d4c6",
|
||||||
SecondaryContrastText = "#0c0a09",
|
SecondaryContrastText = "#0a0a0a",
|
||||||
Tertiary = "#fbbf24",
|
Tertiary = "#c6f400",
|
||||||
TertiaryContrastText = "#0c0a09",
|
TertiaryContrastText = "#0a0a0a",
|
||||||
Info = "#38bdf8",
|
Info = "#6f8bff",
|
||||||
Success = "#4ade80",
|
Success = "#4ade80",
|
||||||
Warning = "#fbbf24",
|
Warning = "#ffae42",
|
||||||
Error = "#f87171", // anomaly signal — softened for dark
|
Error = "#ff5a4f", // anomaly signal — softened for dark
|
||||||
ErrorContrastText = "#0c0a09",
|
ErrorContrastText = "#0a0a0a",
|
||||||
|
|
||||||
Black = "#0c0a09",
|
Black = "#0a0a0a",
|
||||||
White = "#fafaf7",
|
White = "#fffef8",
|
||||||
Surface = "#1c1917", // ink-stained paper
|
Surface = "#1e1c15", // warm charcoal card
|
||||||
Background = "#0c0a09", // near-black
|
Background = "#141310", // near-black warm
|
||||||
BackgroundGray = "#1c1917",
|
BackgroundGray = "#2a2820",
|
||||||
DrawerBackground = "#0c0a09",
|
DrawerBackground = "#1e1c15",
|
||||||
DrawerText = "#e7e5e4",
|
DrawerText = "#d8d4c6",
|
||||||
DrawerIcon = "#a8a29e",
|
DrawerIcon = "#9c9784",
|
||||||
AppbarBackground = "#0c0a09",
|
AppbarBackground = "#0a0a0a", // constant black bar
|
||||||
AppbarText = "#fafaf7",
|
AppbarText = "#f5f3ea",
|
||||||
|
|
||||||
TextPrimary = "#f5f5f4",
|
TextPrimary = "#f5f3ea",
|
||||||
TextSecondary = "#a8a29e",
|
TextSecondary = "#9c9784",
|
||||||
TextDisabled = "#57534e",
|
TextDisabled = "#57534e",
|
||||||
ActionDefault = "#a8a29e",
|
ActionDefault = "#d8d4c6",
|
||||||
ActionDisabled = "#44403c",
|
ActionDisabled = "#57534e",
|
||||||
ActionDisabledBackground = "#1c1917",
|
ActionDisabledBackground = "#2a2820",
|
||||||
|
|
||||||
LinesDefault = "#292524",
|
LinesDefault = "#3a3730",
|
||||||
LinesInputs = "#44403c",
|
LinesInputs = "#f5f3ea", // light input borders on charcoal
|
||||||
TableLines = "#292524",
|
TableLines = "#2a2820",
|
||||||
TableStriped = "#1c1917",
|
TableStriped = "#1e1c15",
|
||||||
TableHover = "#292524",
|
TableHover = "#2a2820",
|
||||||
Divider = "#292524",
|
Divider = "#3a3730",
|
||||||
DividerLight = "#1c1917",
|
DividerLight = "#2a2820",
|
||||||
|
|
||||||
OverlayDark = new MudColor("#0c0a09cc").Value,
|
OverlayDark = new MudColor("#141310cc").Value,
|
||||||
OverlayLight = new MudColor("#fafaf722").Value,
|
OverlayLight = new MudColor("#f5f3ea22").Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// Typography — IBM Plex Sans / JetBrains Mono / IBM Plex Serif (display)
|
// Typography — Oswald (condensed display) / Manrope (body) /
|
||||||
// All have full Cyrillic coverage. Numerals are tabular.
|
// JetBrains Mono (numerals). All have full Cyrillic coverage, which
|
||||||
|
// the Velocity mockup's Anton/DM Sans/Space Mono do not. Numerals tabular.
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
private static readonly string[] DisplayStack = { "IBM Plex Serif", "PT Serif", "Georgia", "serif" };
|
private static readonly string[] DisplayStack = { "Oswald", "PT Sans Narrow", "Arial Narrow", "sans-serif" };
|
||||||
private static readonly string[] BodyStack = { "IBM Plex Sans", "PT Sans", "system-ui", "sans-serif" };
|
private static readonly string[] BodyStack = { "Manrope", "Segoe UI", "system-ui", "sans-serif" };
|
||||||
private static readonly string[] MonoStack = { "JetBrains Mono", "IBM Plex Mono", "Fira Code", "Consolas", "monospace" };
|
private static readonly string[] MonoStack = { "JetBrains Mono", "IBM Plex Mono", "Fira Code", "Consolas", "monospace" };
|
||||||
|
|
||||||
private static readonly Typography MarathonTypography = new()
|
private static readonly Typography MarathonTypography = new()
|
||||||
@@ -139,26 +143,29 @@ public static class MarathonTheme
|
|||||||
H1 = new H1
|
H1 = new H1
|
||||||
{
|
{
|
||||||
FontFamily = DisplayStack,
|
FontFamily = DisplayStack,
|
||||||
FontWeight = 300,
|
FontWeight = 700,
|
||||||
FontSize = "clamp(2.25rem, 4vw, 3.5rem)",
|
FontSize = "clamp(2.5rem, 5vw, 4rem)",
|
||||||
LineHeight = 1.05,
|
LineHeight = 0.98,
|
||||||
LetterSpacing = "-0.022em",
|
LetterSpacing = "0.005em",
|
||||||
|
TextTransform = "uppercase",
|
||||||
},
|
},
|
||||||
H2 = new H2
|
H2 = new H2
|
||||||
{
|
{
|
||||||
FontFamily = DisplayStack,
|
FontFamily = DisplayStack,
|
||||||
FontWeight = 400,
|
FontWeight = 700,
|
||||||
FontSize = "clamp(1.75rem, 2.5vw, 2.25rem)",
|
FontSize = "clamp(1.875rem, 3vw, 2.5rem)",
|
||||||
LineHeight = 1.15,
|
LineHeight = 1.02,
|
||||||
LetterSpacing = "-0.018em",
|
LetterSpacing = "0.005em",
|
||||||
|
TextTransform = "uppercase",
|
||||||
},
|
},
|
||||||
H3 = new H3
|
H3 = new H3
|
||||||
{
|
{
|
||||||
FontFamily = DisplayStack,
|
FontFamily = DisplayStack,
|
||||||
FontWeight = 500,
|
FontWeight = 600,
|
||||||
FontSize = "1.5rem",
|
FontSize = "1.625rem",
|
||||||
LineHeight = 1.25,
|
LineHeight = 1.1,
|
||||||
LetterSpacing = "-0.012em",
|
LetterSpacing = "0.01em",
|
||||||
|
TextTransform = "uppercase",
|
||||||
},
|
},
|
||||||
H4 = new H4
|
H4 = new H4
|
||||||
{
|
{
|
||||||
@@ -242,12 +249,11 @@ public static class MarathonTheme
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// Layout — sharp corners, narrow drawer. The aesthetic earns its
|
// Layout — rounded brutalist blocks, narrow drawer.
|
||||||
// authority through restraint.
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
private static readonly LayoutProperties LayoutProps = new()
|
private static readonly LayoutProperties LayoutProps = new()
|
||||||
{
|
{
|
||||||
DefaultBorderRadius = "2px",
|
DefaultBorderRadius = "10px",
|
||||||
AppbarHeight = "60px",
|
AppbarHeight = "60px",
|
||||||
DrawerWidthLeft = "248px",
|
DrawerWidthLeft = "248px",
|
||||||
DrawerWidthRight = "248px",
|
DrawerWidthRight = "248px",
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ public static class Tokens
|
|||||||
{
|
{
|
||||||
public static class Colors
|
public static class Colors
|
||||||
{
|
{
|
||||||
public const string AnomalySignal = "#dc2626";
|
public const string AnomalySignal = "#ff3b30";
|
||||||
public const string AnomalySignalDark = "#f87171";
|
public const string AnomalySignalDark = "#ff5a4f";
|
||||||
public const string Accent = "#d97706";
|
public const string Accent = "#c6f400"; // acid lime
|
||||||
public const string AccentDark = "#fbbf24";
|
public const string AccentDark = "#c6f400";
|
||||||
public const string InkPrimary = "#0f172a";
|
public const string InkPrimary = "#0a0a0a";
|
||||||
public const string Parchment = "#fafaf7";
|
public const string Parchment = "#fffef8";
|
||||||
public const string ParchmentDeep = "#f5f4ef";
|
public const string ParchmentDeep = "#f3f1e9";
|
||||||
public const string InkDeep = "#0c0a09";
|
public const string InkDeep = "#141310";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Spacing
|
public static class Spacing
|
||||||
@@ -31,8 +31,8 @@ public static class Tokens
|
|||||||
|
|
||||||
public static class Typography
|
public static class Typography
|
||||||
{
|
{
|
||||||
public const string DisplayStack = "\"IBM Plex Serif\", \"PT Serif\", Georgia, serif";
|
public const string DisplayStack = "\"Oswald\", \"PT Sans Narrow\", \"Arial Narrow\", sans-serif";
|
||||||
public const string BodyStack = "\"IBM Plex Sans\", \"PT Sans\", system-ui, sans-serif";
|
public const string BodyStack = "\"Manrope\", \"Segoe UI\", system-ui, sans-serif";
|
||||||
public const string MonoStack = "\"JetBrains Mono\", \"IBM Plex Mono\", \"Fira Code\", Consolas, monospace";
|
public const string MonoStack = "\"JetBrains Mono\", \"IBM Plex Mono\", \"Fira Code\", Consolas, monospace";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+158
-117
@@ -1,9 +1,13 @@
|
|||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
Marathon — Editorial-Quant design system
|
Marathon — "Velocity" design system
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
Inspiration: long-form data journalism (FT, Quartz), terminal
|
Neo-brutalist sportsbook. Acid lime, hard offset shadows, slammed
|
||||||
instruments (Bloomberg), and Belarusian / Soviet print typography.
|
uppercase headlines. Cyrillic-complete type: Oswald (display) +
|
||||||
The aesthetic is confident, dense, and serif-led on display surfaces.
|
Manrope (body) + JetBrains Mono (numerals / labels) — the Velocity
|
||||||
|
mockup's Anton/DM Sans/Space Mono have no Cyrillic, which this
|
||||||
|
Russian-first product needs.
|
||||||
|
Light "paper" chassis + a warm-charcoal dark mode; both keep the
|
||||||
|
lime accent and the hard ink/black shadow signature.
|
||||||
=================================================================== */
|
=================================================================== */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
@@ -18,50 +22,63 @@
|
|||||||
--m-space-8: 64px;
|
--m-space-8: 64px;
|
||||||
--m-space-9: 96px;
|
--m-space-9: 96px;
|
||||||
|
|
||||||
/* ----- Radius — sharp by default, soft variants for inputs ----- */
|
/* ----- Radius — rounded brutalist blocks ----- */
|
||||||
--m-radius-sharp: 0;
|
--m-radius-sharp: 0;
|
||||||
--m-radius-xs: 2px;
|
--m-radius-xs: 6px;
|
||||||
--m-radius-sm: 4px;
|
--m-radius-sm: 8px;
|
||||||
--m-radius-md: 6px;
|
--m-radius-md: 10px;
|
||||||
--m-radius-lg: 10px;
|
--m-radius-lg: 14px;
|
||||||
|
|
||||||
/* ----- Typography ----- */
|
/* ----- Brutalist borders + hard offset shadows ----- */
|
||||||
--m-font-display: "IBM Plex Serif", "PT Serif", Georgia, serif;
|
--m-border-w: 2px;
|
||||||
--m-font-body: "IBM Plex Sans", "PT Sans", system-ui, sans-serif;
|
--m-border-w-bold: 3px;
|
||||||
|
--m-shadow-hard: 5px 5px 0 var(--m-c-ink);
|
||||||
|
--m-shadow-hard-sm: 3px 3px 0 var(--m-c-ink);
|
||||||
|
--m-shadow-hard-accent: 5px 5px 0 var(--m-c-accent);
|
||||||
|
--m-shadow-hard-anomaly: 5px 5px 0 var(--m-c-anomaly);
|
||||||
|
|
||||||
|
/* ----- Typography (all Cyrillic-complete) ----- */
|
||||||
|
--m-font-display: "Oswald", "PT Sans Narrow", "Arial Narrow", sans-serif;
|
||||||
|
--m-font-body: "Manrope", "Segoe UI", system-ui, sans-serif;
|
||||||
--m-font-mono: "JetBrains Mono", "IBM Plex Mono", "Fira Code", Consolas, monospace;
|
--m-font-mono: "JetBrains Mono", "IBM Plex Mono", "Fira Code", Consolas, monospace;
|
||||||
|
|
||||||
/* ----- Colors — light (parchment) chassis ----- */
|
/* ----- Colors — light "paper" chassis ----- */
|
||||||
--m-c-ink: #0f172a;
|
--m-c-ink: #0a0a0a;
|
||||||
--m-c-ink-2: #1e293b;
|
--m-c-ink-2: #26241e;
|
||||||
--m-c-ink-soft: #475569;
|
--m-c-ink-soft: #6b6757;
|
||||||
--m-c-paper: #fafaf7;
|
--m-c-paper: #fffef8;
|
||||||
--m-c-paper-2: #f5f4ef;
|
--m-c-paper-2: #f3f1e9;
|
||||||
--m-c-paper-3: #ebe9e1;
|
--m-c-paper-3: #e7e3d6;
|
||||||
--m-c-rule: #e7e5e4;
|
--m-c-rule: #0a0a0a;
|
||||||
--m-c-accent: #d97706;
|
--m-c-accent: #c6f400; /* acid lime */
|
||||||
--m-c-accent-soft: #f59e0b;
|
--m-c-accent-soft: #b3dd00;
|
||||||
--m-c-anomaly: #dc2626;
|
--m-c-on-accent: #0a0a0a; /* ink on lime — lime is a light hue */
|
||||||
--m-c-positive: #15803d;
|
--m-c-anomaly: #ff3b30;
|
||||||
--m-c-info: #0369a1;
|
--m-c-positive: #1f9e3d;
|
||||||
|
--m-c-info: #244bff; /* electric blue */
|
||||||
|
|
||||||
/* Tabular numerals for everywhere odds/scores appear */
|
/* Tabular numerals for everywhere odds/scores appear */
|
||||||
--m-num-feature: "tnum" 1, "lnum" 1, "ss01" 1;
|
--m-num-feature: "tnum" 1, "lnum" 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark theme overrides (applied via class on <html> or via MudThemeProvider) */
|
/* Dark theme overrides — warm charcoal, lime retained */
|
||||||
.mud-theme-dark, [data-theme="dark"] {
|
.mud-theme-dark, [data-theme="dark"] {
|
||||||
--m-c-ink: #f5f5f4;
|
--m-c-ink: #f5f3ea;
|
||||||
--m-c-ink-2: #e7e5e4;
|
--m-c-ink-2: #d8d4c6;
|
||||||
--m-c-ink-soft: #a8a29e;
|
--m-c-ink-soft: #9c9784;
|
||||||
--m-c-paper: #1c1917;
|
--m-c-paper: #1e1c15;
|
||||||
--m-c-paper-2: #0c0a09;
|
--m-c-paper-2: #141310;
|
||||||
--m-c-paper-3: #292524;
|
--m-c-paper-3: #2a2820;
|
||||||
--m-c-rule: #292524;
|
--m-c-rule: #f5f3ea;
|
||||||
--m-c-accent: #fbbf24;
|
--m-c-accent: #c6f400;
|
||||||
--m-c-accent-soft: #fcd34d;
|
--m-c-accent-soft: #aacc00;
|
||||||
--m-c-anomaly: #f87171;
|
--m-c-on-accent: #0a0a0a;
|
||||||
|
--m-c-anomaly: #ff5a4f;
|
||||||
--m-c-positive: #4ade80;
|
--m-c-positive: #4ade80;
|
||||||
--m-c-info: #38bdf8;
|
--m-c-info: #6f8bff;
|
||||||
|
/* Hard shadow goes pure-black on dark; the light border defines the block. */
|
||||||
|
--m-shadow-hard: 5px 5px 0 #000000;
|
||||||
|
--m-shadow-hard-sm: 3px 3px 0 #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
@@ -81,19 +98,13 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
/* Subtle paper grain — 1px mottled noise, rendered cheaply via SVG. */
|
/* Subtle diagonal hatch — the Velocity texture. */
|
||||||
background-image:
|
background-image: repeating-linear-gradient(135deg, transparent 0 22px, rgba(10, 10, 10, 0.025) 22px 24px);
|
||||||
radial-gradient(circle at 25% 12%, rgba(217, 119, 6, 0.035), transparent 45%),
|
|
||||||
radial-gradient(circle at 88% 78%, rgba(15, 23, 42, 0.040), transparent 50%),
|
|
||||||
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.045 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
|
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mud-theme-dark body, [data-theme="dark"] body {
|
.mud-theme-dark body, [data-theme="dark"] body {
|
||||||
background-image:
|
background-image: repeating-linear-gradient(135deg, transparent 0 22px, rgba(255, 255, 255, 0.022) 22px 24px);
|
||||||
radial-gradient(circle at 25% 12%, rgba(251, 191, 36, 0.045), transparent 45%),
|
|
||||||
radial-gradient(circle at 88% 78%, rgba(56, 189, 248, 0.030), transparent 50%),
|
|
||||||
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.025 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
@@ -120,61 +131,71 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
Editorial markers — kicker label + serif display lockup
|
Editorial markers — lime kicker chip + slammed display lockup
|
||||||
=================================================================== */
|
=================================================================== */
|
||||||
.m-kicker {
|
.m-kicker {
|
||||||
font-family: var(--m-font-mono);
|
font-family: var(--m-font-mono);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.18em;
|
letter-spacing: 0.14em;
|
||||||
font-size: 0.6875rem;
|
font-size: 0.6875rem;
|
||||||
color: var(--m-c-accent);
|
font-weight: 700;
|
||||||
font-weight: 500;
|
color: var(--m-c-on-accent);
|
||||||
|
background: var(--m-c-accent);
|
||||||
|
border: var(--m-border-w) solid var(--m-c-ink);
|
||||||
|
border-radius: var(--m-radius-md);
|
||||||
|
padding: 5px 10px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-bottom: var(--m-space-1);
|
}
|
||||||
border-bottom: 1px solid var(--m-c-accent);
|
|
||||||
|
/* A tilted variant for hero kickers — opt-in so it never skews chrome. */
|
||||||
|
.m-kicker--tilt {
|
||||||
|
transform: rotate(-1.5deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-display {
|
.m-display {
|
||||||
font-family: var(--m-font-display);
|
font-family: var(--m-font-display);
|
||||||
font-weight: 300;
|
font-weight: 700;
|
||||||
letter-spacing: -0.022em;
|
letter-spacing: 0.005em;
|
||||||
line-height: 1.05;
|
line-height: 0.98;
|
||||||
|
text-transform: uppercase;
|
||||||
color: var(--m-c-ink);
|
color: var(--m-c-ink);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-rule {
|
.m-rule {
|
||||||
border: 0;
|
border: 0;
|
||||||
border-top: 1px solid var(--m-c-rule);
|
border-top: var(--m-border-w) solid var(--m-c-ink);
|
||||||
margin: var(--m-space-5) 0;
|
margin: var(--m-space-5) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-rule--double {
|
.m-rule--double {
|
||||||
border: 0;
|
border: 0;
|
||||||
border-top: 3px double var(--m-c-rule);
|
border-top: var(--m-border-w-bold) double var(--m-c-ink);
|
||||||
margin: var(--m-space-5) 0;
|
margin: var(--m-space-5) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
Cards — paper-like, borders not shadows
|
Cards — brutalist blocks: thick border + hard offset shadow
|
||||||
=================================================================== */
|
=================================================================== */
|
||||||
.m-card {
|
.m-card {
|
||||||
background: var(--m-c-paper);
|
background: var(--m-c-paper);
|
||||||
border: 1px solid var(--m-c-rule);
|
border: var(--m-border-w-bold) solid var(--m-c-ink);
|
||||||
border-radius: var(--m-radius-xs);
|
border-radius: var(--m-radius-lg);
|
||||||
|
box-shadow: var(--m-shadow-hard);
|
||||||
padding: var(--m-space-5);
|
padding: var(--m-space-5);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Emphasis variants recolour the hard shadow rather than a hidden left rule. */
|
||||||
.m-card--accented {
|
.m-card--accented {
|
||||||
border-left: 3px solid var(--m-c-accent);
|
box-shadow: var(--m-shadow-hard-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-card--anomaly {
|
.m-card--anomaly {
|
||||||
border-left: 3px solid var(--m-c-anomaly);
|
box-shadow: var(--m-shadow-hard-anomaly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
Stat block — large number, mono, kicker on top
|
Stat block — slammed Oswald number, lime tick, mono label
|
||||||
=================================================================== */
|
=================================================================== */
|
||||||
.m-stat {
|
.m-stat {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -183,26 +204,37 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.m-stat__value {
|
.m-stat__value {
|
||||||
font-family: var(--m-font-mono);
|
font-family: var(--m-font-display);
|
||||||
font-feature-settings: var(--m-num-feature);
|
font-feature-settings: var(--m-num-feature);
|
||||||
font-size: clamp(2rem, 4vw, 3rem);
|
font-size: clamp(2.25rem, 4.5vw, 3.25rem);
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: var(--m-c-ink);
|
color: var(--m-c-ink);
|
||||||
letter-spacing: -0.02em;
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-stat__value::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
width: 42px;
|
||||||
|
height: 5px;
|
||||||
|
margin-top: var(--m-space-2);
|
||||||
|
background: var(--m-c-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-stat__label {
|
.m-stat__label {
|
||||||
font-family: var(--m-font-body);
|
font-family: var(--m-font-mono);
|
||||||
font-size: 0.8125rem;
|
font-size: 0.6875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
color: var(--m-c-ink-soft);
|
color: var(--m-c-ink-soft);
|
||||||
text-transform: none;
|
|
||||||
letter-spacing: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-stat__delta {
|
.m-stat__delta {
|
||||||
font-family: var(--m-font-mono);
|
font-family: var(--m-font-mono);
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
|
font-weight: 700;
|
||||||
color: var(--m-c-positive);
|
color: var(--m-c-positive);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,16 +271,16 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
Focus rings — deliberate, accent, never invisible
|
Focus rings — electric blue for contrast on lime/paper and charcoal
|
||||||
=================================================================== */
|
=================================================================== */
|
||||||
:focus-visible {
|
:focus-visible {
|
||||||
outline: 2px solid var(--m-c-accent);
|
outline: var(--m-border-w) solid var(--m-c-info);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mud-button:focus-visible,
|
.mud-button:focus-visible,
|
||||||
.mud-icon-button:focus-visible {
|
.mud-icon-button:focus-visible {
|
||||||
outline: 2px solid var(--m-c-accent);
|
outline: var(--m-border-w) solid var(--m-c-info);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,10 +324,12 @@ body {
|
|||||||
|
|
||||||
.m-brand__mark {
|
.m-brand__mark {
|
||||||
font-family: var(--m-font-display);
|
font-family: var(--m-font-display);
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
font-size: 1.375rem;
|
font-size: 1.5rem;
|
||||||
letter-spacing: -0.02em;
|
letter-spacing: 0.01em;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-brand__mark::first-letter {
|
.m-brand__mark::first-letter {
|
||||||
@@ -304,47 +338,55 @@ body {
|
|||||||
|
|
||||||
.m-brand__dateline {
|
.m-brand__dateline {
|
||||||
font-family: var(--m-font-mono);
|
font-family: var(--m-font-mono);
|
||||||
font-size: 0.6875rem;
|
font-size: 0.625rem;
|
||||||
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.16em;
|
letter-spacing: 0.16em;
|
||||||
color: var(--m-c-ink-soft);
|
color: var(--m-c-accent);
|
||||||
border-left: 1px solid var(--m-c-rule);
|
border-left: var(--m-border-w) solid currentColor;
|
||||||
padding-left: var(--m-space-3);
|
padding-left: var(--m-space-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
Drawer — narrow, dark, mono labels
|
Drawer — paper sidebar, brutalist nav blocks
|
||||||
=================================================================== */
|
=================================================================== */
|
||||||
.m-nav__group {
|
.m-nav__group {
|
||||||
padding: var(--m-space-3) var(--m-space-4);
|
padding: var(--m-space-4) var(--m-space-3) var(--m-space-2);
|
||||||
font-family: var(--m-font-mono);
|
font-family: var(--m-font-mono);
|
||||||
font-size: 0.6875rem;
|
font-size: 0.625rem;
|
||||||
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.18em;
|
letter-spacing: 0.18em;
|
||||||
color: rgba(231, 229, 228, 0.55);
|
color: var(--m-c-ink-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-nav__link {
|
.m-nav__link {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--m-space-3);
|
gap: var(--m-space-3);
|
||||||
padding: var(--m-space-3) var(--m-space-4);
|
padding: 10px 12px;
|
||||||
color: rgba(231, 229, 228, 0.85);
|
color: var(--m-c-ink-2);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 0.9375rem;
|
font-family: var(--m-font-body);
|
||||||
border-left: 2px solid transparent;
|
font-weight: 700;
|
||||||
transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
|
font-size: 0.875rem;
|
||||||
|
border: var(--m-border-w) solid transparent;
|
||||||
|
border-radius: var(--m-radius-md);
|
||||||
|
transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease, background 120ms ease, color 120ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-nav__link:hover {
|
.m-nav__link:hover {
|
||||||
background: rgba(217, 119, 6, 0.10);
|
border-color: var(--m-c-ink);
|
||||||
color: #ffffff;
|
transform: translate(-1px, -1px);
|
||||||
|
box-shadow: var(--m-shadow-hard-sm);
|
||||||
|
color: var(--m-c-ink);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-nav__link.active {
|
.m-nav__link.active {
|
||||||
color: #ffffff;
|
background: var(--m-c-accent);
|
||||||
background: rgba(217, 119, 6, 0.14);
|
color: var(--m-c-on-accent);
|
||||||
border-left-color: var(--m-c-accent);
|
border-color: var(--m-c-ink);
|
||||||
|
box-shadow: var(--m-shadow-hard-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-nav__link .mud-icon-root { font-size: 1.1rem; }
|
.m-nav__link .mud-icon-root { font-size: 1.1rem; }
|
||||||
@@ -354,8 +396,8 @@ body {
|
|||||||
=================================================================== */
|
=================================================================== */
|
||||||
.m-segmented {
|
.m-segmented {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
border: 1px solid var(--m-c-rule);
|
border: var(--m-border-w) solid var(--m-c-ink);
|
||||||
border-radius: var(--m-radius-xs);
|
border-radius: var(--m-radius-md);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: var(--m-c-paper);
|
background: var(--m-c-paper);
|
||||||
}
|
}
|
||||||
@@ -367,15 +409,16 @@ body {
|
|||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
font-family: var(--m-font-mono);
|
font-family: var(--m-font-mono);
|
||||||
font-size: 0.6875rem;
|
font-size: 0.6875rem;
|
||||||
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.14em;
|
letter-spacing: 0.12em;
|
||||||
color: var(--m-c-ink-soft);
|
color: var(--m-c-ink-soft);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 120ms ease, color 120ms ease;
|
transition: background 120ms ease, color 120ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-segmented__btn + .m-segmented__btn {
|
.m-segmented__btn + .m-segmented__btn {
|
||||||
border-left: 1px solid var(--m-c-rule);
|
border-left: var(--m-border-w) solid var(--m-c-ink);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-segmented__btn:hover {
|
.m-segmented__btn:hover {
|
||||||
@@ -383,21 +426,17 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.m-segmented__btn.is-active {
|
.m-segmented__btn.is-active {
|
||||||
background: var(--m-c-ink);
|
|
||||||
color: var(--m-c-paper);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mud-theme-dark .m-segmented__btn.is-active,
|
|
||||||
[data-theme="dark"] .m-segmented__btn.is-active {
|
|
||||||
background: var(--m-c-accent);
|
background: var(--m-c-accent);
|
||||||
color: var(--m-c-paper-2);
|
color: var(--m-c-on-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================================
|
/* ===================================================================
|
||||||
Settings page — section ledger
|
Settings page — section ledger
|
||||||
=================================================================== */
|
=================================================================== */
|
||||||
.m-section {
|
.m-section {
|
||||||
border: 1px solid var(--m-c-rule);
|
border: var(--m-border-w-bold) solid var(--m-c-ink);
|
||||||
|
border-radius: var(--m-radius-lg);
|
||||||
|
box-shadow: var(--m-shadow-hard);
|
||||||
background: var(--m-c-paper);
|
background: var(--m-c-paper);
|
||||||
margin-bottom: var(--m-space-5);
|
margin-bottom: var(--m-space-5);
|
||||||
}
|
}
|
||||||
@@ -407,16 +446,17 @@ body {
|
|||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: var(--m-space-4) var(--m-space-5);
|
padding: var(--m-space-4) var(--m-space-5);
|
||||||
border-bottom: 1px solid var(--m-c-rule);
|
border-bottom: var(--m-border-w) solid var(--m-c-ink);
|
||||||
background: var(--m-c-paper-2);
|
background: var(--m-c-paper-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-section__head h2 {
|
.m-section__head h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: var(--m-font-display);
|
font-family: var(--m-font-display);
|
||||||
font-weight: 400;
|
font-weight: 700;
|
||||||
font-size: 1.25rem;
|
font-size: 1.375rem;
|
||||||
letter-spacing: -0.012em;
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-section__body {
|
.m-section__body {
|
||||||
@@ -450,15 +490,16 @@ body {
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--m-space-2);
|
gap: var(--m-space-2);
|
||||||
padding: 2px 8px;
|
padding: 3px 9px;
|
||||||
background: rgba(220, 38, 38, 0.10);
|
background: var(--m-c-paper);
|
||||||
color: var(--m-c-anomaly);
|
color: var(--m-c-anomaly);
|
||||||
border: 1px solid currentColor;
|
border: var(--m-border-w) solid currentColor;
|
||||||
border-radius: var(--m-radius-xs);
|
border-radius: var(--m-radius-sm);
|
||||||
font-family: var(--m-font-mono);
|
font-family: var(--m-font-mono);
|
||||||
font-size: 0.6875rem;
|
font-size: 0.6875rem;
|
||||||
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.14em;
|
letter-spacing: 0.12em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-anomaly__pulse {
|
.m-anomaly__pulse {
|
||||||
|
|||||||
@@ -8,17 +8,17 @@
|
|||||||
|
|
||||||
<!-- Prevent flash of unthemed content -->
|
<!-- Prevent flash of unthemed content -->
|
||||||
<style>
|
<style>
|
||||||
html, body { background: #f5f4ef; margin: 0; }
|
html, body { background: #f3f1e9; margin: 0; }
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
html, body { background: #0c0a09; }
|
html, body { background: #141310; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Fonts: IBM Plex Sans / Serif / Mono + JetBrains Mono. Full Cyrillic coverage. -->
|
<!-- Fonts: Oswald (display) + Manrope (body) + JetBrains Mono (numerals). Full Cyrillic coverage. -->
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=IBM+Plex+Serif:wght@300;400;500;600&family=IBM+Plex+Mono:wght@400;500&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;600;700&family=Manrope:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700;800&display=swap"
|
||||||
rel="stylesheet" />
|
rel="stylesheet" />
|
||||||
|
|
||||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
||||||
@@ -26,13 +26,13 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<div style="padding: 64px; font-family: 'IBM Plex Serif', Georgia, serif; color: #475569;">
|
<div style="padding: 64px; font-family: 'Manrope', system-ui, sans-serif; color: #6b6757;">
|
||||||
<span style="font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: #d97706;">Booting</span>
|
<span style="font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: #0a0a0a; background: #c6f400; border: 2px solid #0a0a0a; border-radius: 8px; padding: 4px 9px;">Booting</span>
|
||||||
<div style="font-size: 32px; font-weight: 300; margin-top: 8px;">Marathon Odds Lab</div>
|
<div style="font-family: 'Oswald', sans-serif; font-size: 42px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.01em; margin-top: 14px; color: #0a0a0a;">Marathon Odds Lab</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="blazor-error-ui" style="display:none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000; padding: 12px 24px; background: #dc2626; color: #fafaf7; font-family: 'IBM Plex Sans', sans-serif;">
|
<div id="blazor-error-ui" style="display:none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 1000; padding: 12px 24px; background: #ff3b30; color: #fffef8; font-family: 'Manrope', system-ui, sans-serif;">
|
||||||
<span>An unhandled error has occurred.</span>
|
<span>An unhandled error has occurred.</span>
|
||||||
<a href="" class="reload" style="color: #fff; text-decoration: underline; margin-left: 12px;">Reload</a>
|
<a href="" class="reload" style="color: #fff; text-decoration: underline; margin-left: 12px;">Reload</a>
|
||||||
<a class="dismiss" style="float: right; cursor: pointer; padding: 0 8px;">×</a>
|
<a class="dismiss" style="float: right; cursor: pointer; padding: 0 8px;">×</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user