add(website):更新发布页

This commit is contained in:
sqj
2025-08-26 19:32:58 +08:00
parent eea157b8d6
commit 6945c733e9
3 changed files with 1484 additions and 0 deletions

258
website/index.html Normal file
View File

@@ -0,0 +1,258 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ceru Music - 跨平台音乐播放器</title>
<link rel="stylesheet" href="styles.css">
<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=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<!-- Navigation -->
<nav class="navbar">
<div class="nav-container">
<div class="nav-logo">
<img src="../resources/logo.svg" alt="Ceru Music" class="logo-img">
<span class="logo-text">Ceru Music</span>
</div>
<div class="nav-links">
<a href="#features">功能特色</a>
<a href="#download">下载</a>
<a href="#docs">文档</a>
</div>
</div>
</nav>
<!-- Hero Section -->
<section class="hero">
<div class="hero-container">
<div class="hero-content">
<h1 class="hero-title">
<span class="gradient-text">Ceru Music</span>
<br>跨平台音乐播放器
</h1>
<p class="hero-description">
集成多平台音乐源提供优雅的桌面音乐体验。支持网易云音乐、QQ音乐等多个平台让你的音乐世界更加丰富。
</p>
<div class="hero-buttons">
<button class="btn btn-primary" onclick="scrollToDownload()">
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7,10 12,15 17,10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
立即下载
</button>
<button class="btn btn-secondary" onclick="scrollToFeatures()">
了解更多
</button>
</div>
</div>
<div class="hero-image">
<div class="app-preview">
<div class="app-window">
<div class="window-header">
<div class="window-controls">
<span class="control close"></span>
<span class="control minimize"></span>
<span class="control maximize"></span>
</div>
</div>
<div class="window-content">
<div class="music-player-preview">
<div class="album-art"></div>
<div class="player-info">
<div class="song-title"></div>
<div class="artist-name"></div>
<div class="progress-bar">
<div class="progress"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Features Section -->
<section id="features" class="features">
<div class="container">
<h2 class="section-title">功能特色</h2>
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="12" cy="12" r="3"/>
<path d="M12 1v6m0 6v6"/>
<path d="m21 12-6-3-6 3-6-3"/>
</svg>
</div>
<h3>多平台音源</h3>
<p>支持网易云音乐、QQ音乐等多个平台一站式访问海量音乐资源</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/>
<line x1="8" y1="21" x2="16" y2="21"/>
<line x1="12" y1="17" x2="12" y2="21"/>
</svg>
</div>
<h3>跨平台支持</h3>
<p>原生桌面应用,支持 Windows、macOS、Linux 三大操作系统</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M9 18V5l12-2v13"/>
<circle cx="6" cy="18" r="3"/>
<circle cx="18" cy="16" r="3"/>
</svg>
</div>
<h3>歌词显示</h3>
<p>实时歌词显示,支持专辑信息获取,让音乐体验更加丰富</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
</svg>
</div>
<h3>性能优化</h3>
<p>虚拟滚动技术,轻松处理大型音乐列表,流畅的用户体验</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
</svg>
</div>
<h3>本地播放列表</h3>
<p>创建和管理个人播放列表,本地数据存储,个性化音乐体验</p>
</div>
<div class="feature-card">
<div class="feature-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</svg>
</div>
<h3>优雅界面</h3>
<p>现代化设计语言,流畅动画效果,为你带来愉悦的视觉体验</p>
</div>
</div>
</div>
</section>
<!-- Download Section -->
<section id="download" class="download">
<div class="container">
<h2 class="section-title">立即下载</h2>
<p class="section-subtitle">选择适合你操作系统的版本</p>
<div class="download-cards">
<div class="download-card">
<div class="platform-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M0 12v-2h24v2H12.5c-.2 0-.5.2-.5.5s.3.5.5.5H24v2H0v-2h11.5c.2 0 .5-.2.5-.5s-.3-.5-.5-.5H0z"/>
</svg>
</div>
<h3>Windows</h3>
<p>Windows 10/11 (64-bit)</p>
<button class="btn btn-download" onclick="downloadApp('windows')">
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7,10 12,15 17,10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
下载 .exe
</button>
</div>
<div class="download-card">
<div class="platform-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12.5 2C13.3 2 14 2.7 14 3.5S13.3 5 12.5 5 11 4.3 11 3.5 11.7 2 12.5 2M21 9H15L13.5 7.5C13.1 7.1 12.6 6.9 12 6.9S10.9 7.1 10.5 7.5L9 9H3C1.9 9 1 9.9 1 11V19C1 20.1 1.9 21 3 21H21C22.1 21 23 20.1 23 19V11C23 9.9 22.1 9 21 9Z"/>
</svg>
</div>
<h3>macOS</h3>
<p>macOS 10.15+ (Intel & Apple Silicon)</p>
<button class="btn btn-download" onclick="downloadApp('macos')">
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7,10 12,15 17,10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
下载 .dmg
</button>
</div>
<div class="download-card">
<div class="platform-icon">
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C13.1 2 14 2.9 14 4C14 5.1 13.1 6 12 6C10.9 6 10 5.1 10 4C10 2.9 10.9 2 12 2M21 9V7L15 1H5C3.9 1 3 1.9 3 3V21C3 22.1 3.9 23 5 23H19C20.1 23 21 22.1 21 21V9H21Z"/>
</svg>
</div>
<h3>Linux</h3>
<p>Ubuntu 18.04+ / Debian 10+</p>
<button class="btn btn-download" onclick="downloadApp('linux')">
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7,10 12,15 17,10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
下载 .AppImage
</button>
</div>
</div>
<div class="version-info">
<p>当前版本: <span class="version">v1.0.0</span> | 更新时间: 2024年12月</p>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="container">
<div class="footer-content">
<div class="footer-section">
<div class="footer-logo">
<img src="../resources/logo.svg" alt="Ceru Music" class="logo-img">
<span class="logo-text">Ceru Music</span>
</div>
<p>跨平台音乐播放器,为你带来优雅的音乐体验</p>
</div>
<div class="footer-section">
<h4>产品</h4>
<ul>
<li><a href="#features">功能特色</a></li>
<li><a href="#download">下载</a></li>
<li><a href="../docs/design.md">设计文档</a></li>
</ul>
</div>
<div class="footer-section">
<h4>开发者</h4>
<ul>
<li><a href="../docs/api.md">API 文档</a></li>
<li><a href="../docs/CeruMusic插件开发文档.md">插件开发</a></li>
<li><a href="https://github.com">GitHub</a></li>
</ul>
</div>
<div class="footer-section">
<h4>支持</h4>
<ul>
<li><a href="../docs/CeruMusicPluginHost-使用文档.md">使用文档</a></li>
<li><a href="#contact">联系我们</a></li>
<li><a href="#feedback">反馈建议</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2024 Ceru Music. All rights reserved.</p>
</div>
</div>
</footer>
<script src="script.js"></script>
</body>
</html>

