Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import { AuthProvider } from "./services/AuthContext";
*
* - Wraps the entire application
* - Provides consistent layout with Header and Footer
* - Applies the Godly-inspired dark theme (slate-950 background, design-tokens.json)
* - Renders the routed pages inside the main content area
*/
const App: React.FC = () => {
return (
<AuthProvider>
<div className="min-h-screen flex flex-col">
{/* dark class activates the slate-950/900 dark design system */}
<div className="dark min-h-screen flex flex-col bg-background text-foreground">
{/* Global header */}
<Header />

Expand All @@ -31,3 +33,4 @@ const App: React.FC = () => {
};

export default App;

132 changes: 80 additions & 52 deletions frontend/src/presentation/pages/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface DisplayItem {
/**
* Home page component — introduces Bench Analytics and highlights
* its main features to encourage user engagement.
* Styled to match the Godly-inspired dark design system (design-tokens.json).
*/
const Home: React.FC = () => {
const navigate = useNavigate();
Expand All @@ -52,7 +53,7 @@ const Home: React.FC = () => {
{
title: "Matchup Analysis",
description:
"Generate optimized lineups based on each batters statistical profile.",
"Generate optimized lineups based on each batter's statistical profile.",
icon: Target,
},
{
Expand Down Expand Up @@ -84,18 +85,26 @@ const Home: React.FC = () => {
];

return (
<div className="space-y-12">
<div className="space-y-16">
{/* ---------- Hero Section ---------- */}
{/* Introduces the platform and main call-to-action buttons */}
<section className="relative overflow-hidden rounded-lg flex justify-center items-center min-h-[400px]">
<div className="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 w-[calc(100%-1rem)] max-w-6xl h-[400px] bg-gradient-to-r from-blue-900/10 to-red-600/10 rounded-2xl" />
<div className="relative text-center space-y-6 p-8 md:p-12 max-w-4xl">
<h1 className="text-4xl md:text-6xl text-primary">
Your lineup. Our analytics.
<section className="relative overflow-hidden rounded-xl flex justify-center items-center min-h-[480px]">
{/* Radial gradient background glow */}
<div
className="absolute inset-0 rounded-xl"
style={{
background:
"radial-gradient(ellipse 80% 60% at 50% 50%, rgba(59,130,246,0.10) 0%, rgba(239,68,68,0.05) 60%, transparent 100%)",
border: "1px solid rgba(255,255,255,0.06)",
}}
/>
<div className="relative text-center space-y-8 p-10 md:p-16 max-w-4xl">
<h1 className="text-5xl md:text-7xl font-extrabold text-foreground tracking-tight">
Your lineup.{" "}
<span className="text-primary">Our analytics.</span>
<br />
<span className="text-red-600">Their problem.</span>
<span className="text-accent">Their problem.</span>
</h1>
<p className="text-xl md:text-2xl text-muted-foreground">
<p className="text-lg md:text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed">
Stop guessing. Start winning. Our advanced analytics platform helps
coaches optimize batting orders, analyze matchups, and make smarter
decisions backed by data.
Expand All @@ -104,19 +113,19 @@ const Home: React.FC = () => {
<Button
size="lg"
onClick={() => navigate("/lineup")}
className="text-lg px-8 py-6"
className="text-base px-8 py-6 bg-primary hover:bg-primary/90 text-white font-semibold shadow-glow-blue"
>
Start Optimizing
</Button>

<Button
size="lg"
onClick={() => navigate("/how-to-guide")}
className="text-lg px-8 py-6"
className="text-base px-8 py-6 font-semibold"
style={{
border: "1px solid rgba(0, 0, 0, 0.2)",
color: "rgba(0,0,0,0.7)",
backgroundColor: "transparent",
background: "rgba(255,255,255,0.05)",
border: "1px solid rgba(255,255,255,0.12)",
color: "var(--foreground)",
}}
>
Learn How
Expand All @@ -125,42 +134,46 @@ const Home: React.FC = () => {
</div>
</section>

{/* ---------- Features Grid ---------- */}
{/* Displays key platform features in a responsive grid of cards */}
<div className="space-y-2">
<h2 className="text-xl md:text-3xl text-primary text-center">
{/* ---------- Features Section Header ---------- */}
<div className="space-y-3 text-center">
<h2 className="text-3xl md:text-4xl font-bold text-foreground">
Everything You Need to Win
</h2>
<h3 className="text-base text-center text-muted-foreground">
<p className="text-base text-muted-foreground">
Comprehensive tools designed specifically for baseball coaches.
</h3>
</p>
</div>

{/* ---------- Features Grid ---------- */}
<div className="grid md:grid-cols-2 gap-6 max-w-6xl mx-auto">
{features.map((feature, index) => {
const Icon = feature.icon;
const isAccent = index % 2 === 1;
return (
<Card
key={feature.title}
className={index % 2 === 1 ? "border-[var(--accent-red)]/20" : ""}
style={
isAccent
? { boxShadow: "var(--shadow-glow-red)", borderColor: "rgba(239,68,68,0.18)" }
: {}
}
>
<CardHeader>
<div
className={`w-12 h-12 rounded-lg flex items-center justify-center mb-3 ${
index % 2 === 1 ? "bg-red-600/10" : "bg-blue-900/10"
}`}
className="w-12 h-12 rounded-md flex items-center justify-center mb-3"
style={{
background: isAccent
? "rgba(239,68,68,0.12)"
: "rgba(59,130,246,0.12)",
}}
>
<Icon
className={`h-6 w-6 ${
index % 2 === 1 ? "text-red-600" : "text-blue-900"
}`}
className="h-6 w-6"
style={{ color: isAccent ? "#ef4444" : "#3b82f6" }}
/>
</div>
<CardTitle
className={
index % 2 === 1
? "text-[var(--accent-red)]"
: "text-primary"
}
style={{ color: isAccent ? "#ef4444" : "var(--foreground)" }}
>
{feature.title}
</CardTitle>
Expand All @@ -173,21 +186,30 @@ const Home: React.FC = () => {
})}
</div>

{/* ---------- Benefits Grid ---------- */}
{/* Displays our benefits in block */}

<section className="bg-gray-100/50 rounded-lg p-8 max-w-6xl mx-auto">
<h2 className="text-3xl mb-8 text-center text-primary">Key Benefits</h2>
<div className="grid md:grid-cols-3 gap-6">
{benefits.map((benefit, index) => {
{/* ---------- Benefits Section ---------- */}
<section
className="rounded-xl p-10 max-w-6xl mx-auto"
style={{
background: "var(--surface)",
border: "1px solid var(--border)",
}}
>
<h2 className="text-3xl font-bold mb-10 text-center text-foreground">
Key Benefits
</h2>
<div className="grid md:grid-cols-3 gap-8">
{benefits.map((benefit) => {
const Icon = benefit.icon;
return (
<div key={benefit.title} className="text-center space-y-3">
<div className="w-16 h-16 rounded-full bg-blue-900/10 flex items-center justify-center mx-auto">
<Icon className="h-8 w-8 text-blue-900" />
<div key={benefit.title} className="text-center space-y-4">
<div
className="w-16 h-16 rounded-xl flex items-center justify-center mx-auto"
style={{ background: "rgba(59,130,246,0.12)" }}
>
<Icon className="h-8 w-8 text-primary" />
</div>
<h3 className="font-medium">{benefit.title}</h3>
<p className="text-sm text-muted-foreground">
<h3 className="font-semibold text-foreground">{benefit.title}</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
{benefit.description}
</p>
</div>
Expand All @@ -197,21 +219,27 @@ const Home: React.FC = () => {
</section>

{/* ---------- CTA Section ---------- */}
{/* Final call-to-action to encourage signup */}
<section className="relative rounded-2xl flex justify-center items-center min-h-[250px]">
<div className="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 w-[calc(100%-1rem)] max-w-6xl h-[250px] bg-gradient-to-r from-blue-900/10 to-red-600/10 rounded-2xl" />
<div className="relative text-center space-y-6 p-8 md:p-12 max-w-4xl">
<h2 className="text-2xl md:text-4xl text-primary">
<section className="relative rounded-xl flex justify-center items-center min-h-[280px]">
<div
className="absolute inset-0 rounded-xl"
style={{
background:
"radial-gradient(ellipse 80% 70% at 50% 50%, rgba(239,68,68,0.10) 0%, rgba(59,130,246,0.05) 60%, transparent 100%)",
border: "1px solid rgba(255,255,255,0.06)",
}}
/>
<div className="relative text-center space-y-6 p-10 md:p-14 max-w-3xl">
<h2 className="text-3xl md:text-4xl font-bold text-foreground">
Ready to Transform Your Team?
</h2>
<p className="text-lg md:text-xl text-muted-foreground">
<p className="text-lg text-muted-foreground">
Start today and unlock tools that make every decision smarter,
faster, and more confident.
</p>
<Button
size="lg"
onClick={() => navigate("/lineup")}
className="text-lg px-8 py-6 bg-red-600 hover:bg-red-700"
className="text-base px-8 py-6 bg-accent hover:bg-accent/90 text-white font-semibold shadow-glow-red"
>
Start Building Lineups <MoveRight className="ml-2 h-5 w-5" />
</Button>
Expand Down
109 changes: 109 additions & 0 deletions frontend/src/shared/design-tokens.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"meta": {
"name": "Bench Analytics Design System",
"version": "2.0.0",
"description": "Godly-inspired dark UI design tokens: slate-950/900 backgrounds, glassmorphism cards, subtle glow effects, and high-contrast typography."
},
"colors": {
"background": {
"page": { "value": "#020617", "tailwind": "slate-950", "usage": "Main page / body background" },
"surface": { "value": "#0f172a", "tailwind": "slate-900", "usage": "Cards, panels, elevated surfaces" },
"header": { "value": "rgba(2,6,23,0.85)", "usage": "Fixed header glassmorphism background (with backdrop-blur)" },
"overlay": { "value": "rgba(15,23,42,0.85)", "usage": "Glassmorphism card background (with backdrop-blur)" },
"subtle": { "value": "#1e293b", "tailwind": "slate-800", "usage": "Hover states, input backgrounds" }
},
"primary": {
"DEFAULT": { "value": "#3b82f6", "tailwind": "blue-500", "usage": "Primary interactive elements, links" },
"hover": { "value": "#2563eb", "tailwind": "blue-600", "usage": "Primary button hover state" },
"foreground": { "value": "#ffffff", "usage": "Text on primary-colored backgrounds" },
"glow": { "value": "rgba(59,130,246,0.35)", "usage": "Blue glow for box-shadow accent" }
},
"accent": {
"red": { "value": "#ef4444", "tailwind": "red-500", "usage": "Danger, destructive actions, baseball accent" },
"redHover": { "value": "#dc2626", "tailwind": "red-600", "usage": "Red accent hover" },
"redGlow": { "value": "rgba(239,68,68,0.35)", "usage": "Red glow box-shadow" }
},
"text": {
"primary": { "value": "#f8fafc", "tailwind": "slate-50", "usage": "Headings, high-emphasis text" },
"secondary": { "value": "#94a3b8", "tailwind": "slate-400", "usage": "Body text, descriptions, metadata" },
"muted": { "value": "#64748b", "tailwind": "slate-500", "usage": "Placeholder text, disabled states" }
},
"border": {
"subtle": { "value": "rgba(255,255,255,0.08)", "usage": "Default card / panel borders" },
"medium": { "value": "rgba(255,255,255,0.12)", "usage": "Focused inputs, hover card borders" },
"strong": { "value": "rgba(255,255,255,0.20)", "usage": "Dividers, emphasized borders" }
},
"chart": {
"1": { "value": "#3b82f6", "tailwind": "blue-500" },
"2": { "value": "#10b981", "tailwind": "emerald-500" },
"3": { "value": "#f59e0b", "tailwind": "amber-500" },
"4": { "value": "#ef4444", "tailwind": "red-500" },
"5": { "value": "#8b5cf6", "tailwind": "violet-500" }
}
},
"spacing": {
"density": "marketing",
"note": "Generous padding/margins typical of modern SaaS marketing pages.",
"scale": {
"xs": { "value": "0.25rem", "px": "4px" },
"sm": { "value": "0.5rem", "px": "8px" },
"md": { "value": "1rem", "px": "16px" },
"lg": { "value": "1.5rem", "px": "24px" },
"xl": { "value": "2rem", "px": "32px" },
"2xl": { "value": "3rem", "px": "48px" },
"3xl": { "value": "4rem", "px": "64px" }
},
"cardPadding": { "value": "1.5rem", "px": "24px" },
"sectionGap": { "value": "4rem", "px": "64px" },
"containerMax": { "value": "80rem", "px": "1280px" }
},
"borderRadius": {
"note": "Standard rounded corners — not fully circular, not sharp.",
"none": { "value": "0px" },
"sm": { "value": "6px", "usage": "Small badges, tags" },
"md": { "value": "8px", "usage": "Buttons, inputs" },
"lg": { "value": "12px", "usage": "Cards, panels (primary radius)" },
"xl": { "value": "16px", "usage": "Hero sections, large containers" },
"2xl": { "value": "24px", "usage": "Modal overlays" },
"full": { "value": "9999px", "usage": "Pills, avatars" }
},
"effects": {
"glassmorphism": {
"card": {
"background": "rgba(15,23,42,0.80)",
"backdropBlur": "12px",
"border": "1px solid rgba(255,255,255,0.08)",
"boxShadow": "0 4px 6px -1px rgba(0,0,0,0.4), 0 2px 4px -2px rgba(0,0,0,0.4)"
}
},
"boxShadow": {
"sm": "0 1px 2px rgba(0,0,0,0.4)",
"md": "0 4px 6px -1px rgba(0,0,0,0.4), 0 2px 4px -2px rgba(0,0,0,0.4)",
"lg": "0 10px 15px -3px rgba(0,0,0,0.5), 0 4px 6px -4px rgba(0,0,0,0.4)",
"glowBlue": "0 0 20px rgba(59,130,246,0.25), 0 4px 6px -1px rgba(0,0,0,0.4)",
"glowRed": "0 0 20px rgba(239,68,68,0.25), 0 4px 6px -1px rgba(0,0,0,0.4)"
},
"ring": {
"focus": "0 0 0 2px rgba(59,130,246,0.5)"
}
},
"typography": {
"fontFamily": "Inter, system-ui, -apple-system, sans-serif",
"scale": {
"xs": { "size": "0.75rem", "lineHeight": "1rem", "weight": 400 },
"sm": { "size": "0.875rem", "lineHeight": "1.25rem", "weight": 400 },
"base": { "size": "1rem", "lineHeight": "1.5rem", "weight": 400 },
"lg": { "size": "1.125rem", "lineHeight": "1.75rem", "weight": 500 },
"xl": { "size": "1.25rem", "lineHeight": "1.75rem", "weight": 600 },
"2xl": { "size": "1.5rem", "lineHeight": "2rem", "weight": 700 },
"3xl": { "size": "1.875rem", "lineHeight": "2.25rem", "weight": 700 },
"4xl": { "size": "2.25rem", "lineHeight": "2.5rem", "weight": 800 },
"5xl": { "size": "3rem", "lineHeight": "1", "weight": 800 },
"6xl": { "size": "3.75rem", "lineHeight": "1.1", "weight": 900 }
},
"contrastRatio": {
"heading-to-body": "slate-50 (#f8fafc) on slate-950 (#020617) — approx 18:1 contrast",
"body-to-background": "slate-400 (#94a3b8) on slate-950 (#020617) — approx 7:1 contrast"
}
}
}
Loading
Loading