feat: Triển khai nền mesh gradient động và làm mới giao diện người dùng phần hero.
This commit is contained in:
@@ -147,12 +147,36 @@
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
transform: translateY(20px);
|
||||
filter: blur(10px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
filter: blur(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Mesh Gradient Animation - Creates dynamic moving color spots
|
||||
* VI: Animation Mesh Gradient - Tạo các đốm màu di chuyển động
|
||||
*/
|
||||
@keyframes mesh-move {
|
||||
0% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
|
||||
33% {
|
||||
transform: translate(5%, 10%) scale(1.1);
|
||||
}
|
||||
|
||||
66% {
|
||||
transform: translate(-5%, 5%) scale(0.9);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +200,48 @@
|
||||
*/
|
||||
@layer utilities {
|
||||
.animate-fadeIn {
|
||||
animation: fadeIn 0.3s ease-out forwards;
|
||||
animation: fadeIn 0.8s var(--ease-spring) forwards;
|
||||
}
|
||||
|
||||
.mesh-gradient {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -20;
|
||||
background: var(--bg-primary);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mesh-spot {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
filter: blur(80px);
|
||||
opacity: 0.15;
|
||||
animation: mesh-move 20s infinite alternate var(--ease-in-out);
|
||||
}
|
||||
|
||||
.text-glow {
|
||||
text-shadow: 0 0 20px rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.text-brand-glow {
|
||||
text-shadow: 0 0 30px rgba(59, 130, 246, 0.5);
|
||||
}
|
||||
|
||||
.glass-card {
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(var(--glass-blur));
|
||||
border: 1px solid var(--glass-border);
|
||||
transition: all var(--duration-normal) var(--ease-in-out);
|
||||
}
|
||||
|
||||
.glass-card:hover {
|
||||
background: var(--glass-bg-hover);
|
||||
border-color: rgba(59, 130, 246, 0.4);
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--shadow-brand-lg);
|
||||
}
|
||||
|
||||
.animate-shimmer {
|
||||
|
||||
@@ -61,79 +61,98 @@ export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<NavigationHeader />
|
||||
{/* EN: Main content area with brand gradient background / VI: Khu vực nội dung chính với background gradient thương hiệu */}
|
||||
<main className="relative min-h-screen flex flex-col items-center justify-center p-8 text-center bg-bg-primary text-text-primary overflow-hidden">
|
||||
{/* EN: Brand gradient overlay / VI: Overlay gradient thương hiệu */}
|
||||
<div className="absolute inset-0 bg-brand-gradient opacity-5 -z-10" />
|
||||
|
||||
{/* EN: Decorative brand dots / VI: Chấm trang trí thương hiệu */}
|
||||
<div className="absolute top-20 left-10 w-3 h-3 rounded-full bg-brand-primary opacity-20 animate-pulse" />
|
||||
<div className="absolute top-40 right-20 w-4 h-4 rounded-full bg-brand-secondary opacity-20 animate-pulse" style={{ animationDelay: '1s' }} />
|
||||
<div className="absolute bottom-32 left-1/4 w-2 h-2 rounded-full bg-brand-accent opacity-20 animate-pulse" style={{ animationDelay: '2s' }} />
|
||||
{/* EN: Dynamic Background - Mesh Gradient / VI: Nền động - Mesh Gradient */}
|
||||
<div className="mesh-gradient">
|
||||
<div className="mesh-spot w-[600px] h-[600px] bg-brand-primary -top-1/4 -left-1/4" />
|
||||
<div className="mesh-spot w-[500px] h-[500px] bg-brand-secondary top-1/2 -right-1/4" style={{ animationDelay: '-5s' }} />
|
||||
<div className="mesh-spot w-[400px] h-[400px] bg-brand-accent bottom-0 left-1/3" style={{ animationDelay: '-10s' }} />
|
||||
</div>
|
||||
|
||||
<div className="max-w-container-lg w-full space-y-12 animate-fadeIn z-10">
|
||||
{/* EN: Brand Logo / VI: Logo thương hiệu */}
|
||||
<div className="flex justify-center mb-8">
|
||||
<BrandLogo variant="full" size="xl" priority />
|
||||
</div>
|
||||
<main className="relative min-h-screen flex flex-col items-center pt-32 pb-20 p-8 overflow-hidden">
|
||||
{/* EN: Decorative brand elements / VI: Các yếu tố trang trí thương hiệu */}
|
||||
<div className="absolute top-40 left-10 w-2 h-2 rounded-full bg-brand-primary opacity-40 animate-pulse" />
|
||||
<div className="absolute top-60 right-20 w-3 h-3 rounded-full bg-brand-secondary opacity-40 animate-pulse" style={{ animationDelay: '1.5s' }} />
|
||||
|
||||
{/* EN: Hero Title / VI: Tiêu đề Hero */}
|
||||
<h1 className="text-6xl font-display font-bold tracking-tight mb-4 bg-clip-text text-transparent bg-brand-gradient-vertical leading-tight">
|
||||
{t('home.title')}
|
||||
</h1>
|
||||
<div className="container-responsive flex flex-col items-center space-y-16 z-10">
|
||||
{/* EN: Hero Section / VI: Phần Hero */}
|
||||
<div className="flex flex-col items-center space-y-8 max-w-4xl animate-fadeIn">
|
||||
<BrandLogo variant="full" size="xl" priority className="mb-4 drop-shadow-2xl scale-110" />
|
||||
|
||||
{/* EN: Subtitle/Description / VI: Phụ đề/Mô tả */}
|
||||
<p className="text-xl text-text-secondary max-w-2xl mx-auto leading-relaxed">
|
||||
{t('home.description')}
|
||||
</p>
|
||||
<h1 className="text-responsive-hero font-display font-black tracking-tighter bg-clip-text text-transparent bg-brand-gradient-vertical pb-2 drop-shadow-brand">
|
||||
{t('home.title')}
|
||||
</h1>
|
||||
|
||||
{/* EN: Conditional rendering based on authentication status / VI: Render có điều kiện dựa trên trạng thái xác thực */}
|
||||
<div className="pt-8">
|
||||
{isAuthenticated && user ? (
|
||||
// EN: Authenticated user welcome message / VI: Thông báo chào mừng người dùng đã xác thực
|
||||
<div className="space-y-6 p-8 rounded-2xl bg-glass-bg backdrop-blur-glass border border-glass-border inline-block min-w-[320px] shadow-brand">
|
||||
<div className="w-20 h-20 bg-brand-gradient rounded-full mx-auto flex items-center justify-center mb-6 text-3xl font-semibold text-white shadow-colored">
|
||||
{user.email?.[0].toUpperCase()}
|
||||
</div>
|
||||
<p className="text-lg font-medium text-text-primary">
|
||||
{t('home.welcome', { email: user.email })}
|
||||
</p>
|
||||
<div className="inline-flex items-center px-4 py-2 rounded-full bg-bg-tertiary text-text-secondary text-sm border border-border-primary">
|
||||
<span className="w-2 h-2 rounded-full bg-accent-success mr-2 animate-pulse" />
|
||||
{t('home.role', { role: user.role })}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
// EN: Login prompt for unauthenticated users / VI: Nhắc đăng nhập cho người dùng chưa xác thực
|
||||
<div className="space-y-8">
|
||||
<p className="text-text-secondary text-lg">
|
||||
{t('home.pleaseLogin')}
|
||||
</p>
|
||||
<div className="flex gap-4 justify-center flex-wrap">
|
||||
<p className="text-2xl text-text-secondary max-w-2xl text-center leading-relaxed font-medium">
|
||||
{t('home.description')}
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-6 pt-4 w-full sm:w-auto">
|
||||
{!isAuthenticated ? (
|
||||
<>
|
||||
<Button
|
||||
variant="brand"
|
||||
size="xl"
|
||||
onClick={() => (window.location.href = '/auth/login')}
|
||||
className="px-12"
|
||||
className="px-12 py-7 text-lg rounded-full shadow-brand transition-all hover:scale-105 active:scale-95"
|
||||
>
|
||||
Get Started
|
||||
Get Started Now
|
||||
</Button>
|
||||
<Button
|
||||
variant="glass"
|
||||
size="xl"
|
||||
onClick={() => (window.location.href = '/auth/login')}
|
||||
className="px-12"
|
||||
className="px-12 py-7 text-lg rounded-full transition-all hover:bg-white/10"
|
||||
>
|
||||
Learn More
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<Button
|
||||
variant="brand"
|
||||
size="xl"
|
||||
onClick={() => (window.location.href = '/chat')}
|
||||
className="px-12 py-7 text-lg rounded-full shadow-brand"
|
||||
>
|
||||
Go to Dashboard
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* EN: Status / Context Area / VI: Khu vực trạng thái / ngữ cảnh */}
|
||||
<div className="w-full flex justify-center animate-fadeIn" style={{ animationDelay: '0.4s' }}>
|
||||
{isAuthenticated && user ? (
|
||||
<div className="glass-card p-10 rounded-3xl inline-flex flex-col items-center space-y-6 min-w-[380px] shadow-2xl">
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-brand-primary blur-2xl opacity-20 animate-pulse" />
|
||||
<div className="w-24 h-24 bg-brand-gradient rounded-full flex items-center justify-center text-4xl font-bold text-white relative z-10">
|
||||
{user.email?.[0].toUpperCase()}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<p className="text-xl font-semibold text-text-primary mb-1">
|
||||
{t('home.welcome', { email: user.email })}
|
||||
</p>
|
||||
<div className="inline-flex items-center px-4 py-1.5 rounded-full bg-bg-tertiary text-text-secondary text-sm border border-border-primary">
|
||||
<span className="w-2 h-2 rounded-full bg-accent-success mr-3 shadow-[0_0_8px_var(--accent-success)]" />
|
||||
<span className="uppercase tracking-widest font-bold text-xs">{user.role}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
<div className="h-px w-20 bg-gradient-to-r from-transparent via-border-primary to-transparent" />
|
||||
<p className="text-text-tertiary font-medium uppercase tracking-[0.2em] text-sm">
|
||||
{t('home.pleaseLogin')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* EN: Feature highlights / VI: Điểm nổi bật tính năng */}
|
||||
{/* EN: Feature Highlights / VI: Điểm nổi bật tính năng */}
|
||||
{!isAuthenticated && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 pt-16 max-w-4xl mx-auto">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 w-full pt-12">
|
||||
{[
|
||||
{ title: 'Fast Development', icon: Zap, desc: 'Build and deploy in minutes' },
|
||||
{ title: 'Enterprise Ready', icon: Building, desc: 'Production-grade platform' },
|
||||
@@ -141,21 +160,25 @@ export default function Home() {
|
||||
].map((feature, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="p-6 rounded-xl bg-glass-bg backdrop-blur-glass border border-glass-border hover:border-brand-primary/30 transition-all duration-normal hover:shadow-brand group"
|
||||
className="glass-card p-8 rounded-3xl group animate-fadeIn"
|
||||
style={{ animationDelay: `${0.6 + index * 0.15}s` }}
|
||||
>
|
||||
<div className="flex justify-center mb-4 transition-transform duration-normal group-hover:scale-110">
|
||||
<feature.icon className="h-8 w-8 text-brand-primary" />
|
||||
<div className="w-16 h-16 rounded-2xl bg-brand-primary/10 flex items-center justify-center mb-6 transition-all duration-slower group-hover:bg-brand-primary group-hover:scale-110 group-hover:rotate-3 shadow-inner">
|
||||
<feature.icon className="h-8 w-8 text-brand-primary transition-colors group-hover:text-white" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold mb-2 text-text-primary">
|
||||
<h3 className="text-xl font-bold mb-3 text-text-primary group-hover:text-brand-primary transition-colors">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-sm text-text-secondary">{feature.desc}</p>
|
||||
<p className="text-text-secondary leading-relaxed font-medium">
|
||||
{feature.desc}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -155,7 +155,7 @@ export function Footer({ className }: FooterProps) {
|
||||
<div className="border-t border-border-primary pt-8">
|
||||
<div className="flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
{/* EN: Copyright notice / VI: Thông báo copyright */}
|
||||
<p className="text-sm text-text-secondary text-center md:text-left">
|
||||
<p className="text-sm text-text-tertiary text-center md:text-left">
|
||||
{t('footer.copyright', { year: currentYear })}
|
||||
</p>
|
||||
|
||||
@@ -164,7 +164,7 @@ export function Footer({ className }: FooterProps) {
|
||||
<a
|
||||
href="#privacy"
|
||||
className={cn(
|
||||
'text-sm text-text-secondary hover:text-brand-primary',
|
||||
'text-sm text-text-tertiary hover:text-white',
|
||||
'transition-colors duration-fast',
|
||||
'focus-visible:outline-2 focus-visible:outline-accent-primary'
|
||||
)}
|
||||
@@ -174,7 +174,7 @@ export function Footer({ className }: FooterProps) {
|
||||
<a
|
||||
href="#terms"
|
||||
className={cn(
|
||||
'text-sm text-text-secondary hover:text-brand-primary',
|
||||
'text-sm text-text-tertiary hover:text-white',
|
||||
'transition-colors duration-fast',
|
||||
'focus-visible:outline-2 focus-visible:outline-accent-primary'
|
||||
)}
|
||||
|
||||
@@ -55,8 +55,8 @@ export function NavigationHeader({
|
||||
return (
|
||||
<header
|
||||
className={cn(
|
||||
'sticky top-0 z-50 w-full border-b border-border-primary',
|
||||
'bg-bg-primary/80 backdrop-blur-glass',
|
||||
'sticky top-0 z-50 w-full border-b border-white/5',
|
||||
'bg-bg-primary/20 backdrop-blur-xl',
|
||||
'transition-all duration-normal',
|
||||
className
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import { Button } from './button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
@@ -10,6 +9,7 @@ import {
|
||||
DropdownMenuItem
|
||||
} from './dropdown-menu';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useTranslation } from '@/hooks/use-translation';
|
||||
|
||||
/**
|
||||
* EN: Language configuration
|
||||
@@ -28,9 +28,8 @@ export type LanguageCode = typeof languages[number]['code'];
|
||||
*
|
||||
* Features:
|
||||
* - Dropdown menu for language selection
|
||||
* - Persists locale to localStorage
|
||||
* - Updates URL locale parameter
|
||||
* - Smooth language switching
|
||||
* - Persists locale to localStorage via context
|
||||
* - Smooth language switching without page reload
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
@@ -38,12 +37,7 @@ export type LanguageCode = typeof languages[number]['code'];
|
||||
* ```
|
||||
*/
|
||||
export function LanguageSwitcher() {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
|
||||
// EN: Extract current locale from pathname
|
||||
// VI: Trích xuất locale hiện tại từ pathname
|
||||
const currentLocale = pathname.startsWith('/vi') ? 'vi' : 'en';
|
||||
const { locale: currentLocale, setLocale } = useTranslation();
|
||||
|
||||
const currentLanguage = languages.find(lang => lang.code === currentLocale) || languages[0];
|
||||
|
||||
@@ -52,27 +46,7 @@ export function LanguageSwitcher() {
|
||||
* VI: Xử lý thay đổi ngôn ngữ
|
||||
*/
|
||||
const handleLanguageChange = (newLocale: LanguageCode) => {
|
||||
// EN: Save to localStorage
|
||||
// VI: Lưu vào localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('preferredLocale', newLocale);
|
||||
}
|
||||
|
||||
// EN: Update URL
|
||||
// VI: Cập nhật URL
|
||||
let newPathname = pathname;
|
||||
|
||||
// Remove existing locale prefix
|
||||
if (pathname.startsWith('/en') || pathname.startsWith('/vi')) {
|
||||
newPathname = pathname.substring(3) || '/';
|
||||
}
|
||||
|
||||
// Add new locale prefix
|
||||
if (newLocale !== 'en') {
|
||||
newPathname = `/${newLocale}${newPathname}`;
|
||||
}
|
||||
|
||||
router.push(newPathname);
|
||||
setLocale(newLocale as any);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -121,8 +95,8 @@ export function LanguageSwitcher() {
|
||||
}
|
||||
|
||||
/**
|
||||
* EN: Compact Language Switcher - Shows only flags
|
||||
* VI: Language Switcher nhỏ gọn - Chỉ hiển thị cờ
|
||||
* EN: Compact Language Switcher - Shows only code
|
||||
* VI: Language Switcher nhỏ gọn - Chỉ hiển thị mã
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
@@ -130,30 +104,14 @@ export function LanguageSwitcher() {
|
||||
* ```
|
||||
*/
|
||||
export function LanguageSwitcherCompact() {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const currentLocale = pathname.startsWith('/vi') ? 'vi' : 'en';
|
||||
const { locale: currentLocale, setLocale } = useTranslation();
|
||||
const currentLanguage = languages.find(lang => lang.code === currentLocale) || languages[0];
|
||||
|
||||
const toggleLanguage = () => {
|
||||
const newLocale = currentLocale === 'en' ? 'vi' : 'en';
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('preferredLocale', newLocale);
|
||||
}
|
||||
|
||||
let newPathname = pathname;
|
||||
if (pathname.startsWith('/en') || pathname.startsWith('/vi')) {
|
||||
newPathname = pathname.substring(3) || '/';
|
||||
}
|
||||
if (newLocale !== 'en') {
|
||||
newPathname = `/${newLocale}${newPathname}`;
|
||||
}
|
||||
|
||||
router.push(newPathname);
|
||||
setLocale(newLocale);
|
||||
};
|
||||
|
||||
const currentLanguage = languages.find(lang => lang.code === currentLocale) || languages[0];
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="glass"
|
||||
|
||||
@@ -14,303 +14,305 @@
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Color Palette - Dark Mode (Primary Theme)
|
||||
VI: Bảng màu - Dark Mode (Theme chính)
|
||||
============================================ */
|
||||
|
||||
/* Background Colors / Màu nền */
|
||||
--bg-primary: #000000;
|
||||
/* Pure black - Main background */
|
||||
--bg-secondary: #0A0A0A;
|
||||
/* Almost black - Card/Panel background */
|
||||
--bg-tertiary: #141414;
|
||||
/* Very dark grey - Hover states */
|
||||
--bg-elevated: #1A1A1A;
|
||||
/* Elevated surfaces (modals, dropdowns) */
|
||||
/* Background Colors / Màu nền */
|
||||
--bg-primary: #000000;
|
||||
/* Pure black - Main background */
|
||||
--bg-secondary: #0A0A0A;
|
||||
/* Almost black - Card/Panel background */
|
||||
--bg-tertiary: #141414;
|
||||
/* Very dark grey - Hover states */
|
||||
--bg-elevated: #1A1A1A;
|
||||
/* Elevated surfaces (modals, dropdowns) */
|
||||
|
||||
/* Text Colors (WCAG Compliant) / Màu chữ (tuân thủ WCAG) */
|
||||
--text-primary: #FFFFFF;
|
||||
/* Pure white - Primary text */
|
||||
--text-secondary: #888888;
|
||||
/* Mid grey - Secondary text */
|
||||
--text-tertiary: #444444;
|
||||
/* Dark grey - Tertiary/disabled text */
|
||||
--text-inverse: #000000;
|
||||
/* Black - Text on light/white backgrounds */
|
||||
/* Text Colors (WCAG Compliant) / Màu chữ (tuân thủ WCAG) */
|
||||
--text-primary: #FFFFFF;
|
||||
/* Pure white - Primary text */
|
||||
--text-secondary: #B0B0B0;
|
||||
/* Lighter grey - Secondary text (Improved contrast) */
|
||||
--text-tertiary: #808080;
|
||||
/* Mid grey - Tertiary/disabled text (Improved contrast) */
|
||||
--text-muted: #505050;
|
||||
/* Dark grey - Muted elements */
|
||||
--text-inverse: #000000;
|
||||
/* Black - Text on light/white backgrounds */
|
||||
|
||||
/* Brand/Accent Colors / Màu thương hiệu/Accent */
|
||||
--accent-primary: #FFFFFF;
|
||||
/* White - Primary actions (High contrast) */
|
||||
--accent-secondary: #333333;
|
||||
/* Dark grey - Secondary actions */
|
||||
--accent-success: #10B981;
|
||||
/* Green - Success states */
|
||||
--accent-warning: #F59E0B;
|
||||
/* Amber - Warnings */
|
||||
--accent-error: #EF4444;
|
||||
/* Red - Errors */
|
||||
--accent-info: #06B6D4;
|
||||
/* Cyan - Info */
|
||||
/* Brand/Accent Colors / Màu thương hiệu/Accent */
|
||||
--accent-primary: #FFFFFF;
|
||||
/* White - Primary actions (High contrast) */
|
||||
--accent-secondary: #333333;
|
||||
/* Dark grey - Secondary actions */
|
||||
--accent-success: #10B981;
|
||||
/* Green - Success states */
|
||||
--accent-warning: #F59E0B;
|
||||
/* Amber - Warnings */
|
||||
--accent-error: #EF4444;
|
||||
/* Red - Errors */
|
||||
--accent-info: #06B6D4;
|
||||
/* Cyan - Info */
|
||||
|
||||
/* Chat Specific Colors / Màu riêng cho Chat */
|
||||
--chat-user-bubble: #1A1A1A;
|
||||
/* Dark grey - User message */
|
||||
--chat-ai-bubble: transparent;
|
||||
/* Transparent - AI message (Minimal) */
|
||||
--chat-user-text: #FFFFFF;
|
||||
/* White text */
|
||||
--chat-ai-text: #E5E5E5;
|
||||
/* Off-white text */
|
||||
--chat-timestamp: #555555;
|
||||
/* Dark grey timestamp */
|
||||
--chat-divider: #222222;
|
||||
/* Divider between messages */
|
||||
/* Chat Specific Colors / Màu riêng cho Chat */
|
||||
--chat-user-bubble: #1A1A1A;
|
||||
/* Dark grey - User message */
|
||||
--chat-ai-bubble: transparent;
|
||||
/* Transparent - AI message (Minimal) */
|
||||
--chat-user-text: #FFFFFF;
|
||||
/* White text */
|
||||
--chat-ai-text: #E5E5E5;
|
||||
/* Off-white text */
|
||||
--chat-timestamp: #555555;
|
||||
/* Dark grey timestamp */
|
||||
--chat-divider: #222222;
|
||||
/* Divider between messages */
|
||||
|
||||
/* Border Colors / Màu viền */
|
||||
--border-primary: #222222;
|
||||
/* Subtle borders */
|
||||
--border-secondary: #333333;
|
||||
/* Hover borders */
|
||||
--border-focus: #FFFFFF;
|
||||
/* Focus state - White */
|
||||
/* Border Colors / Màu viền */
|
||||
--border-primary: #222222;
|
||||
/* Subtle borders */
|
||||
--border-secondary: #333333;
|
||||
/* Hover borders */
|
||||
--border-focus: #FFFFFF;
|
||||
/* Focus state - White */
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Brand Colors (Primary Identity)
|
||||
VI: Màu thương hiệu (Nhận diện chính)
|
||||
============================================ */
|
||||
|
||||
/* Primary Brand Color - Main brand identity (Blue - Tech & Trust) */
|
||||
--brand-primary: #3B82F6;
|
||||
--brand-primary-light: #60A5FA;
|
||||
--brand-primary-dark: #2563EB;
|
||||
--brand-primary-contrast: #FFFFFF;
|
||||
/* Primary Brand Color - Main brand identity (Blue - Tech & Trust) */
|
||||
--brand-primary: #3B82F6;
|
||||
--brand-primary-light: #60A5FA;
|
||||
--brand-primary-dark: #2563EB;
|
||||
--brand-primary-contrast: #FFFFFF;
|
||||
|
||||
/* Secondary Brand Color - Supporting color (Purple - Innovation) */
|
||||
--brand-secondary: #8B5CF6;
|
||||
--brand-secondary-light: #A78BFA;
|
||||
--brand-secondary-dark: #7C3AED;
|
||||
/* Secondary Brand Color - Supporting color (Purple - Innovation) */
|
||||
--brand-secondary: #8B5CF6;
|
||||
--brand-secondary-light: #A78BFA;
|
||||
--brand-secondary-dark: #7C3AED;
|
||||
|
||||
/* Accent Color - Call-to-action (Cyan - Energy) */
|
||||
--brand-accent: #06B6D4;
|
||||
--brand-accent-light: #22D3EE;
|
||||
--brand-accent-dark: #0891B2;
|
||||
/* Accent Color - Call-to-action (Cyan - Energy) */
|
||||
--brand-accent: #06B6D4;
|
||||
--brand-accent-light: #22D3EE;
|
||||
--brand-accent-dark: #0891B2;
|
||||
|
||||
/* Brand Gradients - For backgrounds and special elements */
|
||||
--brand-gradient-primary: linear-gradient(135deg, var(--brand-primary) 0%, var(--brand-secondary) 100%);
|
||||
--brand-gradient-accent: linear-gradient(135deg, var(--brand-accent) 0%, var(--brand-primary) 100%);
|
||||
--brand-gradient-vertical: linear-gradient(180deg, var(--brand-primary) 0%, var(--brand-secondary) 100%);
|
||||
/* Brand Gradients - For backgrounds and special elements */
|
||||
--brand-gradient-primary: linear-gradient(135deg, var(--brand-primary) 0%, var(--brand-secondary) 100%);
|
||||
--brand-gradient-accent: linear-gradient(135deg, var(--brand-accent) 0%, var(--brand-primary) 100%);
|
||||
--brand-gradient-vertical: linear-gradient(180deg, var(--brand-primary) 0%, var(--brand-secondary) 100%);
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Glassmorphism Effects
|
||||
VI: Hiệu ứng Glassmorphism
|
||||
============================================ */
|
||||
|
||||
--glass-bg: rgba(255, 255, 255, 0.05);
|
||||
--glass-bg-hover: rgba(255, 255, 255, 0.08);
|
||||
--glass-border: rgba(255, 255, 255, 0.1);
|
||||
--glass-blur: 10px;
|
||||
--glass-bg: rgba(255, 255, 255, 0.05);
|
||||
--glass-bg-hover: rgba(255, 255, 255, 0.08);
|
||||
--glass-border: rgba(255, 255, 255, 0.1);
|
||||
--glass-blur: 10px;
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Extended Shadows & Effects
|
||||
VI: Shadows & Effects mở rộng
|
||||
============================================ */
|
||||
|
||||
--shadow-brand: 0 10px 40px rgba(59, 130, 246, 0.2);
|
||||
--shadow-brand-lg: 0 20px 60px rgba(59, 130, 246, 0.3);
|
||||
--shadow-colored: 0 8px 30px rgba(59, 130, 246, 0.25);
|
||||
--shadow-brand: 0 10px 40px rgba(59, 130, 246, 0.2);
|
||||
--shadow-brand-lg: 0 20px 60px rgba(59, 130, 246, 0.3);
|
||||
--shadow-colored: 0 8px 30px rgba(59, 130, 246, 0.25);
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Light Mode Colors (Secondary Theme)
|
||||
VI: Màu sắc cho Light Mode (Theme phụ)
|
||||
============================================ */
|
||||
--bg-primary-light: #F9F9F9;
|
||||
--bg-secondary-light: #FFFFFF;
|
||||
--bg-tertiary-light: #F0F0F0;
|
||||
--text-primary-light: #000000;
|
||||
--text-secondary-light: #666666;
|
||||
--border-primary-light: #E5E5E5;
|
||||
--bg-primary-light: #F9F9F9;
|
||||
--bg-secondary-light: #FFFFFF;
|
||||
--bg-tertiary-light: #F0F0F0;
|
||||
--text-primary-light: #000000;
|
||||
--text-secondary-light: #666666;
|
||||
--border-primary-light: #E5E5E5;
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Typography
|
||||
VI: Kiểu chữ
|
||||
============================================ */
|
||||
|
||||
/* Font Stack / Bộ font */
|
||||
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
--font-mono: "JetBrains Mono", "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
|
||||
/* Font Stack / Bộ font */
|
||||
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
--font-mono: "JetBrains Mono", "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
|
||||
|
||||
/* Display Font - For hero titles (48px+) */
|
||||
--font-display: "Inter Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
/* Display Font - For hero titles (48px+) */
|
||||
--font-display: "Inter Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
|
||||
/* Heading Font - For section headings (24-36px) */
|
||||
--font-heading: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
/* Heading Font - For section headings (24-36px) */
|
||||
--font-heading: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
|
||||
/* Type Scale / Kích thước chữ */
|
||||
--text-6xl: 3.75rem;
|
||||
/* 60px - Hero titles */
|
||||
--text-5xl: 3rem;
|
||||
/* 48px - Page titles */
|
||||
--text-4xl: 2.25rem;
|
||||
/* 36px - Section headers */
|
||||
--text-3xl: 1.875rem;
|
||||
/* 30px - Card headers */
|
||||
--text-2xl: 1.5rem;
|
||||
/* 24px - Large body */
|
||||
--text-xl: 1.25rem;
|
||||
/* 20px - Emphasized text */
|
||||
--text-lg: 1.125rem;
|
||||
/* 18px - Large body */
|
||||
--text-base: 1rem;
|
||||
/* 16px - Default body */
|
||||
--text-sm: 0.875rem;
|
||||
/* 14px - Small text */
|
||||
--text-xs: 0.75rem;
|
||||
/* 12px - Captions */
|
||||
/* Type Scale / Kích thước chữ */
|
||||
--text-6xl: 3.75rem;
|
||||
/* 60px - Hero titles */
|
||||
--text-5xl: 3rem;
|
||||
/* 48px - Page titles */
|
||||
--text-4xl: 2.25rem;
|
||||
/* 36px - Section headers */
|
||||
--text-3xl: 1.875rem;
|
||||
/* 30px - Card headers */
|
||||
--text-2xl: 1.5rem;
|
||||
/* 24px - Large body */
|
||||
--text-xl: 1.25rem;
|
||||
/* 20px - Emphasized text */
|
||||
--text-lg: 1.125rem;
|
||||
/* 18px - Large body */
|
||||
--text-base: 1rem;
|
||||
/* 16px - Default body */
|
||||
--text-sm: 0.875rem;
|
||||
/* 14px - Small text */
|
||||
--text-xs: 0.75rem;
|
||||
/* 12px - Captions */
|
||||
|
||||
/* Line Heights / Chiều cao dòng */
|
||||
--leading-none: 1;
|
||||
--leading-tight: 1.1;
|
||||
--leading-snug: 1.2;
|
||||
--leading-normal: 1.5;
|
||||
--leading-relaxed: 1.625;
|
||||
--leading-loose: 2;
|
||||
/* Line Heights / Chiều cao dòng */
|
||||
--leading-none: 1;
|
||||
--leading-tight: 1.1;
|
||||
--leading-snug: 1.2;
|
||||
--leading-normal: 1.5;
|
||||
--leading-relaxed: 1.625;
|
||||
--leading-loose: 2;
|
||||
|
||||
/* Font Weights / Độ đậm chữ */
|
||||
--font-light: 300;
|
||||
/* Light text */
|
||||
--font-normal: 400;
|
||||
/* Body text */
|
||||
--font-medium: 500;
|
||||
/* Emphasized */
|
||||
--font-semibold: 600;
|
||||
/* Headings */
|
||||
--font-bold: 700;
|
||||
/* Strong emphasis */
|
||||
/* Font Weights / Độ đậm chữ */
|
||||
--font-light: 300;
|
||||
/* Light text */
|
||||
--font-normal: 400;
|
||||
/* Body text */
|
||||
--font-medium: 500;
|
||||
/* Emphasized */
|
||||
--font-semibold: 600;
|
||||
/* Headings */
|
||||
--font-bold: 700;
|
||||
/* Strong emphasis */
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Spacing & Layout
|
||||
VI: Khoảng cách & Bố cục
|
||||
============================================ */
|
||||
|
||||
/* Base Unit: 4px (0.25rem) / Đơn vị cơ sở: 4px (0.25rem) */
|
||||
--space-0: 0;
|
||||
--space-1: 0.25rem;
|
||||
/* 4px */
|
||||
--space-2: 0.5rem;
|
||||
/* 8px */
|
||||
--space-3: 0.75rem;
|
||||
/* 12px */
|
||||
--space-4: 1rem;
|
||||
/* 16px */
|
||||
--space-5: 1.25rem;
|
||||
/* 20px */
|
||||
--space-6: 1.5rem;
|
||||
/* 24px */
|
||||
--space-8: 2rem;
|
||||
/* 32px */
|
||||
--space-10: 2.5rem;
|
||||
/* 40px */
|
||||
--space-12: 3rem;
|
||||
/* 48px */
|
||||
--space-16: 4rem;
|
||||
/* 64px */
|
||||
--space-20: 5rem;
|
||||
/* 80px */
|
||||
/* Base Unit: 4px (0.25rem) / Đơn vị cơ sở: 4px (0.25rem) */
|
||||
--space-0: 0;
|
||||
--space-1: 0.25rem;
|
||||
/* 4px */
|
||||
--space-2: 0.5rem;
|
||||
/* 8px */
|
||||
--space-3: 0.75rem;
|
||||
/* 12px */
|
||||
--space-4: 1rem;
|
||||
/* 16px */
|
||||
--space-5: 1.25rem;
|
||||
/* 20px */
|
||||
--space-6: 1.5rem;
|
||||
/* 24px */
|
||||
--space-8: 2rem;
|
||||
/* 32px */
|
||||
--space-10: 2.5rem;
|
||||
/* 40px */
|
||||
--space-12: 3rem;
|
||||
/* 48px */
|
||||
--space-16: 4rem;
|
||||
/* 64px */
|
||||
--space-20: 5rem;
|
||||
/* 80px */
|
||||
|
||||
/* Container Widths / Chiều rộng container */
|
||||
--container-sm: 640px;
|
||||
/* Small devices */
|
||||
--container-md: 768px;
|
||||
/* Medium devices */
|
||||
--container-lg: 1024px;
|
||||
/* Large devices */
|
||||
--container-xl: 1280px;
|
||||
/* Extra large */
|
||||
--container-2xl: 1536px;
|
||||
/* 2X large */
|
||||
--chat-max-width: 800px;
|
||||
/* Max width for chat messages */
|
||||
--sidebar-width: 280px;
|
||||
/* Conversation history sidebar */
|
||||
/* Container Widths / Chiều rộng container */
|
||||
--container-sm: 640px;
|
||||
/* Small devices */
|
||||
--container-md: 768px;
|
||||
/* Medium devices */
|
||||
--container-lg: 1024px;
|
||||
/* Large devices */
|
||||
--container-xl: 1280px;
|
||||
/* Extra large */
|
||||
--container-2xl: 1536px;
|
||||
/* 2X large */
|
||||
--chat-max-width: 800px;
|
||||
/* Max width for chat messages */
|
||||
--sidebar-width: 280px;
|
||||
/* Conversation history sidebar */
|
||||
|
||||
/* Border Radius / Bo góc */
|
||||
--radius-sm: 2px;
|
||||
/* Small elements - sharp */
|
||||
--radius-md: 4px;
|
||||
/* Buttons, inputs - sharp */
|
||||
--radius-lg: 8px;
|
||||
/* Cards - minimal roundness */
|
||||
--radius-xl: 12px;
|
||||
/* Large cards */
|
||||
--radius-2xl: 16px;
|
||||
/* Modals */
|
||||
--radius-full: 9999px;
|
||||
/* Full round - Avatars, pills */
|
||||
/* Border Radius / Bo góc */
|
||||
--radius-sm: 2px;
|
||||
/* Small elements - sharp */
|
||||
--radius-md: 4px;
|
||||
/* Buttons, inputs - sharp */
|
||||
--radius-lg: 8px;
|
||||
/* Cards - minimal roundness */
|
||||
--radius-xl: 12px;
|
||||
/* Large cards */
|
||||
--radius-2xl: 16px;
|
||||
/* Modals */
|
||||
--radius-full: 9999px;
|
||||
/* Full round - Avatars, pills */
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Shadows (Dark Mode Optimized)
|
||||
VI: Đổ bóng (Tối ưu cho Dark Mode)
|
||||
============================================ */
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.8);
|
||||
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.8);
|
||||
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.9);
|
||||
--shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.95);
|
||||
--shadow-glow: 0 0 20px rgba(255, 255, 255, 0.1);
|
||||
/* White glow for focus */
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.8);
|
||||
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.8);
|
||||
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.9);
|
||||
--shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.95);
|
||||
--shadow-glow: 0 0 20px rgba(255, 255, 255, 0.1);
|
||||
/* White glow for focus */
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Grid System & Breakpoints
|
||||
VI: Hệ thống lưới & Điểm ngắt
|
||||
============================================ */
|
||||
--screen-sm: 640px;
|
||||
/* Mobile landscape */
|
||||
--screen-md: 768px;
|
||||
/* Tablet */
|
||||
--screen-lg: 1024px;
|
||||
/* Desktop */
|
||||
--screen-xl: 1280px;
|
||||
/* Large desktop */
|
||||
--screen-2xl: 1536px;
|
||||
/* Extra large desktop */
|
||||
--screen-sm: 640px;
|
||||
/* Mobile landscape */
|
||||
--screen-md: 768px;
|
||||
/* Tablet */
|
||||
--screen-lg: 1024px;
|
||||
/* Desktop */
|
||||
--screen-xl: 1280px;
|
||||
/* Large desktop */
|
||||
--screen-2xl: 1536px;
|
||||
/* Extra large desktop */
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Animation & Transitions
|
||||
VI: Animation & Chuyển tiếp
|
||||
============================================ */
|
||||
|
||||
/* Timing Functions / Hàm thời gian */
|
||||
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
/* Timing Functions / Hàm thời gian */
|
||||
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
|
||||
/* Duration / Thời lượng */
|
||||
--duration-fast: 150ms;
|
||||
/* Hover effects */
|
||||
--duration-normal: 250ms;
|
||||
/* Default transitions */
|
||||
--duration-slow: 350ms;
|
||||
/* Complex animations */
|
||||
--duration-slower: 500ms;
|
||||
/* Page transitions */
|
||||
/* Duration / Thời lượng */
|
||||
--duration-fast: 150ms;
|
||||
/* Hover effects */
|
||||
--duration-normal: 250ms;
|
||||
/* Default transitions */
|
||||
--duration-slow: 350ms;
|
||||
/* Complex animations */
|
||||
--duration-slower: 500ms;
|
||||
/* Page transitions */
|
||||
|
||||
/* ============================================
|
||||
/* ============================================
|
||||
EN: Advanced Motion Tokens
|
||||
VI: Token chuyển động nâng cao
|
||||
============================================ */
|
||||
|
||||
/* Motion Ease Functions - For micro-interactions */
|
||||
--motion-ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
--motion-ease-elastic: cubic-bezier(0.68, -0.6, 0.32, 1.6);
|
||||
/* Motion Ease Functions - For micro-interactions */
|
||||
--motion-ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
--motion-ease-elastic: cubic-bezier(0.68, -0.6, 0.32, 1.6);
|
||||
|
||||
/* Hover Scale - For interactive elements */
|
||||
--hover-scale-sm: 1.02;
|
||||
--hover-scale-md: 1.05;
|
||||
--hover-scale-lg: 1.1;
|
||||
/* Hover Scale - For interactive elements */
|
||||
--hover-scale-sm: 1.02;
|
||||
--hover-scale-md: 1.05;
|
||||
--hover-scale-lg: 1.1;
|
||||
|
||||
/* Active Scale - For pressed states */
|
||||
--active-scale: 0.98;
|
||||
/* Active Scale - For pressed states */
|
||||
--active-scale: 0.98;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
@@ -318,14 +320,14 @@
|
||||
VI: Ghi đè theme cho Light Mode
|
||||
============================================ */
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--bg-primary: var(--bg-primary-light);
|
||||
--bg-secondary: var(--bg-secondary-light);
|
||||
--bg-tertiary: var(--bg-tertiary-light);
|
||||
--text-primary: var(--text-primary-light);
|
||||
--text-secondary: var(--text-secondary-light);
|
||||
--border-primary: var(--border-primary-light);
|
||||
}
|
||||
:root {
|
||||
--bg-primary: var(--bg-primary-light);
|
||||
--bg-secondary: var(--bg-secondary-light);
|
||||
--bg-tertiary: var(--bg-tertiary-light);
|
||||
--text-primary: var(--text-primary-light);
|
||||
--text-secondary: var(--text-secondary-light);
|
||||
--border-primary: var(--border-primary-light);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
@@ -334,15 +336,16 @@
|
||||
============================================ */
|
||||
[data-theme="dark"],
|
||||
.dark {
|
||||
--bg-primary: #000000;
|
||||
--bg-secondary: #0A0A0A;
|
||||
--bg-tertiary: #141414;
|
||||
--bg-elevated: #1A1A1A;
|
||||
--text-primary: #FFFFFF;
|
||||
--text-secondary: #888888;
|
||||
--text-tertiary: #444444;
|
||||
--border-primary: #222222;
|
||||
--border-secondary: #333333;
|
||||
--bg-primary: #000000;
|
||||
--bg-secondary: #0A0A0A;
|
||||
--bg-tertiary: #141414;
|
||||
--bg-elevated: #1A1A1A;
|
||||
--text-primary: #FFFFFF;
|
||||
--text-secondary: #B0B0B0;
|
||||
--text-tertiary: #808080;
|
||||
--text-muted: #505050;
|
||||
--border-primary: #222222;
|
||||
--border-secondary: #333333;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
@@ -351,10 +354,10 @@
|
||||
============================================ */
|
||||
[data-theme="light"],
|
||||
.light {
|
||||
--bg-primary: var(--bg-primary-light);
|
||||
--bg-secondary: var(--bg-secondary-light);
|
||||
--bg-tertiary: var(--bg-tertiary-light);
|
||||
--text-primary: var(--text-primary-light);
|
||||
--text-secondary: var(--text-secondary-light);
|
||||
--border-primary: var(--border-primary-light);
|
||||
--bg-primary: var(--bg-primary-light);
|
||||
--bg-secondary: var(--bg-secondary-light);
|
||||
--bg-tertiary: var(--bg-tertiary-light);
|
||||
--text-primary: var(--text-primary-light);
|
||||
--text-secondary: var(--text-secondary-light);
|
||||
--border-primary: var(--border-primary-light);
|
||||
}
|
||||
Reference in New Issue
Block a user