576
website/script.js Normal file
View File

@@ -0,0 +1,576 @@
// Smooth scrolling functions
function scrollToDownload() {
document.getElementById('download').scrollIntoView({
behavior: 'smooth'
});
}
function scrollToFeatures() {
document.getElementById('features').scrollIntoView({
behavior: 'smooth'
});
}
// GitHub repository configuration
const GITHUB_REPO = 'timeshiftsauce/CeruMusic';
const GITHUB_API_URL = `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`;
// Cache for release data
let releaseData = null;
let releaseDataTimestamp = null;
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
// Download functionality
async function downloadApp(platform) {
const button = event.target;
const originalText = button.innerHTML;
// Show loading state
button.innerHTML = `
<svg class="btn-icon spinning" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M21 12a9 9 0 11-6.219-8.56"/>
</svg>
获取下载链接...
`;
button.disabled = true;
try {
// Get latest release data
const release = await getLatestRelease();
if (!release) {
throw new Error('无法获取最新版本信息');
}
// Find the appropriate download asset
const downloadUrl = findDownloadAsset(release.assets, platform);
if (!downloadUrl) {
throw new Error(`暂无 ${getPlatformName(platform)} 版本下载`);
}
// Show success notification
showNotification(`正在下载 ${getPlatformName(platform)} 版本 v${release.tag_name}...`, 'success');
// Start download
window.open(downloadUrl, '_blank');
// Track download
trackDownload(platform, release.tag_name);
} catch (error) {
console.error('Download error:', error);
showNotification(`下载失败: ${error.message}`, 'error');
// Fallback to GitHub releases page
setTimeout(() => {
showNotification('正在跳转到GitHub下载页面...', 'info');
window.open(`https://github.com/${GITHUB_REPO}/releases/latest`, '_blank');
}, 2000);
} finally {
// Restore button state
setTimeout(() => {
button.innerHTML = originalText;
button.disabled = false;
}, 1500);
}
}
// Get latest release from GitHub API
async function getLatestRelease() {
// Check cache first
const now = Date.now();
if (releaseData && releaseDataTimestamp && (now - releaseDataTimestamp) < CACHE_DURATION) {
return releaseData;
}
try {
const response = await fetch(GITHUB_API_URL);
if (!response.ok) {
throw new Error(`GitHub API error: ${response.status}`);
}
const data = await response.json();
// Cache the data
releaseData = data;
releaseDataTimestamp = now;
return data;
} catch (error) {
console.error('Failed to fetch release data:', error);
return null;
}
}
// Find appropriate download asset based on platform
function findDownloadAsset(assets, platform) {
if (!assets || !Array.isArray(assets)) {
return null;
}
// Define file patterns for each platform
const patterns = {
windows: [
/\.exe$/i,
/windows.*\.zip$/i,
/win32.*\.zip$/i,
/win.*x64.*\.zip$/i
],
macos: [
/\.dmg$/i,
/darwin.*\.zip$/i,
/macos.*\.zip$/i,
/mac.*\.zip$/i,
/osx.*\.zip$/i
],
linux: [
/\.AppImage$/i,
/linux.*\.zip$/i,
/linux.*\.tar\.gz$/i,
/\.deb$/i,
/\.rpm$/i
]
};
const platformPatterns = patterns[platform] || [];
// Try to find exact match
for (const pattern of platformPatterns) {
const asset = assets.find(asset => pattern.test(asset.name));
if (asset) {
return asset.browser_download_url;
}
}
// Fallback: look for any asset that might match the platform
const fallbackPatterns = {
windows: /win|exe/i,
macos: /mac|darwin|dmg/i,
linux: /linux|appimage|deb|rpm/i
};
const fallbackPattern = fallbackPatterns[platform];
if (fallbackPattern) {
const asset = assets.find(asset => fallbackPattern.test(asset.name));
if (asset) {
return asset.browser_download_url;
}
}
return null;
}
function getPlatformName(platform) {
const names = {
windows: 'Windows',
macos: 'macOS',
linux: 'Linux'
};
return names[platform] || platform;
}
// Notification system
function showNotification(message, type = 'info') {
// Remove existing notifications
const existingNotifications = document.querySelectorAll('.notification');
existingNotifications.forEach(notification => notification.remove());
// Create notification element
const notification = document.createElement('div');
notification.className = `notification notification-${type}`;
notification.innerHTML = `
<div class="notification-content">
<span class="notification-message">${message}</span>
<button class="notification-close" onclick="this.parentElement.parentElement.remove()">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
`;
// Add notification styles if not already added
if (!document.querySelector('#notification-styles')) {
const styles = document.createElement('style');
styles.id = 'notification-styles';
styles.textContent = `
.notification {
position: fixed;
top: 90px;
right: 20px;
background: white;
border: 1px solid var(--border);
border-radius: var(--border-radius);
box-shadow: var(--shadow-lg);
z-index: 1001;
min-width: 300px;
animation: slideInRight 0.3s ease-out;
}
.notification-info {
border-left: 4px solid var(--primary-color);
}
.notification-success {
border-left: 4px solid #10b981;
}
.notification-error {
border-left: 4px solid #ef4444;
}
.notification-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
}
.notification-message {
color: var(--text-primary);
font-weight: 500;
}
.notification-close {
background: none;
border: none;
cursor: pointer;
color: var(--text-muted);
padding: 0.25rem;
border-radius: 4px;
transition: var(--transition);
}
.notification-close:hover {
background: var(--surface);
color: var(--text-primary);
}
.notification-close svg {
width: 16px;
height: 16px;
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@media (max-width: 480px) {
.notification {
right: 10px;
left: 10px;
min-width: auto;
}
}
`;
document.head.appendChild(styles);
}
// Add to page
document.body.appendChild(notification);
// Auto remove after 5 seconds
setTimeout(() => {
if (notification.parentElement) {
notification.style.animation = 'slideInRight 0.3s ease-out reverse';
setTimeout(() => notification.remove(), 300);
}
}, 5000);
}
// Navbar scroll effect
function handleNavbarScroll() {
const navbar = document.querySelector('.navbar');
if (window.scrollY > 50) {
navbar.style.background = 'rgba(255, 255, 255, 0.98)';
navbar.style.boxShadow = 'var(--shadow)';
} else {
navbar.style.background = 'rgba(255, 255, 255, 0.95)';
navbar.style.boxShadow = 'none';
}
}
// Intersection Observer for animations
function setupAnimations() {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.animation = 'fadeInUp 0.6s ease-out forwards';
}
});
}, observerOptions);
// Observe feature cards and download cards
document.querySelectorAll('.feature-card, .download-card').forEach(card => {
card.style.opacity = '0';
card.style.transform = 'translateY(30px)';
observer.observe(card);
});
}
// Auto-detect user's operating system
function detectOS() {
const userAgent = navigator.userAgent.toLowerCase();
if (userAgent.includes('win')) return 'windows';
if (userAgent.includes('mac')) return 'macos';
if (userAgent.includes('linux')) return 'linux';
return 'windows'; // default
}
// Highlight user's OS download option
function highlightUserOS() {
const userOS = detectOS();
const downloadCards = document.querySelectorAll('.download-card');
downloadCards.forEach((card, index) => {
const platforms = ['windows', 'macos', 'linux'];
if (platforms[index] === userOS) {
card.style.border = '2px solid var(--primary-color)';
card.style.transform = 'scale(1.02)';
// Add "推荐" badge
const badge = document.createElement('div');
badge.className = 'recommended-badge';
badge.textContent = '推荐';
badge.style.cssText = `
position: absolute;
top: -10px;
right: 20px;
background: var(--primary-color);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
`;
card.style.position = 'relative';
card.appendChild(badge);
}
});
}
// Keyboard navigation
function setupKeyboardNavigation() {
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
// Close notifications
document.querySelectorAll('.notification').forEach(notification => {
notification.remove();
});
}
if (e.key === 'Enter' && e.target.classList.contains('btn')) {
e.target.click();
}
});
}
// Performance optimization: Lazy load images
function setupLazyLoading() {
const images = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
imageObserver.unobserve(img);
}
});
});
images.forEach(img => imageObserver.observe(img));
}
// Initialize everything when DOM is loaded
document.addEventListener('DOMContentLoaded', async () => {
// Setup scroll effects
window.addEventListener('scroll', handleNavbarScroll);
// Setup animations
setupAnimations();
// Highlight user's OS
highlightUserOS();
// Setup keyboard navigation
setupKeyboardNavigation();
// Setup lazy loading
setupLazyLoading();
// Add GitHub links
addGitHubLinks();
// Update version information from GitHub
await updateVersionInfo();
// Add smooth scrolling to all anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Remove the old download button click handlers since downloadApp now handles everything
// The downloadApp function is called directly from the HTML onclick attributes
});
// Add spinning animation for loading state
const spinningStyles = document.createElement('style');
spinningStyles.textContent = `
.spinning {
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
`;
document.head.appendChild(spinningStyles);
// Error handling for failed downloads
window.addEventListener('error', (e) => {
console.error('页面错误:', e.error);
});
// Update version information on page
async function updateVersionInfo() {
try {
const release = await getLatestRelease();
if (release) {
const versionElement = document.querySelector('.version');
const versionInfoElement = document.querySelector('.version-info p');
if (versionElement) {
versionElement.textContent = release.tag_name;
}
if (versionInfoElement) {
const publishDate = new Date(release.published_at);
const formattedDate = publishDate.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long'
});
versionInfoElement.innerHTML = `当前版本: <span class="version">${release.tag_name}</span> | 更新时间: ${formattedDate}`;
}
// Update download button text with file sizes if available
updateDownloadButtonsWithAssets(release.assets);
}
} catch (error) {
console.error('Failed to update version info:', error);
}
}
// Update download buttons with asset information
function updateDownloadButtonsWithAssets(assets) {
if (!assets || !Array.isArray(assets)) return;
const downloadCards = document.querySelectorAll('.download-card');
const platforms = ['windows', 'macos', 'linux'];
downloadCards.forEach((card, index) => {
const platform = platforms[index];
const asset = findAssetForPlatform(assets, platform);
if (asset) {
const button = card.querySelector('.btn-download');
const sizeText = formatFileSize(asset.size);
const originalText = button.innerHTML;
// Add file size info
button.innerHTML = originalText.replace(/下载 \.(.*?)$/, `下载 .${getFileExtension(asset.name)} (${sizeText})`);
}
});
}
// Helper function to find asset for platform
function findAssetForPlatform(assets, platform) {
const patterns = {
windows: [/\.exe$/i, /windows.*\.zip$/i, /win32.*\.zip$/i],
macos: [/\.dmg$/i, /darwin.*\.zip$/i, /macos.*\.zip$/i],
linux: [/\.AppImage$/i, /linux.*\.zip$/i, /\.deb$/i]
};
const platformPatterns = patterns[platform] || [];
for (const pattern of platformPatterns) {
const asset = assets.find(asset => pattern.test(asset.name));
if (asset) return asset;
}
return null;
}
// Helper function to get file extension
function getFileExtension(filename) {
return filename.split('.').pop();
}
// Helper function to format file size
function formatFileSize(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}
// Analytics tracking (placeholder)
function trackDownload(platform, version) {
// Add your analytics tracking code here
console.log(`Download tracked: ${platform} v${version}`);
// Example: Google Analytics
// gtag('event', 'download', {
// 'event_category': 'software',
// 'event_label': platform,
// 'value': version
// });
}
// Add GitHub link functionality
function addGitHubLinks() {
// Add GitHub link to footer if not exists
const footerSection = document.querySelector('.footer-section:nth-child(3) ul');
if (footerSection) {
const githubLink = document.createElement('li');
githubLink.innerHTML = `<a href="https://github.com/${GITHUB_REPO}" target="_blank">GitHub 仓库</a>`;
footerSection.appendChild(githubLink);
}
// Add "查看所有版本" link to download section
const versionInfo = document.querySelector('.version-info');
if (versionInfo) {
const allVersionsLink = document.createElement('p');
allVersionsLink.innerHTML = `<a href="https://github.com/${GITHUB_REPO}/releases" target="_blank" style="color: var(--primary-color); text-decoration: none;">查看所有版本 →</a>`;
allVersionsLink.style.marginTop = '1rem';
versionInfo.appendChild(allVersionsLink);
}
}

