feat(theme): apply CYBER STAR design system (purple palette + Megrim/Audiowide/Cinzel/Inter fonts + ambient bg)

This commit is contained in:
iye 2026-05-12 09:30:51 +08:00
parent 8a83815f1c
commit ba5287add8
3 changed files with 370 additions and 85 deletions

View File

@ -1,26 +1,266 @@
@import "tailwindcss"; @import "tailwindcss";
:root { /*
--background: #ffffff; CYBER STAR · 设计令牌Tailwind v4 @theme
--foreground: #171717; 将所有 token 暴露为 Tailwind 工具类
*/
@theme {
/* ── 背景层级(偏紫调深色) ── */
--color-deepest: #08051a;
--color-deep: #0d0a24;
--color-base: #13102e;
--color-surface: #1a1638;
--color-elevated: #221d4a;
--color-card: #1e1840;
/* ── 主调紫 · Royal Violet ── */
--color-purple-100: #ede9fe;
--color-purple-200: #ddd6fe;
--color-purple-300: #c4b5fd;
--color-purple-400: #a78bfa;
--color-purple-500: #8b5cf6;
--color-purple-600: #7c3aed;
--color-purple-700: #6d28d9;
--color-purple-800: #5b21b6;
/* ── 辅助蓝青(仅用于点缀光效) ── */
--color-blue-300: #93b8ff;
--color-blue-500: #2d7fff;
--color-cyan-400: #38d9f5;
/* ── 强调色 ── */
--color-magenta: #d946ef;
--color-pink-400: #f472b6;
--color-pink-500: #ec4899;
--color-gold-400: #fcd34d;
--color-silver: #c4ccd8;
--color-bronze: #cd7f32;
/* ── 字体(变量注入自 next/font ── */
--font-logo: var(--font-megrim), "Cinzel", serif;
--font-display: var(--font-audiowide), "Audiowide", sans-serif;
--font-label: var(--font-cinzel), "Cinzel", serif;
--font-body: var(--font-inter), -apple-system, "Source Han Sans SC",
"PingFang SC", "Microsoft YaHei", sans-serif;
/* ── 自定义动画 ── */
--animate-pulse-glow: pulse-glow 2.4s ease-in-out infinite;
--animate-float: float 3s ease-in-out infinite;
--animate-spin-slow: spin-slow 20s linear infinite;
} }
@theme inline { /*
--color-background: var(--background); Tailwind 化的 CSS 变量复杂值 / 渐变 / 阴影
--color-foreground: var(--foreground); */
--font-sans: var(--font-geist-sans); :root {
--font-mono: var(--font-geist-mono); --grad-hero: radial-gradient(
ellipse at 70% 40%,
#2a1f5c 0%,
#13102e 45%,
#08051a 100%
);
--grad-purple: linear-gradient(
135deg,
#6d28d9 0%,
#8b5cf6 55%,
#a78bfa 100%
);
--grad-purple-deep: linear-gradient(160deg, #5b21b6 0%, #7c3aed 100%);
--grad-violet-glow: radial-gradient(
circle,
rgba(139, 92, 246, 0.4) 0%,
transparent 65%
);
--grad-card: linear-gradient(155deg, #221d4a 0%, #1a1638 100%);
--grad-shine: linear-gradient(
105deg,
transparent 40%,
rgba(255, 255, 255, 0.06) 50%,
transparent 60%
);
--shadow-purple: 0 0 24px rgba(139, 92, 246, 0.5),
0 0 60px rgba(139, 92, 246, 0.18);
--shadow-card: 0 8px 32px rgba(0, 0, 0, 0.65),
inset 0 1px 0 rgba(255, 255, 255, 0.06);
--shadow-glow: 0 0 40px rgba(196, 181, 253, 0.25);
--border-subtle: rgba(255, 255, 255, 0.08);
--border-default: rgba(255, 255, 255, 0.14);
--border-purple: rgba(139, 92, 246, 0.55);
--border-glow: rgba(196, 181, 253, 0.65);
} }
@media (prefers-color-scheme: dark) { /*
:root { 全局基础样式
--background: #0a0a0a; */
--foreground: #ededed; html {
} background: var(--color-deepest);
color: #fff;
font-family: var(--font-body);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
} }
body { body {
background: var(--background); background: var(--color-deepest);
color: var(--foreground); min-height: 100vh;
font-family: Arial, Helvetica, sans-serif; position: relative;
overflow-x: hidden;
}
/* ── 氛围装饰层 1 · 紫雾环境光 ── */
body::before {
content: "";
position: fixed;
inset: 0;
background:
radial-gradient(
ellipse at 20% 10%,
rgba(139, 92, 246, 0.12) 0%,
transparent 40%
),
radial-gradient(
ellipse at 80% 70%,
rgba(217, 70, 239, 0.08) 0%,
transparent 45%
);
pointer-events: none;
z-index: 0;
}
/* ── 氛围装饰层 2 · 星点粒子背景 ── */
body::after {
content: "";
position: fixed;
inset: 0;
background-image:
radial-gradient(1px 1px at 23% 17%, rgba(255, 255, 255, 0.6), transparent),
radial-gradient(1px 1px at 67% 41%, rgba(196, 181, 253, 0.5), transparent),
radial-gradient(1.5px 1.5px at 89% 23%, rgba(255, 255, 255, 0.4), transparent),
radial-gradient(1px 1px at 12% 78%, rgba(196, 181, 253, 0.4), transparent),
radial-gradient(1px 1px at 45% 89%, rgba(255, 255, 255, 0.5), transparent),
radial-gradient(1.5px 1.5px at 78% 11%, rgba(255, 255, 255, 0.3), transparent),
radial-gradient(1px 1px at 33% 53%, rgba(196, 181, 253, 0.35), transparent),
radial-gradient(1px 1px at 91% 88%, rgba(255, 255, 255, 0.4), transparent);
pointer-events: none;
z-index: 0;
}
/* 页面内容须高于装饰层 */
body > * {
position: relative;
z-index: 1;
}
/* ── 选中文字 ── */
::selection {
background: rgba(139, 92, 246, 0.4);
color: #fff;
}
/* ── 自定义滚动条 ── */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background: var(--color-deep);
}
::-webkit-scrollbar-thumb {
background: var(--color-elevated);
border-radius: 5px;
border: 2px solid var(--color-deep);
}
::-webkit-scrollbar-thumb:hover {
background: var(--color-purple-700);
}
/*
动画 keyframes
*/
@keyframes pulse-glow {
0%,
100% {
box-shadow: 0 0 12px rgba(139, 92, 246, 0.45);
}
50% {
box-shadow:
0 0 32px rgba(139, 92, 246, 0.85),
0 0 64px rgba(139, 92, 246, 0.35);
}
}
@keyframes float {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-6px);
}
}
@keyframes spin-slow {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes fade-in-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes shine-sweep {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
/*
工具类 Tailwind 之外的需要特殊渲染的
*/
.glow-text-purple {
text-shadow:
0 0 16px rgba(196, 181, 253, 0.55),
0 0 32px rgba(139, 92, 246, 0.35);
}
.glow-text-cyan {
text-shadow:
0 0 12px rgba(56, 217, 245, 0.5);
}
.bg-grad-hero {
background: var(--grad-hero);
}
.bg-grad-purple {
background: var(--grad-purple);
}
.bg-grad-card {
background: var(--grad-card);
}
.shadow-purple-glow {
box-shadow: var(--shadow-purple);
}
.shadow-card {
box-shadow: var(--shadow-card);
}
.border-purple-glow {
border-color: var(--border-purple);
} }

View File

@ -1,20 +1,44 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google"; import { Megrim, Audiowide, Cinzel, Inter } from "next/font/google";
import "./globals.css"; import "./globals.css";
const geistSans = Geist({ const megrim = Megrim({
variable: "--font-geist-sans", weight: "400",
subsets: ["latin"], subsets: ["latin"],
variable: "--font-megrim",
display: "swap",
}); });
const geistMono = Geist_Mono({ const audiowide = Audiowide({
variable: "--font-geist-mono", weight: "400",
subsets: ["latin"], subsets: ["latin"],
variable: "--font-audiowide",
display: "swap",
});
const cinzel = Cinzel({
weight: ["400", "500", "600", "700"],
subsets: ["latin"],
variable: "--font-cinzel",
display: "swap",
});
const inter = Inter({
subsets: ["latin"],
variable: "--font-inter",
display: "swap",
}); });
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Create Next App", title: "CYBER ✦ STAR · 虚拟偶像 Top12 出道企划",
description: "Generated by create next app", description:
"35 位虚拟偶像候选人,由你投票决出最终出道 Top12。Cyber Star · Virtual Idol Debut Project.",
keywords: ["虚拟偶像", "出道", "投票", "Top12", "Cyber Star", "Virtual Idol"],
openGraph: {
title: "CYBER ✦ STAR",
description: "虚拟偶像 Top12 出道企划",
type: "website",
},
}; };
export default function RootLayout({ export default function RootLayout({
@ -24,10 +48,10 @@ export default function RootLayout({
}>) { }>) {
return ( return (
<html <html
lang="en" lang="zh-CN"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`} className={`${megrim.variable} ${audiowide.variable} ${cinzel.variable} ${inter.variable} h-full antialiased`}
> >
<body className="min-h-full flex flex-col">{children}</body> <body className="min-h-full">{children}</body>
</html> </html>
); );
} }

View File

@ -1,65 +1,86 @@
import Image from "next/image";
export default function Home() { export default function Home() {
return ( return (
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black"> <main className="min-h-screen flex flex-col items-center justify-center px-6 py-16">
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start"> {/* Logo */}
<Image <h1
className="dark:invert" className="font-logo text-7xl sm:text-8xl tracking-[0.5em] uppercase glow-text-purple text-center mb-4"
src="/next.svg" style={{ paddingLeft: "0.5em" }}
alt="Next.js logo" >
width={100} Cyber
height={20} <span className="text-purple-300 mx-3 text-5xl sm:text-6xl align-middle">
priority
/> </span>
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left"> Star
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
To get started, edit the page.tsx file.
</h1> </h1>
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
Looking for a starting point or more instructions? Head over to{" "} {/* Subtitle */}
<a <p className="font-label text-sm tracking-[0.4em] uppercase text-purple-300 mb-2">
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" Virtual Idol Debut Project
className="font-medium text-zinc-950 dark:text-zinc-50" </p>
> <p className="text-white/60 text-sm mb-12">
Templates Top12
</a>{" "} </p>
or the{" "}
<a {/* Status badge */}
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" <div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-purple-500/10 border border-purple-500/30 mb-12">
className="font-medium text-zinc-950 dark:text-zinc-50" <span className="w-2 h-2 rounded-full bg-purple-400 animate-pulse-glow"></span>
> <span className="font-label text-xs tracking-widest text-purple-300 uppercase">
Learning Phase 2 · Theme Ready
</a>{" "} </span>
center. </div>
{/* Theme verification swatches */}
<div className="grid grid-cols-3 sm:grid-cols-6 gap-3 max-w-2xl">
{[
{ name: "purple-300", className: "bg-purple-300" },
{ name: "purple-500", className: "bg-purple-500" },
{ name: "purple-700", className: "bg-purple-700" },
{ name: "magenta", className: "bg-magenta" },
{ name: "pink-400", className: "bg-pink-400" },
{ name: "cyan-400", className: "bg-cyan-400" },
].map((c) => (
<div key={c.name} className="text-center">
<div
className={`${c.className} h-16 rounded-lg border border-white/10`}
/>
<p className="text-[10px] text-white/40 mt-1 font-mono">{c.name}</p>
</div>
))}
</div>
{/* Font verification */}
<div className="mt-12 grid grid-cols-1 sm:grid-cols-2 gap-4 max-w-2xl w-full">
<div className="bg-surface border border-white/10 rounded-xl p-5">
<p className="font-label text-[10px] tracking-widest text-purple-300 uppercase mb-2">
Logo Font · Megrim
</p>
<p className="font-logo text-3xl tracking-widest">Cyber Star</p>
</div>
<div className="bg-surface border border-white/10 rounded-xl p-5">
<p className="font-label text-[10px] tracking-widest text-purple-300 uppercase mb-2">
Display Font · Audiowide
</p>
<p className="font-display text-3xl tracking-wider">VOTE 2026</p>
</div>
<div className="bg-surface border border-white/10 rounded-xl p-5">
<p className="font-label text-[10px] tracking-widest text-purple-300 uppercase mb-2">
Label Font · Cinzel
</p>
<p className="font-label text-xl tracking-widest font-semibold">
DEBUT PROJECT
</p> </p>
</div> </div>
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row"> <div className="bg-surface border border-white/10 rounded-xl p-5">
<a <p className="font-label text-[10px] tracking-widest text-purple-300 uppercase mb-2">
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]" Body Font · Inter
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" </p>
target="_blank" <p className="font-body text-lg"> · Aria</p>
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/>
Deploy Now
</a>
<a
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
</div> </div>
</div>
<p className="mt-16 text-white/40 text-xs font-mono">
Phase 3 Layout + Navigation
</p>
</main> </main>
</div>
); );
} }