diff --git a/frontend/app/chart/[index]/page.tsx b/frontend/app/chart/[index]/page.tsx index 1a4471a..93d7e93 100644 --- a/frontend/app/chart/[index]/page.tsx +++ b/frontend/app/chart/[index]/page.tsx @@ -1,10 +1,19 @@ +import { notFound } from "next/navigation"; +import { Chart } from "@/components/Chart"; +import type { IndexId } from "@/lib/api"; + type Params = Promise<{ index: string }>; +const ALLOWED: readonly IndexId[] = ["bvol", "evol"] as const; + export default async function ChartPage({ params }: { params: Params }) { const { index } = await params; + if (!ALLOWED.includes(index as IndexId)) { + notFound(); + } return ( -
-

chart — {index} — placeholder

+
+
); } diff --git a/frontend/app/docs/page.tsx b/frontend/app/docs/page.tsx index 3e9a978..7a86690 100644 --- a/frontend/app/docs/page.tsx +++ b/frontend/app/docs/page.tsx @@ -1,7 +1,7 @@ export default function DocsPage() { return (
-

api docs — placeholder

+

api docs — placeholder

); } diff --git a/frontend/app/globals.css b/frontend/app/globals.css index 349718b..5588bd2 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -1,18 +1,78 @@ @import "tailwindcss"; -:root { - --background: #0a0a0a; +@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); +@custom-variant light (&:where([data-theme="light"], [data-theme="light"] *)); + +:root, +[data-theme="dark"] { + --background: #07070a; --foreground: #ededed; + --surface: rgba(255, 255, 255, 0.02); + --surface-2: rgba(255, 255, 255, 0.04); + --border-subtle: rgba(255, 255, 255, 0.06); + --border: rgba(255, 255, 255, 0.1); + --border-strong: rgba(255, 255, 255, 0.18); + --muted: rgba(237, 237, 237, 0.55); + --soft: rgba(237, 237, 237, 0.35); + --soft-2: rgba(237, 237, 237, 0.22); + --up: #4ade80; + --down: #f87171; + --up-soft: rgba(74, 222, 128, 0.12); + --down-soft: rgba(248, 113, 113, 0.12); + --bg-radial-1: rgba(74, 222, 128, 0.06); + --bg-radial-2: rgba(248, 113, 113, 0.05); + --tooltip-bg: rgba(20, 20, 20, 0.95); + --grid: rgba(255, 255, 255, 0.04); +} + +[data-theme="light"] { + --background: #fafafa; + --foreground: #0a0a0c; + --surface: rgba(10, 10, 12, 0.03); + --surface-2: rgba(10, 10, 12, 0.05); + --border-subtle: rgba(10, 10, 12, 0.06); + --border: rgba(10, 10, 12, 0.1); + --border-strong: rgba(10, 10, 12, 0.2); + --muted: rgba(10, 10, 12, 0.65); + --soft: rgba(10, 10, 12, 0.45); + --soft-2: rgba(10, 10, 12, 0.28); + --up: #16a34a; + --down: #dc2626; + --up-soft: rgba(22, 163, 74, 0.1); + --down-soft: rgba(220, 38, 38, 0.1); + --bg-radial-1: rgba(22, 163, 74, 0.05); + --bg-radial-2: rgba(220, 38, 38, 0.04); + --tooltip-bg: rgba(252, 252, 252, 0.98); + --grid: rgba(10, 10, 12, 0.07); } @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); + --color-surface: var(--surface); + --color-surface-2: var(--surface-2); + --color-border-subtle: var(--border-subtle); + --color-border: var(--border); + --color-border-strong: var(--border-strong); + --color-muted: var(--muted); + --color-soft: var(--soft); + --color-soft-2: var(--soft-2); + --color-up: var(--up); + --color-down: var(--down); + --color-up-soft: var(--up-soft); + --color-down-soft: var(--down-soft); } +html, body { background: var(--background); color: var(--foreground); +} + +body { + background-image: radial-gradient(at 20% 0%, var(--bg-radial-1), transparent 50%), + radial-gradient(at 80% 0%, var(--bg-radial-2), transparent 50%); + background-attachment: fixed; font-family: ui-sans-serif, system-ui, @@ -21,4 +81,9 @@ body { Roboto, sans-serif; -webkit-font-smoothing: antialiased; + color-scheme: dark; +} + +[data-theme="light"] body { + color-scheme: light; } diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 1276c0d..019a6c8 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -1,4 +1,5 @@ import type { Metadata } from "next"; +import { ThemeProvider, themeInitScript } from "@/lib/theme"; import "./globals.css"; export const metadata: Metadata = { @@ -12,8 +13,13 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - {children} + + +