650
website/styles.css Normal file
View File

@@ -0,0 +1,650 @@
/* Reset and Base Styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-color: #6366f1;
--primary-dark: #4f46e5;
--secondary-color: #f8fafc;
--text-primary: #1e293b;
--text-secondary: #64748b;
--text-muted: #94a3b8;
--background: #ffffff;
--surface: #f8fafc;
--border: #e2e8f0;
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--border-radius: 12px;
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
color: var(--text-primary);
background: var(--background);
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
/* Navigation */
.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border);
z-index: 1000;
transition: var(--transition);
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: flex;
align-items: center;
justify-content: space-between;
height: 70px;
}
.nav-logo {
display: flex;
align-items: center;
gap: 0.75rem;
font-weight: 600;
font-size: 1.25rem;
color: var(--text-primary);
}
.logo-img {
width: 32px;
height: 32px;
}
.nav-links {
display: flex;
gap: 2rem;
}
.nav-links a {
text-decoration: none;
color: var(--text-secondary);
font-weight: 500;
transition: var(--transition);
position: relative;
}
.nav-links a:hover {
color: var(--primary-color);
}
.nav-links a::after {
content: '';
position: absolute;
bottom: -5px;
left: 0;
width: 0;
height: 2px;
background: var(--primary-color);
transition: var(--transition);
}
.nav-links a:hover::after {
width: 100%;
}
/* Hero Section */
.hero {
padding: 140px 0 100px;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
position: relative;
overflow: hidden;
}
.hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="50" cy="50" r="0.5" fill="%23000" opacity="0.02"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
pointer-events: none;
}
.hero-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
}
.hero-content {
z-index: 2;
}
.hero-title {
font-size: 3.5rem;
font-weight: 700;
line-height: 1.1;
margin-bottom: 1.5rem;
}
.gradient-text {
background: var(--gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-description {
font-size: 1.25rem;
color: var(--text-secondary);
margin-bottom: 2.5rem;
line-height: 1.7;
}
.hero-buttons {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.875rem 2rem;
border: none;
border-radius: var(--border-radius);
font-weight: 600;
font-size: 1rem;
cursor: pointer;
transition: var(--transition);
text-decoration: none;
}
.btn-icon {
width: 20px;
height: 20px;
}
.btn-primary {
background: var(--primary-color);
color: white;
box-shadow: var(--shadow);
}
.btn-primary:hover {
background: var(--primary-dark);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.btn-secondary {
background: white;
color: var(--text-primary);
border: 2px solid var(--border);
}
.btn-secondary:hover {
border-color: var(--primary-color);
color: var(--primary-color);
transform: translateY(-2px);
}
/* Hero Image */
.hero-image {
display: flex;
justify-content: center;
align-items: center;
z-index: 2;
}
.app-preview {
perspective: 1000px;
}
.app-window {
width: 400px;
height: 300px;
background: white;
border-radius: 12px;
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
overflow: hidden;
transform: rotateY(-15deg) rotateX(10deg);
transition: var(--transition);
}
.app-window:hover {
transform: rotateY(-10deg) rotateX(5deg);
}
.window-header {
height: 40px;
background: #f1f5f9;
display: flex;
align-items: center;
padding: 0 1rem;
border-bottom: 1px solid var(--border);
}
.window-controls {
display: flex;
gap: 0.5rem;
}
.control {
width: 12px;
height: 12px;
border-radius: 50%;
}
.control.close { background: #ef4444; }
.control.minimize { background: #f59e0b; }
.control.maximize { background: #10b981; }
.window-content {
padding: 2rem;
height: calc(100% - 40px);
}
.music-player-preview {
display: flex;
flex-direction: column;
gap: 1rem;
height: 100%;
}
.album-art {
width: 120px;
height: 120px;
background: var(--gradient);
border-radius: 8px;
margin: 0 auto;
animation: pulse 2s infinite;
}
.player-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.song-title {
height: 20px;
background: var(--border);
border-radius: 4px;
width: 80%;
}
.artist-name {
height: 16px;
background: var(--border);
border-radius: 4px;
width: 60%;
}
.progress-bar {
height: 4px;
background: var(--border);
border-radius: 2px;
margin-top: 1rem;
overflow: hidden;
}
.progress {
height: 100%;
background: var(--primary-color);
width: 40%;
border-radius: 2px;
animation: progress 3s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.7; }
}
@keyframes progress {
0% { width: 40%; }
50% { width: 70%; }
100% { width: 40%; }
}
/* Features Section */
.features {
padding: 100px 0;
background: var(--background);
}
.section-title {
font-size: 2.5rem;
font-weight: 700;
text-align: center;
margin-bottom: 3rem;
color: var(--text-primary);
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 2rem;
}
.feature-card {
background: white;
padding: 2rem;
border-radius: var(--border-radius);
box-shadow: var(--shadow);
border: 1px solid var(--border);
transition: var(--transition);
text-align: center;
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-lg);
border-color: var(--primary-color);
}
.feature-icon {
width: 60px;
height: 60px;
margin: 0 auto 1.5rem;
background: var(--gradient);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.feature-icon svg {
width: 28px;
height: 28px;
}
.feature-card h3 {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 1rem;
color: var(--text-primary);
}
.feature-card p {
color: var(--text-secondary);
line-height: 1.6;
}
/* Download Section */
.download {
padding: 100px 0;
background: var(--surface);
}
.section-subtitle {
text-align: center;
color: var(--text-secondary);
font-size: 1.125rem;
margin-bottom: 3rem;
}
.download-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 3rem;
}
.download-card {
background: white;
padding: 2.5rem;
border-radius: var(--border-radius);
box-shadow: var(--shadow);
border: 1px solid var(--border);
text-align: center;
transition: var(--transition);
}
.download-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-lg);
}
.platform-icon {
width: 80px;
height: 80px;
margin: 0 auto 1.5rem;
background: var(--surface);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: var(--primary-color);
}
.platform-icon svg {
width: 40px;
height: 40px;
}
.download-card h3 {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: var(--text-primary);
}
.download-card p {
color: var(--text-secondary);
margin-bottom: 2rem;
}
.btn-download {
background: var(--primary-color);
color: white;
width: 100%;
justify-content: center;
}
.btn-download:hover {
background: var(--primary-dark);
transform: translateY(-2px);
}
.version-info {
text-align: center;
color: var(--text-muted);
font-size: 0.875rem;
}
.version {
color: var(--primary-color);
font-weight: 600;
}
/* Footer */
.footer {
background: var(--text-primary);
color: white;
padding: 60px 0 30px;
}
.footer-content {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
gap: 3rem;
margin-bottom: 2rem;
}
.footer-section h4 {
font-size: 1.125rem;
font-weight: 600;
margin-bottom: 1rem;
color: white;
}
.footer-section ul {
list-style: none;
}
.footer-section ul li {
margin-bottom: 0.5rem;
}
.footer-section ul li a {
color: #94a3b8;
text-decoration: none;
transition: var(--transition);
}
.footer-section ul li a:hover {
color: white;
}
.footer-logo {
display: flex;
align-items: center;
gap: 0.75rem;
font-weight: 600;
font-size: 1.25rem;
margin-bottom: 1rem;
}
.footer-section p {
color: #94a3b8;
line-height: 1.6;
}
.footer-bottom {
border-top: 1px solid #334155;
padding-top: 2rem;
text-align: center;
color: #94a3b8;
}
/* Responsive Design */
@media (max-width: 768px) {
.nav-container {
padding: 0 1rem;
}
.nav-links {
display: none;
}
.hero-container {
grid-template-columns: 1fr;
gap: 2rem;
text-align: center;
}
.hero-title {
font-size: 2.5rem;
}
.hero-buttons {
justify-content: center;
}
.app-window {
width: 300px;
height: 225px;
transform: none;
}
.features-grid {
grid-template-columns: 1fr;
}
.download-cards {
grid-template-columns: 1fr;
}
.footer-content {
grid-template-columns: 1fr;
gap: 2rem;
}
.container {
padding: 0 1rem;
}
}
@media (max-width: 480px) {
.hero {
padding: 120px 0 80px;
}
.hero-title {
font-size: 2rem;
}
.hero-description {
font-size: 1rem;
}
.btn {
padding: 0.75rem 1.5rem;
font-size: 0.875rem;
}
.section-title {
font-size: 2rem;
}
.features,
.download {
padding: 80px 0;
}
}
/* Smooth scrolling */
html {
scroll-behavior: smooth;
}
/* Loading animation */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.feature-card,
.download-card {
animation: fadeInUp 0.6s ease-out;
}
/* Hover effects */
.feature-card:hover .feature-icon {
transform: scale(1.1);
}
.download-card:hover .platform-icon {
transform: scale(1.1);
background: var(--primary-color);
color: white;
}