mirror of
https://github.com/timeshiftsauce/CeruMusic.git
synced 2025-11-25 11:29:42 +08:00
add(website):更新发布页
This commit is contained in:
258
website/index.html
Normal file
258
website/index.html
Normal 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>© 2024 Ceru Music. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
576
website/script.js
Normal file
576
website/script.js
Normal 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
650
website/styles.css
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user