UI-UX/docs/design-spec.html
iye d5ed43acbd feat(ui): design overhaul, global login modal, design spec
- nav: center links (首页/排行榜/我的), right-side AuthMenu + RemainingVotesBadge; image logo with responsive sizing
- auth: replace /login route with global LoginModal triggered anywhere; "我的" intercepts unauth users with post-login redirect
- home: full-screen Hero, redesigned Top12 (12 pill cards, top-3 glow), scroll-snap mandatory between Hero/Top12/candidates
- home: candidates section with sticky filter that gains frosted-glass bg when stuck (matches nav)
- filter: simplified tags (全部/舞蹈/声乐/rap/全能型); ArtistCard uniform purple vote button
- ranking/me: remove Top12Bar; me header stacks 编辑资料/退出登录 vertically
- typography: font-logo set to Orbitron; ✦ glyph in CYBER ✦ STAR preserved
- layout: max-w-[1500px] unified across pages
- docs: add design-spec.md + design-spec.html with full visual spec (lucide SVG, zero emoji policy)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 18:59:30 +08:00

1842 lines
80 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CYBER STAR · Design Spec v2.1</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@500;700;900&family=Audiowide&family=Cinzel:wght@400;600&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root {
--deepest: #08051a;
--deep: #0d0a24;
--base: #13102e;
--surface: #1a1638;
--elevated: #221d4a;
--card: #1e1840;
--p100: #ede9fe;
--p200: #ddd6fe;
--p300: #c4b5fd;
--p400: #a78bfa;
--p500: #8b5cf6;
--p600: #7c3aed;
--p700: #6d28d9;
--p800: #5b21b6;
--cyan: #38d9f5;
--blue: #2d7fff;
--magenta: #d946ef;
--pink: #ec4899;
--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-purple-soft: rgba(196, 181, 253, 0.4);
--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-card: linear-gradient(155deg, #221d4a 0%, #1a1638 100%);
--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);
--font-logo: "Orbitron", "Audiowide", sans-serif;
--font-display: "Audiowide", sans-serif;
--font-label: "Cinzel", serif;
--font-body: "Inter", "PingFang SC", "Microsoft YaHei", sans-serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--deepest); }
body {
font-family: var(--font-body);
color: #fff;
line-height: 1.6;
min-height: 100vh;
background: var(--deepest);
position: relative;
overflow-x: hidden;
}
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;
}
a { color: inherit; text-decoration: none; }
/* ─── Inline SVG sizing helper ─── */
.icon { display: inline-flex; align-items: center; justify-content: center; }
.icon svg { width: 100%; height: 100%; display: block; }
.icon-12 { width: 12px; height: 12px; }
.icon-14 { width: 14px; height: 14px; }
.icon-16 { width: 16px; height: 16px; }
.icon-18 { width: 18px; height: 18px; }
.icon-20 { width: 20px; height: 20px; }
.icon-24 { width: 24px; height: 24px; }
.icon-32 { width: 32px; height: 32px; }
/* ─── Layout ─── */
.layout {
display: grid;
grid-template-columns: 240px 1fr;
max-width: 1400px;
margin: 0 auto;
position: relative;
z-index: 1;
}
.sidebar {
position: sticky;
top: 0;
height: 100vh;
padding: 32px 24px;
border-right: 1px solid var(--border-subtle);
overflow-y: auto;
}
.sidebar h2 {
font-family: var(--font-logo);
font-weight: 900;
font-size: 18px;
letter-spacing: 0.15em;
background: linear-gradient(135deg, #c4b5fd 0%, #fff 50%, #a78bfa 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
margin-bottom: 8px;
display: inline-flex;
align-items: center;
gap: 6px;
}
.sidebar .ver {
font-family: var(--font-label);
font-size: 10px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: rgba(255,255,255,0.45);
margin-bottom: 28px;
}
.sidebar nav ul { list-style: none; }
.sidebar nav li { margin-bottom: 4px; }
.sidebar nav a {
display: block;
padding: 8px 12px;
border-radius: 8px;
font-size: 13px;
color: rgba(255,255,255,0.6);
transition: all 0.18s ease;
border-left: 2px solid transparent;
}
.sidebar nav a:hover {
color: var(--p300);
background: rgba(139,92,246,0.06);
border-left-color: var(--p400);
}
.sidebar nav .group-label {
font-family: var(--font-label);
font-size: 10px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(255,255,255,0.3);
padding: 16px 12px 6px;
}
.content { padding: 64px 64px 120px; min-width: 0; }
@media (max-width: 900px) {
.layout { grid-template-columns: 1fr; }
.sidebar { position: static; height: auto; border-right: none; border-bottom: 1px solid var(--border-subtle); }
.content { padding: 40px 24px 80px; }
}
/* ─── Cover ─── */
.cover {
margin-bottom: 80px;
padding: 64px 48px;
border-radius: 24px;
background: var(--grad-hero);
border: 1px solid var(--border-subtle);
position: relative;
overflow: hidden;
}
.cover::before {
content: "";
position: absolute;
top: -100px;
right: -100px;
width: 360px;
height: 360px;
background: radial-gradient(circle, rgba(139,92,246,0.25) 0%, transparent 65%);
pointer-events: none;
}
.cover .eyebrow {
font-family: var(--font-label);
font-size: 11px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--p300);
margin-bottom: 16px;
}
.cover h1 {
font-family: var(--font-logo);
font-weight: 900;
font-size: clamp(40px, 7vw, 88px);
letter-spacing: 0.18em;
line-height: 1;
text-shadow: 0 0 16px rgba(196,181,253,0.55), 0 0 32px rgba(139,92,246,0.35);
margin-bottom: 16px;
display: inline-flex;
align-items: center;
gap: 0.2em;
}
.cover h1 .star-deco { color: var(--p300); display: inline-flex; }
.cover h1 .star-deco svg { width: 0.7em; height: 0.7em; filter: drop-shadow(0 0 12px rgba(196,181,253,0.7)); }
/* CYBER ✦ STAR 字标中的 ✦ 是 emoji 禁令的唯一例外 */
.logo-star {
color: var(--p300);
font-size: 0.7em;
margin: 0 0.15em;
display: inline-block;
filter: drop-shadow(0 0 12px rgba(196,181,253,0.7));
-webkit-text-fill-color: var(--p300);
vertical-align: 0.05em;
}
.cover .sub { font-size: 16px; color: rgba(255,255,255,0.7); max-width: 600px; }
.cover .meta {
margin-top: 24px;
display: flex;
gap: 20px;
flex-wrap: wrap;
font-family: var(--font-label);
font-size: 11px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: rgba(255,255,255,0.5);
}
.cover .meta span { padding: 6px 14px; border: 1px solid var(--border-subtle); border-radius: 999px; }
/* ─── Sections ─── */
section { margin-bottom: 80px; scroll-margin-top: 24px; }
section > .sec-head {
display: flex;
align-items: baseline;
gap: 16px;
margin-bottom: 8px;
}
section > .sec-head .num {
font-family: var(--font-logo);
font-weight: 700;
font-size: 14px;
color: var(--p400);
letter-spacing: 0.1em;
}
section > h2 {
font-family: var(--font-display);
font-size: 28px;
letter-spacing: 0.05em;
margin-bottom: 8px;
}
section > .desc {
font-size: 14px;
color: rgba(255,255,255,0.55);
margin-bottom: 32px;
max-width: 760px;
}
h3 {
font-family: var(--font-display);
font-size: 18px;
letter-spacing: 0.04em;
margin-top: 40px;
margin-bottom: 16px;
color: rgba(255,255,255,0.92);
}
h4 {
font-size: 13px;
font-weight: 600;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--p300);
margin-top: 24px;
margin-bottom: 12px;
}
p { color: rgba(255,255,255,0.7); font-size: 14px; }
p + p { margin-top: 12px; }
ul.bullets { list-style: none; padding: 0; }
ul.bullets li {
padding-left: 22px;
position: relative;
color: rgba(255,255,255,0.75);
font-size: 14px;
margin-bottom: 8px;
}
ul.bullets li .bullet-star {
position: absolute;
left: 0;
top: 4px;
color: var(--p400);
display: inline-flex;
width: 12px;
height: 12px;
}
/* ─── Color swatches ─── */
.swatch-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 14px;
}
.swatch {
border-radius: 12px;
overflow: hidden;
border: 1px solid var(--border-subtle);
background: var(--surface);
transition: transform 0.2s ease;
}
.swatch:hover { transform: translateY(-2px); }
.swatch .chip { height: 88px; display: flex; align-items: flex-end; padding: 12px; }
.swatch .chip .hex {
font-family: var(--font-display);
font-size: 11px;
letter-spacing: 0.1em;
padding: 3px 8px;
background: rgba(0,0,0,0.55);
color: #fff;
border-radius: 999px;
backdrop-filter: blur(8px);
}
.swatch .info { padding: 12px 14px; }
.swatch .info .name { font-size: 13px; color: #fff; margin-bottom: 4px; font-weight: 500; }
.swatch .info .token {
font-family: ui-monospace, "SF Mono", Menlo, monospace;
font-size: 11px;
color: var(--p300);
margin-bottom: 6px;
}
.swatch .info .desc { font-size: 11px; color: rgba(255,255,255,0.45); line-height: 1.5; }
.text-stack { display: grid; gap: 12px; margin-bottom: 24px; }
.text-row {
display: grid;
grid-template-columns: 1fr 200px;
gap: 24px;
align-items: center;
padding: 12px 16px;
background: rgba(255,255,255,0.02);
border-radius: 8px;
border: 1px solid var(--border-subtle);
}
.text-row .sample { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.text-row .meta {
font-family: ui-monospace, monospace;
font-size: 11px;
color: rgba(255,255,255,0.5);
text-align: right;
}
/* ─── Type specimens ─── */
.font-card {
padding: 28px;
background: var(--grad-card);
border: 1px solid var(--border-subtle);
border-radius: 16px;
margin-bottom: 16px;
}
.font-card .label {
font-family: var(--font-label);
font-size: 11px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--p300);
margin-bottom: 12px;
}
.font-card .specimen { font-size: 56px; letter-spacing: 0.12em; line-height: 1; margin-bottom: 16px; color: #fff; }
.font-card .glyphs { font-size: 14px; letter-spacing: 0.08em; color: rgba(255,255,255,0.6); margin-bottom: 12px; }
.font-card .info { font-family: ui-monospace, monospace; font-size: 11px; color: rgba(255,255,255,0.45); }
.font-orbitron { font-family: var(--font-logo); }
.font-audiowide { font-family: var(--font-display); }
.font-cinzel { font-family: var(--font-label); }
.font-inter { font-family: var(--font-body); }
/* ─── Spacing ─── */
.spacing-grid { display: grid; gap: 10px; }
.space-row {
display: grid;
grid-template-columns: 60px 1fr 80px;
gap: 16px;
align-items: center;
padding: 8px 12px;
background: rgba(255,255,255,0.02);
border-radius: 8px;
}
.space-row .num { font-family: var(--font-display); font-size: 14px; color: var(--p300); }
.space-row .bar { height: 16px; background: var(--grad-purple); border-radius: 4px; }
.space-row .px {
font-family: ui-monospace, monospace;
font-size: 12px;
color: rgba(255,255,255,0.5);
text-align: right;
}
/* ─── Demo grid ─── */
.demo-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 16px;
}
.demo-box {
aspect-ratio: 1.4 / 1;
background: var(--card);
border: 1px solid var(--border-default);
display: flex;
align-items: center;
justify-content: center;
color: rgba(255,255,255,0.8);
font-family: ui-monospace, monospace;
font-size: 12px;
position: relative;
flex-direction: column;
gap: 8px;
}
.demo-box .caption {
position: absolute;
bottom: 8px;
left: 50%;
transform: translateX(-50%);
font-size: 10px;
color: rgba(255,255,255,0.45);
white-space: nowrap;
}
/* ─── Buttons ─── */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
font-family: var(--font-display);
font-weight: 400;
cursor: pointer;
border: 0;
transition: all 0.18s ease;
text-transform: uppercase;
color: #fff;
border-radius: 8px;
}
.btn.primary { background: var(--grad-purple); box-shadow: var(--shadow-purple); }
.btn.primary:hover { filter: brightness(1.1); transform: translateY(-1px); }
.btn.outline {
background: transparent;
border: 1px solid var(--border-purple);
color: var(--p300);
}
.btn.outline:hover { background: rgba(139,92,246,0.1); }
.btn.ghost {
background: rgba(255,255,255,0.05);
border: 1px solid var(--border-default);
color: rgba(255,255,255,0.85);
}
.btn.danger { background: var(--pink); box-shadow: 0 0 20px rgba(236,72,153,0.4); }
.btn.sm { height: 32px; padding: 0 14px; font-size: 10px; letter-spacing: 0.15em; }
.btn.md { height: 44px; padding: 0 24px; font-size: 12px; letter-spacing: 0.25em; }
.btn.lg { height: 56px; padding: 0 40px; font-size: 14px; letter-spacing: 0.25em; }
.btn-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin-bottom: 16px; }
/* ─── Preview frame ─── */
.preview {
border: 1px dashed var(--border-default);
border-radius: 16px;
padding: 24px;
background: var(--deepest);
margin-top: 16px;
position: relative;
}
.preview::before {
content: "PREVIEW";
position: absolute;
top: -8px;
left: 16px;
font-family: var(--font-label);
font-size: 9px;
letter-spacing: 0.3em;
color: var(--p400);
background: var(--deepest);
padding: 0 8px;
}
/* ─── Navigation preview ─── */
.nav-preview {
height: 64px;
background: rgba(13,10,36,0.85);
backdrop-filter: blur(12px);
border: 1px solid var(--border-subtle);
border-radius: 12px;
display: flex;
align-items: center;
padding: 0 24px;
gap: 32px;
}
.nav-logo {
font-family: var(--font-logo);
font-weight: 900;
font-size: 18px;
letter-spacing: 0.15em;
background: linear-gradient(135deg, #c4b5fd 0%, #fff 50%, #a78bfa 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
display: inline-flex;
align-items: center;
gap: 6px;
}
.nav-logo-star {
color: var(--p300);
-webkit-text-fill-color: var(--p300);
display: inline-flex;
align-items: center;
}
.nav-link {
font-family: var(--font-display);
font-size: 12px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(255,255,255,0.65);
position: relative;
padding-bottom: 4px;
}
.nav-link.active {
color: var(--p300);
text-shadow: 0 0 16px rgba(196,181,253,0.55);
}
.nav-link.active::after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: -2px;
height: 1px;
background: var(--p400);
box-shadow: 0 0 8px var(--p400);
}
.nav-right { margin-left: auto; display: flex; gap: 12px; align-items: center; }
.icon-btn {
width: 36px;
height: 36px;
border-radius: 50%;
background: rgba(255,255,255,0.04);
border: 1px solid var(--border-default);
display: flex;
align-items: center;
justify-content: center;
color: rgba(255,255,255,0.85);
}
/* ─── Hero preview ─── */
.hero-preview {
position: relative;
height: 380px;
background: var(--grad-hero);
border-radius: 16px;
overflow: hidden;
padding: 24px;
}
.hero-eyebrow {
position: absolute;
top: 24px;
left: 24px;
font-family: var(--font-label);
font-size: 10px;
letter-spacing: 0.4em;
color: rgba(196,181,253,0.9);
text-transform: uppercase;
}
.countdown-pill {
position: absolute;
top: 24px;
right: 24px;
padding: 8px 16px;
border: 1px solid var(--border-purple-soft);
border-radius: 999px;
background: rgba(13,10,36,0.55);
backdrop-filter: blur(8px);
font-size: 12px;
color: #fff;
display: inline-flex;
align-items: center;
gap: 8px;
letter-spacing: 0.05em;
}
.countdown-pill .num { color: var(--p300); font-variant-numeric: tabular-nums; font-family: var(--font-display); }
.hero-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.hero-title {
font-family: var(--font-logo);
font-weight: 900;
font-size: 64px;
letter-spacing: 0.2em;
color: #fff;
text-shadow: 0 0 16px rgba(196,181,253,0.55), 0 0 32px rgba(139,92,246,0.35);
display: inline-flex;
align-items: center;
gap: 0.15em;
}
.hero-title .star-deco { color: var(--p300); display: inline-flex; align-items: center; }
.hero-title .star-deco svg { width: 0.55em; height: 0.55em; filter: drop-shadow(0 0 12px rgba(196,181,253,0.7)); }
.hero-sub { margin-top: 16px; font-size: 16px; color: rgba(255,255,255,0.7); }
.sound-btn {
position: absolute;
bottom: 20px;
right: 20px;
width: 36px;
height: 36px;
border-radius: 50%;
background: rgba(0,0,0,0.55);
backdrop-filter: blur(12px);
border: 1px solid rgba(255,255,255,0.1);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
/* ─── Top12 avatar ─── */
.top12-row { display: flex; gap: 16px; flex-wrap: wrap; }
.top12-item { text-align: center; width: 80px; }
.top12-avatar {
width: 64px;
height: 64px;
border-radius: 50%;
border: 2px solid var(--p500);
box-shadow: 0 0 12px rgba(139,92,246,0.45);
background: linear-gradient(180deg, #2a1f5c 0%, #1a1638 100%);
margin: 0 auto 8px;
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-label);
color: rgba(255,255,255,0.5);
font-size: 10px;
}
.top12-badge {
width: 20px;
height: 20px;
border-radius: 50%;
background: var(--p500);
color: #fff;
font-family: var(--font-display);
font-size: 10px;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 4px;
}
.top12-name { font-size: 12px; color: #fff; margin-bottom: 2px; }
.top12-votes { font-size: 11px; color: var(--p300); font-variant-numeric: tabular-nums; }
/* ─── Artist card ─── */
.card-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-top: 16px;
}
.artist-card {
background: var(--grad-card);
border-radius: 12px;
overflow: hidden;
border: 1px solid var(--border-subtle);
box-shadow: var(--shadow-card);
position: relative;
}
.artist-card.top12 {
border-color: var(--border-purple);
box-shadow: var(--shadow-card), 0 0 24px rgba(139,92,246,0.25);
}
.artist-card .portrait {
aspect-ratio: 4 / 5;
background: linear-gradient(180deg, #2a1f5c 0%, #1a1638 100%);
position: relative;
display: flex;
align-items: flex-end;
justify-content: center;
padding: 16px;
}
.artist-card.candidate .portrait { opacity: 0.78; }
.artist-card .badge {
position: absolute;
top: 8px;
left: 8px;
width: 28px;
height: 28px;
border-radius: 50%;
background: var(--p500);
box-shadow: var(--shadow-purple);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-family: var(--font-display);
font-size: 12px;
}
.artist-card.candidate .badge {
background: var(--elevated);
border: 1px solid var(--border-default);
color: rgba(255,255,255,0.55);
box-shadow: none;
}
.artist-card .ph-text {
font-family: var(--font-label);
font-size: 9px;
letter-spacing: 0.3em;
color: rgba(255,255,255,0.35);
text-transform: uppercase;
}
.artist-card .info {
padding: 12px;
background: rgba(0,0,0,0.4);
border-top: 1px solid var(--border-subtle);
}
.artist-card .no {
font-family: var(--font-display);
font-size: 11px;
color: rgba(255,255,255,0.55);
letter-spacing: 0.1em;
margin-bottom: 2px;
}
.artist-card .name { font-size: 14px; font-weight: 600; color: #fff; margin-bottom: 2px; }
.artist-card .slogan { font-size: 11px; color: rgba(255,255,255,0.55); margin-bottom: 6px; }
.artist-card .votes {
font-family: var(--font-display);
font-size: 12px;
color: var(--p300);
margin-bottom: 10px;
letter-spacing: 0.04em;
display: inline-flex;
align-items: center;
gap: 6px;
}
.artist-card .vote-btn {
width: 100%;
height: 36px;
border-radius: 8px;
background: var(--grad-purple);
color: #fff;
border: 0;
font-family: var(--font-body);
font-weight: 600;
font-size: 13px;
cursor: pointer;
box-shadow: 0 0 12px rgba(139,92,246,0.35);
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
}
/* ─── Filter bar preview ─── */
.filter-preview {
display: flex;
gap: 20px;
align-items: center;
flex-wrap: wrap;
}
.tag-pill {
padding: 6px 12px;
background: transparent;
border: 0;
color: rgba(255,255,255,0.55);
font-size: 13px;
cursor: pointer;
}
.tag-pill.active {
color: var(--p300);
border-bottom: 2px solid var(--p400);
}
.sort-btn {
height: 36px;
padding: 0 14px;
background: rgba(255,255,255,0.04);
border: 1px solid var(--border-default);
border-radius: 8px;
color: rgba(255,255,255,0.75);
font-size: 12px;
display: inline-flex;
align-items: center;
gap: 6px;
}
.search-box {
height: 36px;
width: 220px;
background: var(--surface);
border: 1px solid var(--border-default);
border-radius: 8px;
padding: 0 12px;
display: flex;
align-items: center;
gap: 8px;
color: rgba(255,255,255,0.45);
font-size: 13px;
}
.view-toggle {
display: flex;
height: 36px;
border: 1px solid var(--border-default);
border-radius: 8px;
overflow: hidden;
}
.view-toggle > div {
width: 36px;
display: flex;
align-items: center;
justify-content: center;
}
.view-toggle > .active { background: rgba(139,92,246,0.12); color: var(--p300); }
.view-toggle > .inactive { color: rgba(255,255,255,0.55); }
/* ─── Modal preview ─── */
.modal-shell {
background: rgba(0,0,0,0.75);
padding: 40px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.modal-body {
width: 320px;
background: rgba(34,29,74,0.95);
border: 1px solid var(--border-default);
border-radius: 16px;
padding: 28px;
box-shadow: 0 24px 80px rgba(0,0,0,0.7), 0 0 40px rgba(139,92,246,0.12);
position: relative;
}
.modal-close {
position: absolute;
top: 16px;
right: 16px;
color: rgba(255,255,255,0.55);
cursor: pointer;
}
.modal-avatar {
width: 80px;
height: 80px;
border-radius: 50%;
background: var(--grad-purple);
margin: 0 auto 16px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 16px rgba(139,92,246,0.4);
color: #fff;
font-family: var(--font-display);
}
.modal-title { text-align: center; font-size: 16px; font-weight: 600; margin-bottom: 4px; }
.modal-meta {
text-align: center;
font-family: var(--font-label);
font-size: 10px;
letter-spacing: 0.2em;
color: rgba(255,255,255,0.45);
margin-bottom: 20px;
}
.vote-opts { display: flex; gap: 8px; justify-content: center; margin-bottom: 20px; }
.vote-opt {
width: 48px;
height: 48px;
border-radius: 8px;
background: rgba(26,22,56,1);
border: 1px solid var(--border-default);
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-display);
color: rgba(255,255,255,0.65);
}
.vote-opt.active {
background: rgba(139,92,246,0.12);
border-color: var(--p500);
color: var(--p300);
box-shadow: 0 0 12px rgba(139,92,246,0.3);
}
/* ─── Tables ─── */
table { width: 100%; border-collapse: collapse; margin-top: 12px; margin-bottom: 16px; }
th, td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--border-subtle); font-size: 13px; }
th {
font-family: var(--font-label);
font-size: 11px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--p300);
}
td { color: rgba(255,255,255,0.75); }
td code, p code, li code, .inline-code {
font-family: ui-monospace, monospace;
font-size: 12px;
padding: 2px 6px;
background: rgba(139,92,246,0.12);
border-radius: 4px;
color: var(--p200);
}
/* ─── Callouts ─── */
.callout {
padding: 16px 20px;
border-radius: 8px;
background: rgba(139,92,246,0.08);
border-left: 3px solid var(--p400);
margin: 16px 0;
font-size: 13px;
color: rgba(255,255,255,0.8);
}
.callout.warn { background: rgba(236,72,153,0.08); border-left-color: var(--pink); }
.callout strong { color: #fff; }
/* ─── Animations ─── */
@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); }
}
.anim-demo {
width: 80px;
height: 80px;
border-radius: 50%;
background: var(--grad-purple);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-family: var(--font-display);
font-size: 14px;
}
.anim-pulse { animation: pulse-glow 2.4s ease-in-out infinite; }
.anim-float { animation: float 3s ease-in-out infinite; }
.anim-spin {
width: 80px;
height: 80px;
border-radius: 50%;
border: 2px solid transparent;
border-top-color: var(--p400);
animation: spin-slow 2s linear infinite;
}
/* ─── Icon gallery ─── */
.icon-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 12px;
}
.icon-card {
padding: 20px 14px;
background: var(--surface);
border: 1px solid var(--border-subtle);
border-radius: 12px;
text-align: center;
transition: all 0.2s ease;
}
.icon-card:hover { border-color: var(--border-purple); background: rgba(139,92,246,0.08); }
.icon-card .ico {
width: 32px;
height: 32px;
margin: 0 auto 12px;
color: var(--p300);
}
.icon-card .ico svg { width: 100%; height: 100%; }
.icon-card .name { font-size: 12px; color: #fff; margin-bottom: 2px; }
.icon-card .usage { font-size: 10px; color: rgba(255,255,255,0.45); letter-spacing: 0.05em; }
.footer-preview {
height: 64px;
background: var(--deep);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
color: rgba(255,255,255,0.35);
letter-spacing: 0.05em;
}
</style>
</head>
<body>
<!-- ╔════════════════════════════════════════════════════════════╗ -->
<!-- ║ INLINE SVG ICON DEFS ║ -->
<!-- ║ All icons used in this spec are inline SVG (lucide style). ║ -->
<!-- ║ Zero emoji. Use <svg><use href="#icon-name"/></svg> ║ -->
<!-- ╚════════════════════════════════════════════════════════════╝ -->
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
<defs>
<symbol id="i-star" viewBox="0 0 24 24" fill="currentColor"><path d="M12 1.5 13.6 9 21 10.4 14.9 13.2 16 21 12 17.5 8 21 9.1 13.2 3 10.4 10.4 9 Z"/></symbol>
<symbol id="i-heart" viewBox="0 0 24 24" fill="currentColor"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.29 1.51 4.04 3 5.5l7 7Z"/></symbol>
<symbol id="i-trophy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"/><path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"/><path d="M18 2H6v7a6 6 0 0 0 12 0V2Z"/></symbol>
<symbol id="i-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></symbol>
<symbol id="i-volumex" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><line x1="22" x2="16" y1="9" y2="15"/><line x1="16" x2="22" y1="9" y2="15"/></symbol>
<symbol id="i-volume2" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/></symbol>
<symbol id="i-chevron-right" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></symbol>
<symbol id="i-arrow-right" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></symbol>
<symbol id="i-grid" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="7" height="7" x="3" y="3"/><rect width="7" height="7" x="14" y="3"/><rect width="7" height="7" x="14" y="14"/><rect width="7" height="7" x="3" y="14"/></symbol>
<symbol id="i-list" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" x2="21" y1="6" y2="6"/><line x1="8" x2="21" y1="12" y2="12"/><line x1="8" x2="21" y1="18" y2="18"/><line x1="3" x2="3.01" y1="6" y2="6"/><line x1="3" x2="3.01" y1="12" y2="12"/><line x1="3" x2="3.01" y1="18" y2="18"/></symbol>
<symbol id="i-sort" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21 16-4 4-4-4"/><path d="M17 20V4"/><path d="m3 8 4-4 4 4"/><path d="M7 4v16"/></symbol>
<symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></symbol>
<symbol id="i-sparkles" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></symbol>
<symbol id="i-loader" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" x2="12" y1="2" y2="6"/><line x1="12" x2="12" y1="18" y2="22"/><line x1="4.93" x2="7.76" y1="4.93" y2="7.76"/><line x1="16.24" x2="19.07" y1="16.24" y2="19.07"/><line x1="2" x2="6" y1="12" y2="12"/><line x1="18" x2="22" y1="12" y2="12"/><line x1="4.93" x2="7.76" y1="19.07" y2="16.24"/><line x1="16.24" x2="19.07" y1="7.76" y2="4.93"/></symbol>
<symbol id="i-play" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></symbol>
<symbol id="i-pause" viewBox="0 0 24 24" fill="currentColor"><rect x="14" y="4" width="4" height="16"/><rect x="6" y="4" width="4" height="16"/></symbol>
</defs>
</svg>
<div class="layout">
<!-- ═══════ SIDEBAR ═══════ -->
<aside class="sidebar">
<h2>
CYBER <span class="logo-star"></span> STAR
</h2>
<div class="ver">Design Spec · v2.1</div>
<nav>
<div class="group-label">概览</div>
<ul>
<li><a href="#cover">封面</a></li>
<li><a href="#brand">1. 品牌识别</a></li>
</ul>
<div class="group-label">基础</div>
<ul>
<li><a href="#color">2. 色彩</a></li>
<li><a href="#type">3. 字体</a></li>
<li><a href="#layout">4. 间距 / 布局</a></li>
<li><a href="#radius">5. 圆角 / 阴影</a></li>
<li><a href="#motion">6. 动效</a></li>
</ul>
<div class="group-label">组件</div>
<ul>
<li><a href="#nav">7.1 导航</a></li>
<li><a href="#hero">7.2 Hero</a></li>
<li><a href="#top12">7.3 Top12</a></li>
<li><a href="#filter">7.4 筛选栏</a></li>
<li><a href="#card">7.5 艺人卡片</a></li>
<li><a href="#footer">7.6 Footer</a></li>
<li><a href="#button">7.7 按钮</a></li>
<li><a href="#modal">7.8 弹窗</a></li>
</ul>
<div class="group-label">规则</div>
<ul>
<li><a href="#icon">8. 图标</a></li>
<li><a href="#breakpoint">9. 响应式</a></li>
<li><a href="#uxrules">10. UI/UX 规范</a></li>
<li><a href="#copy">11. 文案约定</a></li>
<li><a href="#tokens">12. Token 映射</a></li>
</ul>
</nav>
</aside>
<!-- ═══════ MAIN ═══════ -->
<main class="content">
<header id="cover" class="cover">
<div class="eyebrow">Top 12 · Virtual Idol Debut Project</div>
<h1>
CYBER <span class="logo-star"></span> STAR
</h1>
<p class="sub">虚拟偶像出道企划官方网站视觉设计规范。本文档定义品牌识别、色彩、字体、组件、动效、可访问性等全部前端视觉资产是设计与开发之间的单一来源Single Source of Truth</p>
<div class="meta">
<span>Version 2.1</span>
<span>2026-05-12</span>
<span>Zero Emoji</span>
<span>WCAG 2.1 AA</span>
</div>
</header>
<div class="callout">
<strong>v2.1 更新(本版):</strong>
① 删除 Hero 内所有按钮(含 Play Debut PV、Debut PV tag
② 倒计时加浅紫色边框胶囊;
③ 卡片投票按钮所有排名统一为紫色实心样式;
④ 弹窗去除顶部 2px 紫线;
⑤ 全规范文档与代码 <strong>禁用 emoji</strong>,所有图标统一 lucide SVG。
</div>
<!-- ─── 1. Brand ─── -->
<section id="brand">
<div class="sec-head"><span class="num">01</span></div>
<h2>Brand Identity · 品牌识别</h2>
<p class="desc">CYBER STAR 的视觉语言聚焦于「赛博 / 暗黑 / 紫色霓虹 / 太空感」。所有设计决策都应强化这种神秘、未来、高级感的氛围。</p>
<h3>Logo 规范</h3>
<table>
<tr><th></th><th>规则</th></tr>
<tr><td>主 Logo</td><td>金属铬质 <code>CYBER STAR</code> + 星形装饰PNG 透明背景)</td></tr>
<tr><td>资源路径</td><td><code>/public/logo.png</code></td></tr>
<tr><td>原始比例</td><td>约 2.7 : 1</td></tr>
<tr><td>最小展示宽度</td><td>120 px</td></tr>
<tr><td>顶栏使用高度</td><td>32 px对应宽度约 86 px</td></tr>
<tr><td>简化版</td><td>仅四角星 SVG + 紫色辉光favicon、极窄场景</td></tr>
</table>
<h3>禁忌项</h3>
<ul class="bullets">
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>不使用扁平色块大面积铺底</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>不使用强烈的彩虹色 / 多色对比</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>不使用阳光、暖色调</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>不使用粗线条 / 卡通风格的图标</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>不使用纯黑 #000 大面积背景</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span><strong>不使用任何 emoji包括心形、播放三角、奖杯等 Unicode 装饰字符)— 唯一例外CYBER ✦ STAR 字标中的 ✦</strong></li>
</ul>
</section>
<!-- ─── 2. Color ─── -->
<section id="color">
<div class="sec-head"><span class="num">02</span></div>
<h2>Color System · 色彩系统</h2>
<p class="desc">背景层级越深越亮一点点以营造空间纵深;主调紫色覆盖 8 级亮度阶梯3-5 档为最常用值。</p>
<h3>背景层级(暗紫调)</h3>
<div class="swatch-grid">
<div class="swatch"><div class="chip" style="background:#08051A"><span class="hex">#08051A</span></div><div class="info"><div class="name">Deepest</div><div class="token">--color-deepest</div><div class="desc">页面最底层</div></div></div>
<div class="swatch"><div class="chip" style="background:#0D0A24"><span class="hex">#0D0A24</span></div><div class="info"><div class="name">Deep</div><div class="token">--color-deep</div><div class="desc">导航 / Footer</div></div></div>
<div class="swatch"><div class="chip" style="background:#13102E"><span class="hex">#13102E</span></div><div class="info"><div class="name">Base</div><div class="token">--color-base</div><div class="desc">主要区块</div></div></div>
<div class="swatch"><div class="chip" style="background:#1A1638"><span class="hex">#1A1638</span></div><div class="info"><div class="name">Surface</div><div class="token">--color-surface</div><div class="desc">卡片 / 输入框</div></div></div>
<div class="swatch"><div class="chip" style="background:#221D4A"><span class="hex">#221D4A</span></div><div class="info"><div class="name">Elevated</div><div class="token">--color-elevated</div><div class="desc">浮层 / 弹窗</div></div></div>
<div class="swatch"><div class="chip" style="background:#1E1840"><span class="hex">#1E1840</span></div><div class="info"><div class="name">Card</div><div class="token">--color-card</div><div class="desc">艺人卡片底</div></div></div>
</div>
<h3>主调紫 · Royal Violet</h3>
<div class="swatch-grid">
<div class="swatch"><div class="chip" style="background:#EDE9FE"><span class="hex" style="background:rgba(0,0,0,0.7)">#EDE9FE</span></div><div class="info"><div class="name">Purple 100</div><div class="token">--color-purple-100</div><div class="desc">极淡紫</div></div></div>
<div class="swatch"><div class="chip" style="background:#DDD6FE"><span class="hex" style="background:rgba(0,0,0,0.7)">#DDD6FE</span></div><div class="info"><div class="name">Purple 200</div><div class="token">--color-purple-200</div><div class="desc">高亮文字</div></div></div>
<div class="swatch"><div class="chip" style="background:#C4B5FD"><span class="hex" style="background:rgba(0,0,0,0.7)">#C4B5FD</span></div><div class="info"><div class="name">Purple 300</div><div class="token">--color-purple-300</div><div class="desc">文字高亮 ★</div></div></div>
<div class="swatch"><div class="chip" style="background:#A78BFA"><span class="hex">#A78BFA</span></div><div class="info"><div class="name">Purple 400</div><div class="token">--color-purple-400</div><div class="desc">边框 / 图标</div></div></div>
<div class="swatch"><div class="chip" style="background:#8B5CF6"><span class="hex">#8B5CF6</span></div><div class="info"><div class="name">Purple 500</div><div class="token">--color-purple-500</div><div class="desc">主品牌色 ★</div></div></div>
<div class="swatch"><div class="chip" style="background:#7C3AED"><span class="hex">#7C3AED</span></div><div class="info"><div class="name">Purple 600</div><div class="token">--color-purple-600</div><div class="desc">按钮 Hover</div></div></div>
<div class="swatch"><div class="chip" style="background:#6D28D9"><span class="hex">#6D28D9</span></div><div class="info"><div class="name">Purple 700</div><div class="token">--color-purple-700</div><div class="desc">按钮 Active</div></div></div>
<div class="swatch"><div class="chip" style="background:#5B21B6"><span class="hex">#5B21B6</span></div><div class="info"><div class="name">Purple 800</div><div class="token">--color-purple-800</div><div class="desc">渐变深端</div></div></div>
</div>
<h3>文字颜色(按透明度)</h3>
<div class="text-stack">
<div class="text-row"><div class="sample" style="color:#fff; font-size:18px;">主标题 · Heading Sample Text</div><div class="meta">#FFFFFF · 100%</div></div>
<div class="text-row"><div class="sample" style="color:rgba(255,255,255,0.85); font-size:16px;">正文阅读 · Body Sample Text</div><div class="meta">rgba(255,255,255,0.85)</div></div>
<div class="text-row"><div class="sample" style="color:rgba(255,255,255,0.65); font-size:14px;">次要说明 · Caption Sample</div><div class="meta">rgba(255,255,255,0.65)</div></div>
<div class="text-row"><div class="sample" style="color:rgba(255,255,255,0.45); font-size:13px;">弱化元数据 · Meta Sample</div><div class="meta">rgba(255,255,255,0.45)</div></div>
<div class="text-row"><div class="sample" style="color:rgba(255,255,255,0.25); font-size:13px;">几近隐藏 · Disabled Sample</div><div class="meta">rgba(255,255,255,0.25)</div></div>
<div class="text-row"><div class="sample" style="color:var(--p300); font-size:14px; display: inline-flex; align-items: center; gap: 6px;"><span class="icon icon-12"><svg><use href="#i-heart"/></svg></span>紫色强调 · 12.6W 票</div><div class="meta">var(--color-purple-300)</div></div>
<div class="text-row"><div class="sample" style="color:var(--pink); font-size:14px;">错误提示 · Error Sample</div><div class="meta">var(--color-pink-500)</div></div>
</div>
<h3>边框 · 渐变</h3>
<div class="demo-grid">
<div class="demo-box" style="border-color: rgba(255,255,255,0.08)"><span>Subtle</span><span class="caption">--border-subtle</span></div>
<div class="demo-box" style="border-color: rgba(255,255,255,0.14)"><span>Default</span><span class="caption">--border-default</span></div>
<div class="demo-box" style="border-color: rgba(139,92,246,0.55)"><span>Purple</span><span class="caption">--border-purple</span></div>
<div class="demo-box" style="border-color: rgba(196,181,253,0.4)"><span>Purple Soft</span><span class="caption">倒计时胶囊用</span></div>
<div class="demo-box" style="background: var(--grad-hero); border: none;"><span>Hero</span><span class="caption">--grad-hero</span></div>
<div class="demo-box" style="background: var(--grad-purple); border: none;"><span>Purple</span><span class="caption">--grad-purple</span></div>
<div class="demo-box" style="background: var(--grad-card); border: none;"><span>Card</span><span class="caption">--grad-card</span></div>
</div>
</section>
<!-- ─── 3. Type ─── -->
<section id="type">
<div class="sec-head"><span class="num">03</span></div>
<h2>Typography · 字体系统</h2>
<p class="desc">4 套字体各司其职。中文严格使用 Inter Fallback 链中的中文字体,不尝试用 Display 字体显示中文。</p>
<div class="font-card">
<div class="label">Font Logo · 标题专用</div>
<div class="specimen font-orbitron" style="font-weight: 900">CYBER STAR</div>
<div class="glyphs font-orbitron">ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789</div>
<div class="info">Orbitron · Weight 500 / 700 / 900 · var(--font-logo)</div>
</div>
<div class="font-card">
<div class="label">Font Display · 按钮 / 副标题</div>
<div class="specimen font-audiowide">VOTE NOW</div>
<div class="glyphs font-audiowide">ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789</div>
<div class="info">Audiowide · Weight 400 · var(--font-display)</div>
</div>
<div class="font-card">
<div class="label">Font Label · 英文小写大写标签</div>
<div class="specimen font-cinzel" style="font-size:36px; letter-spacing: 0.35em;">CANDIDATES</div>
<div class="glyphs font-cinzel">ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789</div>
<div class="info">Cinzel · Weight 400 / 600 · var(--font-label)</div>
</div>
<div class="font-card">
<div class="label">Font Body · 中英文正文</div>
<div class="specimen font-inter" style="font-size:32px; letter-spacing: normal;">虚拟偶像 Top12 出道企划 Aa 123</div>
<div class="glyphs font-inter">中文 + Inter 西文。所有中文一律用此族,不强制 uppercase。</div>
<div class="info">Inter · Weight 400-700 · var(--font-body)</div>
</div>
<h3>字号阶梯</h3>
<table>
<tr><th>用途</th><th>桌面</th><th>移动</th><th>Tracking</th></tr>
<tr><td>Hero 主标题 H1</td><td>clamp(64, 7vw, 96)px</td><td>48px</td><td>0.35em</td></tr>
<tr><td>区块标题 H2</td><td>18px</td><td>16px</td><td>0.2em</td></tr>
<tr><td>卡片标题</td><td>14px</td><td>13px</td><td>normal</td></tr>
<tr><td>正文</td><td>14px</td><td>13px</td><td>normal</td></tr>
<tr><td>标签 / Eyebrow (uppercase)</td><td>11px</td><td>10px</td><td>0.3-0.4em</td></tr>
<tr><td>票数 / 排名(数字)</td><td colspan="2"><code>tabular-nums</code></td><td>normal</td></tr>
</table>
</section>
<!-- ─── 4. Layout ─── -->
<section id="layout">
<div class="sec-head"><span class="num">04</span></div>
<h2>Spacing & Layout · 间距与布局</h2>
<p class="desc">基础栅格 4px容器最大宽度 1280px。</p>
<h3>间距阶梯</h3>
<div class="spacing-grid">
<div class="space-row"><span class="num">space-1</span><div class="bar" style="width:4px;"></div><span class="px">4px</span></div>
<div class="space-row"><span class="num">space-2</span><div class="bar" style="width:8px;"></div><span class="px">8px</span></div>
<div class="space-row"><span class="num">space-3</span><div class="bar" style="width:12px;"></div><span class="px">12px</span></div>
<div class="space-row"><span class="num">space-4</span><div class="bar" style="width:16px;"></div><span class="px">16px</span></div>
<div class="space-row"><span class="num">space-5</span><div class="bar" style="width:20px;"></div><span class="px">20px</span></div>
<div class="space-row"><span class="num">space-6</span><div class="bar" style="width:24px;"></div><span class="px">24px</span></div>
<div class="space-row"><span class="num">space-8</span><div class="bar" style="width:32px;"></div><span class="px">32px</span></div>
<div class="space-row"><span class="num">space-10</span><div class="bar" style="width:40px;"></div><span class="px">40px</span></div>
<div class="space-row"><span class="num">space-16</span><div class="bar" style="width:64px;"></div><span class="px">64px</span></div>
</div>
<h3>艺人卡片网格</h3>
<table>
<tr><th>断点</th><th>列数</th><th>Gap</th></tr>
<tr><td>&lt; 640px</td><td>2</td><td>12px</td></tr>
<tr><td>≥ 640px</td><td>3</td><td>16px</td></tr>
<tr><td>≥ 768px</td><td>4</td><td>16px</td></tr>
<tr><td>≥ 1024px</td><td><strong>5</strong></td><td>16px</td></tr>
</table>
</section>
<!-- ─── 5. Radius/Shadow ─── -->
<section id="radius">
<div class="sec-head"><span class="num">05</span></div>
<h2>Radius · Shadow · Glow</h2>
<h3>圆角</h3>
<div class="demo-grid">
<div class="demo-box" style="border-radius: 0;"><span>0</span><span class="caption">直角,不用</span></div>
<div class="demo-box" style="border-radius: 8px;"><span>8px</span><span class="caption">输入框 / 按钮</span></div>
<div class="demo-box" style="border-radius: 12px;"><span>12px</span><span class="caption">卡片 / 容器</span></div>
<div class="demo-box" style="border-radius: 16px;"><span>16px</span><span class="caption">大卡片</span></div>
<div class="demo-box" style="border-radius: 20px;"><span>20px</span><span class="caption">弹窗 / Hero</span></div>
<div class="demo-box" style="border-radius: 9999px;"><span>9999</span><span class="caption">胶囊 / 徽章</span></div>
</div>
<h3>阴影 & 辉光</h3>
<div class="demo-grid">
<div class="demo-box" style="box-shadow: var(--shadow-card); border-color: var(--border-subtle);"><span>Card</span><span class="caption">shadow-card</span></div>
<div class="demo-box" style="box-shadow: var(--shadow-purple); border-color: var(--border-purple);"><span>Purple Glow</span><span class="caption">shadow-purple</span></div>
<div class="demo-box" style="box-shadow: var(--shadow-glow); border-color: var(--border-subtle);"><span>Soft Glow</span><span class="caption">shadow-glow</span></div>
</div>
<h3>文字辉光</h3>
<div class="preview" style="text-align: center; padding: 40px;">
<div style="font-family: var(--font-logo); font-weight: 900; font-size: 48px; letter-spacing: 0.2em; color: #fff; text-shadow: 0 0 16px rgba(196,181,253,0.55), 0 0 32px rgba(139,92,246,0.35);">CYBER STAR</div>
<div style="margin-top: 8px; font-family: var(--font-label); font-size: 10px; letter-spacing: 0.3em; color: rgba(255,255,255,0.45);">.glow-text-purple</div>
</div>
</section>
<!-- ─── 6. Motion ─── -->
<section id="motion">
<div class="sec-head"><span class="num">06</span></div>
<h2>Motion · 动效规范</h2>
<p class="desc">动效短促克制强调反馈即时性。Hover &lt; 200ms模态进入 ~280ms。</p>
<table>
<tr><th>名称</th><th>时长</th><th>Easing</th><th>用法</th></tr>
<tr><td>Hover 微抬升</td><td>200ms</td><td>ease-out</td><td>卡片 translateY(-2px)</td></tr>
<tr><td>按钮过渡</td><td>180ms</td><td>ease-out</td><td>颜色 / 阴影变化</td></tr>
<tr><td>弹窗进入</td><td>280ms</td><td>cubic-bezier(0.22, 1, 0.36, 1)</td><td>scale 0.94→1 + fade</td></tr>
<tr><td>弹窗退出</td><td>200ms</td><td>ease-in</td><td>scale 1→0.96 + fade</td></tr>
<tr><td>pulse-glow</td><td>2.4s infinite</td><td>ease-in-out</td><td>VOTE 按钮 / 当前排名</td></tr>
<tr><td>float</td><td>3s infinite</td><td>ease-in-out</td><td>滚动提示</td></tr>
<tr><td>spin-slow</td><td>20s infinite</td><td>linear</td><td>Hero 装饰光环</td></tr>
</table>
<h3>动效演示</h3>
<div style="display: flex; gap: 40px; padding: 32px; background: var(--surface); border-radius: 12px; align-items: center; flex-wrap: wrap;">
<div style="text-align: center;">
<div class="anim-demo anim-pulse">VOTE</div>
<div style="margin-top: 12px; font-size: 11px; color: rgba(255,255,255,0.55); letter-spacing: 0.1em;">pulse-glow</div>
</div>
<div style="text-align: center;">
<div class="anim-demo anim-float"><span class="icon icon-24" style="color:#fff;"><svg><use href="#i-arrow-right"/></svg></span></div>
<div style="margin-top: 12px; font-size: 11px; color: rgba(255,255,255,0.55); letter-spacing: 0.1em;">float</div>
</div>
<div style="text-align: center;">
<div class="anim-spin"></div>
<div style="margin-top: 12px; font-size: 11px; color: rgba(255,255,255,0.55); letter-spacing: 0.1em;">spin-slow</div>
</div>
</div>
</section>
<!-- ─── 7.1 Nav ─── -->
<section id="nav">
<div class="sec-head"><span class="num">07.1</span></div>
<h2>Navigation · 导航栏</h2>
<p class="desc">高度 64px紫色透明黑背景 + 毛玻璃sticky 顶部。</p>
<div class="preview">
<div class="nav-preview">
<div class="nav-logo">
CYBER <span class="logo-star"></span> STAR
</div>
<a class="nav-link active">首页</a>
<a class="nav-link">排行榜</a>
<div class="nav-right">
<div class="icon-btn"><span class="icon icon-16"><svg><use href="#i-search"/></svg></span></div>
<a class="btn outline sm">登录 / 注册</a>
</div>
</div>
</div>
<table>
<tr><th>属性</th><th></th></tr>
<tr><td>高度</td><td>64px</td></tr>
<tr><td>背景</td><td>rgba(13,10,36,0.85) + backdrop-blur(xl)</td></tr>
<tr><td>底边</td><td>1px solid rgba(255,255,255,0.08)</td></tr>
<tr><td>位置</td><td>sticky top-0, z-50</td></tr>
<tr><td>Logo 高度</td><td>32px</td></tr>
<tr><td>搜索图标</td><td>lucide <code>Search</code> SVG · 16px</td></tr>
<tr><td>导航项字体</td><td>font-display, 12px, tracking-[0.25em], uppercase</td></tr>
<tr><td>激活态</td><td>--color-purple-300 + 文字辉光 + 底部 1px 紫线</td></tr>
</table>
<div class="callout">倒计时 <strong>不放在导航栏</strong>,保留在 Hero 内(设计师明确要求)。</div>
</section>
<!-- ─── 7.2 Hero ─── -->
<section id="hero">
<div class="sec-head"><span class="num">07.2</span></div>
<h2>Hero Section · Hero 区</h2>
<p class="desc">全屏视频背景(自动播放、循环、默认静音)。<strong style="color: var(--p300);">Hero 内不放置任何按钮</strong>,仅倒计时(右上)与声音切换(右下)。</p>
<div class="preview" style="padding: 0; overflow: hidden;">
<div class="hero-preview">
<div class="hero-eyebrow">TOP 12 · VIRTUAL IDOL DEBUT PROJECT</div>
<div class="countdown-pill">
<span>距离投票结束</span>
<span class="num">12天 03:24:16</span>
</div>
<div class="hero-center">
<div class="hero-title">
CYBER <span class="logo-star"></span> STAR
</div>
<div class="hero-sub">虚拟偶像出道企划</div>
</div>
<div class="sound-btn">
<span class="icon icon-14"><svg><use href="#i-volumex"/></svg></span>
</div>
</div>
</div>
<table>
<tr><th>属性</th><th></th></tr>
<tr><td>高度</td><td>70vhmin 480px / max 720px</td></tr>
<tr><td>圆角</td><td>20px</td></tr>
<tr><td>背景</td><td>全屏视频 object-cover + 半透明黑色蒙层</td></tr>
<tr><td>视频行为</td><td>autoPlay loop muted playsInline</td></tr>
<tr><td><strong style="color:var(--pink);">禁止在 Hero 内放置按钮</strong></td><td>删除 Play Debut PV、删除 Debut PV 自动播放 tag</td></tr>
<tr><td>倒计时位置</td><td>右上角,距边 24px</td></tr>
<tr><td>倒计时容器</td><td>padding 8×16 + <strong>1px solid rgba(196,181,253,0.4) 浅紫边框</strong> + rounded-full + rgba(13,10,36,0.55) + backdrop-blur</td></tr>
<tr><td>倒计时文字</td><td>12-13px 白字 + 紫色高亮数字 + tabular-nums</td></tr>
<tr><td>声音按钮</td><td>右下角36×36 圆形毛玻璃lucide <code>VolumeX</code>/<code>Volume2</code></td></tr>
<tr><td>视频缺失降级</td><td>--grad-hero 渐变</td></tr>
</table>
</section>
<!-- ─── 7.3 Top12 ─── -->
<section id="top12">
<div class="sec-head"><span class="num">07.3</span></div>
<h2>Top 12 出道位</h2>
<p class="desc">圆形头像横排,独立紫色序号圆 + 中文名 + 票数,统一紫色样式,不分 1-3 / 4-12。</p>
<div class="preview">
<div style="display: flex; justify-content: space-between; margin-bottom: 16px; align-items: center;">
<div style="font-family: var(--font-display); font-size: 16px; letter-spacing: 0.2em; color: #fff; display: inline-flex; align-items: center; gap: 8px;">
<span class="icon icon-18" style="color: var(--p300);"><svg><use href="#i-trophy"/></svg></span>
实时 Top12 出道位
</div>
<a style="font-family: var(--font-label); font-size: 11px; letter-spacing: 0.2em; color: var(--p300); text-transform: uppercase; display: inline-flex; align-items: center; gap: 4px;">
查看完整榜单
<span class="icon icon-14"><svg><use href="#i-chevron-right"/></svg></span>
</a>
</div>
<div style="background: rgba(13,10,36,0.95); border: 1px solid var(--border-subtle); border-radius: 12px; padding: 16px;">
<div class="top12-row">
<div class="top12-item"><div class="top12-avatar">A</div><div class="top12-badge">1</div><div class="top12-name">艺人 A</div><div class="top12-votes">12.6W 票</div></div>
<div class="top12-item"><div class="top12-avatar">B</div><div class="top12-badge">2</div><div class="top12-name">艺人 B</div><div class="top12-votes">11.8W 票</div></div>
<div class="top12-item"><div class="top12-avatar">C</div><div class="top12-badge">3</div><div class="top12-name">艺人 C</div><div class="top12-votes">10.5W 票</div></div>
<div class="top12-item"><div class="top12-avatar">D</div><div class="top12-badge">4</div><div class="top12-name">艺人 D</div><div class="top12-votes">9.2W 票</div></div>
<div class="top12-item"><div class="top12-avatar">E</div><div class="top12-badge">5</div><div class="top12-name">艺人 E</div><div class="top12-votes">8.7W 票</div></div>
<div class="top12-item"><div class="top12-avatar">F</div><div class="top12-badge">6</div><div class="top12-name">艺人 F</div><div class="top12-votes">7.9W 票</div></div>
</div>
</div>
</div>
<div class="callout warn"><strong>禁止</strong>添加 VOTE NOW 侧栏面板。当前实现中的 <code>VotePanel</code> 须删除。</div>
</section>
<!-- ─── 7.4 Filter ─── -->
<section id="filter">
<div class="sec-head"><span class="num">07.4</span></div>
<h2>Filter Bar · 筛选 + 搜索栏</h2>
<div class="preview">
<div class="filter-preview">
<div style="display: flex; gap: 4px;">
<button class="tag-pill active">全部</button>
<button class="tag-pill">舞蹈担当</button>
<button class="tag-pill">声乐担当</button>
<button class="tag-pill">rap担当</button>
<button class="tag-pill">全能型</button>
</div>
<div style="margin-left: auto; display: flex; gap: 12px; align-items: center;">
<button class="sort-btn">
<span class="icon icon-14"><svg><use href="#i-sort"/></svg></span>
实时排名
</button>
<div class="search-box">
<span class="icon icon-14"><svg><use href="#i-search"/></svg></span>
搜索艺人
</div>
<div class="view-toggle">
<div class="active"><span class="icon icon-14"><svg><use href="#i-grid"/></svg></span></div>
<div class="inactive"><span class="icon icon-14"><svg><use href="#i-list"/></svg></span></div>
</div>
</div>
</div>
</div>
<table>
<tr><th>元素</th><th>图标</th></tr>
<tr><td>排序触发</td><td>lucide <code>ArrowUpDown</code></td></tr>
<tr><td>搜索框前缀</td><td>lucide <code>Search</code></td></tr>
<tr><td>网格视图</td><td>lucide <code>LayoutGrid</code></td></tr>
<tr><td>列表视图</td><td>lucide <code>List</code></td></tr>
</table>
</section>
<!-- ─── 7.5 Artist Card ─── -->
<section id="card">
<div class="sec-head"><span class="num">07.5</span></div>
<h2>Artist Card · 艺人卡片</h2>
<p class="desc"><strong style="color: var(--p300);">所有 35 张卡片的投票按钮完全相同</strong>。Top12 与候选区只在「立绘明度 + 边框 + 排名徽章」3 处差异化。</p>
<h3>Top 12 出道位卡片</h3>
<div class="card-row">
<div class="artist-card top12">
<div class="portrait">
<div class="badge">1</div>
<div class="ph-text">Portrait Placeholder</div>
</div>
<div class="info">
<div class="no">No.001</div>
<div class="name">艺人 A</div>
<div class="slogan">樱花校园系</div>
<div class="votes">
<span class="icon icon-12"><svg><use href="#i-heart"/></svg></span>
12.5W 票
</div>
<button class="vote-btn">投票</button>
</div>
</div>
<div class="artist-card top12">
<div class="portrait">
<div class="badge">2</div>
<div class="ph-text">Portrait Placeholder</div>
</div>
<div class="info">
<div class="no">No.002</div>
<div class="name">艺人 B</div>
<div class="slogan">古风国风系</div>
<div class="votes">
<span class="icon icon-12"><svg><use href="#i-heart"/></svg></span>
11.8W 票
</div>
<button class="vote-btn">投票</button>
</div>
</div>
</div>
<h3>13+ 候选区卡片(仅立绘弱化 + 边框 + 徽章变化)</h3>
<div class="card-row">
<div class="artist-card candidate">
<div class="portrait">
<div class="badge">13</div>
<div class="ph-text">Portrait Placeholder</div>
</div>
<div class="info">
<div class="no">No.013</div>
<div class="name">艺人 M</div>
<div class="slogan">活力少女</div>
<div class="votes" style="color: rgba(255,255,255,0.55);">
<span class="icon icon-12"><svg><use href="#i-heart"/></svg></span>
4.8W 票
</div>
<button class="vote-btn">投票</button>
</div>
</div>
<div class="artist-card candidate">
<div class="portrait">
<div class="badge">14</div>
<div class="ph-text">Portrait Placeholder</div>
</div>
<div class="info">
<div class="no">No.014</div>
<div class="name">艺人 N</div>
<div class="slogan">冷艳风</div>
<div class="votes" style="color: rgba(255,255,255,0.55);">
<span class="icon icon-12"><svg><use href="#i-heart"/></svg></span>
4.3W 票
</div>
<button class="vote-btn">投票</button>
</div>
</div>
</div>
<h3>差异化对比表</h3>
<table>
<tr><th>元素</th><th>Top 1-12</th><th>13+ 候选区</th></tr>
<tr><td>立绘 opacity</td><td>1鲜艳</td><td>0.78(轻度暗化)</td></tr>
<tr><td>卡片边框</td><td>--border-purple 紫边</td><td>14% 白边框</td></tr>
<tr><td>卡片辉光</td><td>--shadow-purple 紫色辉光</td><td>无辉光</td></tr>
<tr><td>排名徽章</td><td>紫色实心圆 + 紫色辉光</td><td>--elevated 底 + 55% 白字</td></tr>
<tr><td><strong>投票按钮</strong></td><td colspan="2" style="text-align:center; color: var(--p300);"><strong>完全相同:紫色实心 + 白字「投票」</strong></td></tr>
<tr><td>票数颜色</td><td>--color-purple-300</td><td>55% 白色</td></tr>
<tr><td>组件结构</td><td colspan="2" style="text-align:center;">100% 一致,仅 className 差异</td></tr>
</table>
</section>
<!-- ─── 7.6 Footer ─── -->
<section id="footer">
<div class="sec-head"><span class="num">07.6</span></div>
<h2>Footer</h2>
<div class="preview">
<div class="footer-preview">© 2026 CYBER STAR · All Rights Reserved</div>
</div>
</section>
<!-- ─── 7.7 Buttons ─── -->
<section id="button">
<div class="sec-head"><span class="num">07.7</span></div>
<h2>Buttons · 按钮</h2>
<h3>Variants</h3>
<div class="btn-row">
<button class="btn primary md">PRIMARY</button>
<button class="btn outline md">OUTLINE</button>
<button class="btn ghost md">GHOST</button>
<button class="btn danger md">DANGER</button>
</div>
<h3>Sizes</h3>
<div class="btn-row">
<button class="btn primary sm">SMALL</button>
<button class="btn primary md">MEDIUM</button>
<button class="btn primary lg">LARGE</button>
</div>
<h3>带图标按钮lucide SVG</h3>
<div class="btn-row">
<button class="btn primary md">
<span class="icon icon-14"><svg><use href="#i-heart"/></svg></span>
确认投票
</button>
<button class="btn outline md">
<span class="icon icon-14"><svg><use href="#i-search"/></svg></span>
搜索艺人
</button>
<button class="btn ghost md">
<span class="icon icon-14"><svg><use href="#i-x"/></svg></span>
关闭
</button>
</div>
<table>
<tr><th>尺寸</th><th>高度</th><th>Padding-X</th><th>字号</th><th>用途</th></tr>
<tr><td>sm</td><td>32px</td><td>14px</td><td>10px / 0.15em</td><td>次要按钮、Tag 操作</td></tr>
<tr><td>md</td><td>44px</td><td>24px</td><td>12px / 0.25em</td><td>默认尺寸 ★</td></tr>
<tr><td>lg</td><td>56px</td><td>40px</td><td>14px / 0.25em</td><td>Hero CTA、主操作</td></tr>
</table>
</section>
<!-- ─── 7.8 Modal ─── -->
<section id="modal">
<div class="sec-head"><span class="num">07.8</span></div>
<h2>Modal · 弹窗</h2>
<p class="desc"><strong style="color: var(--p300);">已去除顶部 2px 紫色横条</strong>,保持容器干净。关闭按钮使用 lucide <code>X</code> SVG。</p>
<div class="preview" style="padding: 32px;">
<div class="modal-shell">
<div class="modal-body">
<span class="modal-close icon icon-18"><svg><use href="#i-x"/></svg></span>
<div class="modal-avatar">A</div>
<div class="modal-title">为 艺人 A 投票</div>
<div class="modal-meta">NO.001 · CURRENT RANK #1</div>
<div class="vote-opts">
<div class="vote-opt">1</div>
<div class="vote-opt active">3</div>
<div class="vote-opt">5</div>
<div class="vote-opt" style="font-size: 11px;">ALL</div>
</div>
<button class="btn primary md" style="width: 100%; font-family: var(--font-body); text-transform: none; letter-spacing: 0.05em;">
<span class="icon icon-14"><svg><use href="#i-heart"/></svg></span>
确认投出 3 票
</button>
</div>
</div>
</div>
<table>
<tr><th>属性</th><th></th></tr>
<tr><td>遮罩</td><td>rgba(0,0,0,0.75) + backdrop-blur(md)</td></tr>
<tr><td>容器</td><td>--elevated 95% + --border-default + rounded-2xl</td></tr>
<tr><td>阴影</td><td>0 24px 80px black/0.7, 0 0 40px purple/0.12</td></tr>
<tr><td><strong style="color: var(--pink);">顶部光条</strong></td><td><strong>已删除</strong>(不要 2px 紫色横条)</td></tr>
<tr><td>关闭按钮</td><td>右上角 18px lucide <code>X</code> · 55% 白色</td></tr>
<tr><td>居中</td><td>position:fixed, inset:0, flex center, z-100</td></tr>
</table>
</section>
<!-- ─── 8. Icons ─── -->
<section id="icon">
<div class="sec-head"><span class="num">08</span></div>
<h2>Icons · 图标系统</h2>
<div class="callout warn">
<strong>铁律:</strong>禁止使用任何 emoji奖杯、心形、放大镜、喇叭、播放三角、箭头等所有彩色 / Unicode 装饰字符)。所有图标统一使用 <code>lucide-react</code> SVGstroke 宽度 1.5-2无 fill 例外(如 Heart 用 fill="currentColor")。<br><br><strong style="color: var(--p300);">唯一例外:</strong>品牌字标 <code>CYBER ✦ STAR</code> 中间的 <code></code>U+2726 BLACK FOUR POINTED STAR保留原字符配紫色辉光。
</div>
<h3>项目使用的 lucide 图标清单</h3>
<div class="icon-gallery">
<div class="icon-card">
<div class="ico"><svg><use href="#i-heart"/></svg></div>
<div class="name">Heart</div>
<div class="usage">票数前缀</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-trophy"/></svg></div>
<div class="name">Trophy</div>
<div class="usage">Top12 标题</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-search"/></svg></div>
<div class="name">Search</div>
<div class="usage">搜索图标</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-volumex"/></svg></div>
<div class="name">VolumeX</div>
<div class="usage">静音状态</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-volume2"/></svg></div>
<div class="name">Volume2</div>
<div class="usage">有声状态</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-chevron-right"/></svg></div>
<div class="name">ChevronRight</div>
<div class="usage">查看更多</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-arrow-right"/></svg></div>
<div class="name">ArrowRight</div>
<div class="usage">主跳转</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-grid"/></svg></div>
<div class="name">LayoutGrid</div>
<div class="usage">网格视图</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-list"/></svg></div>
<div class="name">List</div>
<div class="usage">列表视图</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-sort"/></svg></div>
<div class="name">ArrowUpDown</div>
<div class="usage">排序</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-x"/></svg></div>
<div class="name">X</div>
<div class="usage">弹窗关闭</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-star"/></svg></div>
<div class="name">Star (四角星)</div>
<div class="usage">favicon / 极窄场景<br>CYBER ✦ STAR 字标用 ✦ 字符)</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-sparkles"/></svg></div>
<div class="name">Sparkles</div>
<div class="usage">装饰点缀</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-loader"/></svg></div>
<div class="name">Loader2</div>
<div class="usage">加载中</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-play"/></svg></div>
<div class="name">Play</div>
<div class="usage">详情页视频</div>
</div>
<div class="icon-card">
<div class="ico"><svg><use href="#i-pause"/></svg></div>
<div class="name">Pause</div>
<div class="usage">详情页视频</div>
</div>
</div>
<h3>标准尺寸</h3>
<table>
<tr><th>用途</th><th>尺寸</th></tr>
<tr><td>内联小图标(票数、标签)</td><td>12-14px</td></tr>
<tr><td>按钮内图标</td><td>14-16px</td></tr>
<tr><td>独立操作图标</td><td>16-20px</td></tr>
<tr><td>大尺寸标题图标</td><td>24-32px</td></tr>
</table>
</section>
<!-- ─── 9. Breakpoints ─── -->
<section id="breakpoint">
<div class="sec-head"><span class="num">09</span></div>
<h2>Responsive · 响应式断点</h2>
<table>
<tr><th>断点</th><th>设备</th><th>卡片列数</th><th>布局变化</th></tr>
<tr><td>&lt; 640px</td><td>手机</td><td>2</td><td>横滚 Top12隐藏 nav 文字</td></tr>
<tr><td>≥ 640px</td><td>大手机 / 平板竖</td><td>3</td><td></td></tr>
<tr><td>≥ 768px</td><td>平板横</td><td>4</td><td>显示 nav 文字</td></tr>
<tr><td>≥ 1024px</td><td>桌面</td><td><strong>5</strong></td><td>完整布局</td></tr>
<tr><td>≥ 1280px</td><td>大桌面</td><td>5</td><td>容器 max-w-7xl 居中</td></tr>
</table>
</section>
<!-- ─── 10. UI/UX Rules ─── -->
<section id="uxrules">
<div class="sec-head"><span class="num">10</span></div>
<h2>UI/UX 通用规范(必须遵守)</h2>
<p class="desc">10 条网页设计行业铁律,所有页面都必须满足。</p>
<h4>10.1 可访问性WCAG 2.1 AA</h4>
<ul class="bullets">
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>所有交互元素必须有 <code>aria-label</code> 或可见文字</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>颜色对比度:正文 ≥ 4.5:1大字 ≥ 3:1</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>不依赖颜色单独传达信息(必须配合图标 / 文字)</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>视频自动播放必须 muted并提供解除静音控件</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>弹窗Escape 关闭、聚焦陷阱、<code>aria-modal="true"</code></li>
</ul>
<h4>10.2 焦点指示Keyboard Nav</h4>
<ul class="bullets">
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>所有可聚焦元素必须有可见 <code>:focus-visible</code> 轮廓</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>标准2px 紫色实线 + 2px 偏移,色值 <code>--color-purple-400</code></li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>禁止 <code>outline: none</code> 而不提供替代焦点样式</li>
</ul>
<h4>10.3 触控目标</h4>
<ul class="bullets">
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>移动端最小触控目标 <strong>44 × 44 px</strong></li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>相邻可点击元素至少留 8px 间距</li>
</ul>
<h4>10.4 三态必备</h4>
<table>
<tr><th>状态</th><th>视觉</th></tr>
<tr><td>加载中Loading</td><td>骨架屏 + lucide <code>Loader2</code>,不用 spinner 占整页</td></tr>
<tr><td>空状态Empty</td><td>居中插画 / 图标 + 说明 + 可选 CTA</td></tr>
<tr><td>错误Error</td><td>居中错误图标pink-500+ 描述 + 重试按钮</td></tr>
</table>
<h4>10.5 表单设计</h4>
<ul class="bullets">
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>Label 始终在输入框<strong>上方</strong>(不用浮动 label</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>错误提示:输入框下方红字 + 边框转 pink-500</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>Placeholder 不能代替 Label</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>必填字段标 <span style="color: var(--p300)">*</span>(紫色)</li>
</ul>
<h4>10.6 语义</h4>
<ul class="bullets">
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span><code>&lt;button&gt;</code> 用于触发动作,<code>&lt;a href&gt;</code> 用于跳转</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>禁止:用按钮做跳转 / 用链接做提交</li>
</ul>
<h4>10.7-10 信息密度 · 性能 · 暗色模式 · 禁用 emoji</h4>
<ul class="bullets">
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>同区块 ≤ 3 个字号层级section 间距 ≥ 40 / 64 px</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>段落最大宽度 ≤ 75 字符</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>LCP &lt; 2.5sCLS &lt; 0.1,图片必须 aspect-ratio 占位</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span>暗色模式专属:禁纯黑 #000、禁大面积纯白、阴影改辉光</li>
<li><span class="bullet-star"><svg><use href="#i-star"/></svg></span><strong>禁止任何 emoji</strong>,所有图标统一 lucide SVG强制铁律</li>
</ul>
</section>
<!-- ─── 11. Copy ─── -->
<section id="copy">
<div class="sec-head"><span class="num">11</span></div>
<h2>Content · 文案约定</h2>
<table>
<tr><th>场景</th><th>文案</th></tr>
<tr><td>投票按钮</td><td><strong style="color: var(--p300)">「投票」</strong>(不用 "Vote"</td></tr>
<tr><td>顶部 nav</td><td>「首页」「排行榜」</td></tr>
<tr><td>排名榜标题</td><td><code>&lt;Trophy size={14}/&gt;</code> + 「实时 Top12 出道位」</td></tr>
<tr><td>倒计时前缀</td><td>「距离投票结束」</td></tr>
<tr><td>投票成功</td><td>「已为 {名字} 投出 {N} 票」</td></tr>
<tr><td>票数耗尽</td><td>「今日票数已用完,明天再来吧」</td></tr>
<tr><td>卡片票数</td><td><code>&lt;Heart size={12} fill="currentColor"/&gt;</code> + 「12.6W 票」W 大写)</td></tr>
<tr><td>版权</td><td>「© {当年} CYBER STAR · All Rights Reserved」</td></tr>
</table>
</section>
<!-- ─── 12. Tokens ─── -->
<section id="tokens">
<div class="sec-head"><span class="num">12</span></div>
<h2>Token 映射 · 设计 ↔ 代码</h2>
<p class="desc">交付时设计师直接引用 Tailwind 工具类名,开发零成本接入。</p>
<table>
<tr><th>Figma 颜色名</th><th>CSS 变量</th><th>Tailwind 工具类</th></tr>
<tr><td>Background / Deepest</td><td><code>var(--color-deepest)</code></td><td><code>bg-deepest</code></td></tr>
<tr><td>Background / Card</td><td><code>var(--color-card)</code></td><td><code>bg-card</code></td></tr>
<tr><td>Brand / Purple 500</td><td><code>var(--color-purple-500)</code></td><td><code>bg-purple-500</code> / <code>text-purple-500</code></td></tr>
<tr><td>Brand / Purple 300</td><td><code>var(--color-purple-300)</code></td><td><code>text-purple-300</code></td></tr>
<tr><td>Border / Subtle</td><td><code>var(--border-subtle)</code></td><td><code>border-white/[0.08]</code></td></tr>
<tr><td>Border / Purple Soft</td><td><code>rgba(196,181,253,0.4)</code></td><td><code>border-purple-300/40</code></td></tr>
<tr><td>Shadow / Purple Glow</td><td><code>var(--shadow-purple)</code></td><td><code>shadow-purple-glow</code></td></tr>
<tr><td>Gradient / Purple</td><td><code>var(--grad-purple)</code></td><td><code>bg-grad-purple</code></td></tr>
<tr><td>Font / Logo</td><td><code>var(--font-logo)</code> = Orbitron</td><td><code>font-logo</code></td></tr>
<tr><td>Font / Display</td><td><code>var(--font-display)</code> = Audiowide</td><td><code>font-display</code></td></tr>
<tr><td>Font / Body</td><td><code>var(--font-body)</code> = Inter</td><td><code>font-body</code></td></tr>
</table>
</section>
<footer style="margin-top: 80px; padding-top: 32px; border-top: 1px solid var(--border-subtle); text-align: center; color: rgba(255,255,255,0.35); font-size: 11px; letter-spacing: 0.1em;">
© 2026 CYBER STAR · Design Spec v2.1 · All Rights Reserved
</footer>
</main>
</div>
</body>
</html>