powerbackup
Version:
Multi-Database Backup & Restore Tool v2.4.2 with Beautiful Logging, REST API, Enhanced Binary Detection & Debug Tools
909 lines (797 loc) โข 32.9 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PowerBackup v2.2.6 - Enterprise Database Backup & Restore Solution</title>
<meta name="description" content="Enterprise-grade database backup and restore solution with advanced security, automated scheduling, and comprehensive monitoring. Supports MySQL and PostgreSQL with GPG encryption and restore locations.">
<meta name="keywords" content="database backup, enterprise backup, mysql backup, postgresql backup, automated backup, gpg encryption, backup security, database restore, backup monitoring">
<meta name="author" content="PowerBackup Enterprise Team">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://anonnion.github.io/powerbackup/">
<meta property="og:title" content="PowerBackup v2.2.6 - Enterprise Database Backup & Restore Solution">
<meta property="og:description" content="Enterprise-grade database backup and restore solution with advanced security, automated scheduling, and comprehensive monitoring.">
<meta property="og:image" content="https://anonnion.github.io/powerbackup/assets/og-image.png">
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://anonnion.github.io/powerbackup/">
<meta property="twitter:title" content="PowerBackup v2.2.6 - Enterprise Database Backup & Restore Solution">
<meta property="twitter:description" content="Enterprise-grade database backup and restore solution with advanced security, automated scheduling, and comprehensive monitoring.">
<meta property="twitter:image" content="https://anonnion.github.io/powerbackup/assets/og-image.png">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="assets/favicon.ico">
<!-- Google Fonts -->
<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;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<!-- CSS -->
<style>
:root {
--primary-color: #2563eb;
--primary-dark: #1d4ed8;
--primary-light: #3b82f6;
--secondary-color: #10b981;
--secondary-dark: #059669;
--accent-color: #f59e0b;
--text-primary: #1f2937;
--text-secondary: #6b7280;
--text-light: #9ca3af;
--bg-primary: #ffffff;
--bg-secondary: #f9fafb;
--bg-dark: #111827;
--border-color: #e5e7eb;
--border-dark: #374151;
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px 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);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
color: var(--text-primary);
background: var(--bg-primary);
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* Header */
.header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);
color: white;
padding: 120px 0 80px;
position: relative;
overflow: hidden;
}
.header::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="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(255,255,255,0.1)" stroke-width="0.5"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
opacity: 0.3;
}
.header-content {
position: relative;
z-index: 2;
text-align: center;
}
.version-badge {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
padding: 8px 16px;
border-radius: 20px;
display: inline-block;
font-size: 0.875rem;
font-weight: 600;
margin-bottom: 24px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.hero-title {
font-size: clamp(2.5rem, 5vw, 4rem);
font-weight: 900;
margin-bottom: 16px;
background: linear-gradient(135deg, #ffffff 0%, #e0e7ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: -0.02em;
}
.hero-subtitle {
font-size: clamp(1.25rem, 2.5vw, 1.5rem);
font-weight: 400;
margin-bottom: 32px;
opacity: 0.95;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.hero-description {
font-size: 1.125rem;
margin-bottom: 48px;
opacity: 0.9;
max-width: 700px;
margin-left: auto;
margin-right: auto;
line-height: 1.7;
}
/* Status Badges */
.badges {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 48px;
}
.badges a {
text-decoration: none;
transition: transform 0.2s ease;
}
.badges a:hover {
transform: translateY(-2px);
}
.badges img {
height: 24px;
border-radius: 4px;
box-shadow: var(--shadow-sm);
}
/* CTA Buttons */
.cta-buttons {
display: flex;
gap: 16px;
justify-content: center;
flex-wrap: wrap;
}
.btn {
padding: 16px 32px;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
font-size: 1rem;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
gap: 8px;
border: 2px solid transparent;
}
.btn-primary {
background: var(--secondary-color);
color: white;
box-shadow: var(--shadow-md);
}
.btn-primary:hover {
background: var(--secondary-dark);
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.btn-secondary {
background: rgba(255, 255, 255, 0.1);
color: white;
border-color: rgba(255, 255, 255, 0.3);
backdrop-filter: blur(10px);
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.5);
transform: translateY(-2px);
}
/* Features Section */
.features {
padding: 80px 0;
background: var(--bg-secondary);
}
.section-header {
text-align: center;
margin-bottom: 64px;
}
.section-title {
font-size: clamp(2rem, 4vw, 3rem);
font-weight: 800;
color: var(--text-primary);
margin-bottom: 16px;
letter-spacing: -0.02em;
}
.section-subtitle {
font-size: 1.25rem;
color: var(--text-secondary);
max-width: 600px;
margin: 0 auto;
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 32px;
}
.feature-card {
background: white;
padding: 32px;
border-radius: 12px;
border: 1px solid var(--border-color);
box-shadow: var(--shadow-sm);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.feature-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 100%;
background: linear-gradient(180deg, var(--primary-color), var(--secondary-color));
transform: scaleY(0);
transition: transform 0.3s ease;
}
.feature-card:hover::before {
transform: scaleY(1);
}
.feature-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
border-color: var(--primary-light);
}
.feature-card h3 {
font-size: 1.5rem;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 16px;
}
.feature-card p {
color: var(--text-secondary);
line-height: 1.7;
font-size: 1rem;
}
/* Demo Section */
.demo {
padding: 80px 0;
background: var(--bg-dark);
color: white;
}
.demo-content {
max-width: 800px;
margin: 0 auto;
}
.demo h3 {
color: var(--secondary-color);
margin-bottom: 24px;
font-size: 1.5rem;
font-weight: 600;
}
.demo pre {
background: rgba(0, 0, 0, 0.8);
padding: 24px;
border-radius: 8px;
overflow-x: auto;
margin: 0;
border: 1px solid var(--border-dark);
font-family: 'JetBrains Mono', 'Monaco', 'Menlo', monospace;
font-size: 0.9rem;
line-height: 1.6;
}
.demo code {
color: #e5e7eb;
}
/* Stats Section */
.stats {
padding: 80px 0;
background: white;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 32px;
}
.stat-card {
text-align: center;
padding: 32px 24px;
background: var(--bg-secondary);
border-radius: 12px;
border: 1px solid var(--border-color);
transition: all 0.3s ease;
}
.stat-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
}
.stat-number {
font-size: 3rem;
font-weight: 900;
color: var(--primary-color);
margin-bottom: 8px;
line-height: 1;
}
.stat-label {
color: var(--text-secondary);
font-weight: 600;
font-size: 1rem;
}
/* Download Stats Section */
.download-stats {
padding: 60px 0;
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-dark) 100%);
color: white;
}
.download-stats .section-title {
color: white;
}
.download-stats .section-subtitle {
color: rgba(255, 255, 255, 0.9);
}
.download-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
margin-top: 40px;
}
.download-card {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 12px;
padding: 32px;
text-align: center;
transition: all 0.3s ease;
}
.download-card:hover {
transform: translateY(-4px);
background: rgba(255, 255, 255, 0.15);
box-shadow: var(--shadow-lg);
}
.download-card h3 {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 16px;
color: white;
}
.download-card p {
color: rgba(255, 255, 255, 0.9);
margin-bottom: 20px;
line-height: 1.6;
}
.download-badge {
display: inline-block;
margin: 8px;
transition: transform 0.2s ease;
}
.download-badge:hover {
transform: scale(1.05);
}
.download-badge img {
height: 28px;
border-radius: 6px;
}
/* Enterprise Section */
.enterprise {
padding: 80px 0;
background: linear-gradient(135deg, var(--bg-dark) 0%, #1f2937 100%);
color: white;
}
.enterprise-content {
max-width: 800px;
margin: 0 auto;
text-align: center;
}
.enterprise h2 {
font-size: clamp(2rem, 4vw, 3rem);
font-weight: 800;
margin-bottom: 24px;
color: white;
}
.enterprise p {
font-size: 1.25rem;
color: rgba(255, 255, 255, 0.9);
line-height: 1.7;
margin-bottom: 32px;
}
/* Footer */
.footer {
background: var(--text-primary);
color: white;
padding: 60px 0 40px;
text-align: center;
}
.footer-content {
max-width: 600px;
margin: 0 auto;
}
.footer p {
margin-bottom: 16px;
color: rgba(255, 255, 255, 0.8);
}
.footer a {
color: var(--secondary-color);
text-decoration: none;
transition: color 0.2s ease;
}
.footer a:hover {
color: var(--secondary-light);
text-decoration: underline;
}
.footer-links {
display: flex;
gap: 24px;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 24px;
}
/* Responsive Design */
@media (max-width: 768px) {
.container {
padding: 0 16px;
}
.cta-buttons {
flex-direction: column;
align-items: center;
}
.btn {
width: 100%;
max-width: 300px;
justify-content: center;
}
.features-grid {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.footer-links {
flex-direction: column;
gap: 16px;
}
}
/* Animations */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in-up {
animation: fadeInUp 0.6s ease-out;
}
/* Copy functionality */
.copyable {
cursor: pointer;
position: relative;
}
.copyable::after {
content: 'Click to copy';
position: absolute;
top: -30px;
right: 0;
background: var(--text-primary);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 0.75rem;
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
}
.copyable:hover::after {
opacity: 1;
}
</style>
</head>
<body>
<!-- Header -->
<header class="header">
<div class="container">
<div class="header-content">
<div class="version-badge">๐ v2.2.3</div>
<h1 class="hero-title">PowerBackup</h1>
<p class="hero-subtitle">Enterprise Database Backup & Restore Solution</p>
<p class="hero-description">
Secure, reliable, and automated database backup solution designed for enterprise environments.
Features advanced security with GPG encryption, comprehensive monitoring, and seamless integration
with MySQL and PostgreSQL databases.
</p>
<!-- Status Badges -->
<div class="badges">
<a href="https://github.com/anonnion/powerbackup/actions/workflows/ci.yml">
<img src="https://github.com/anonnion/powerbackup/workflows/CI%2FCD%20Pipeline/badge.svg" alt="CI/CD Pipeline">
</a>
<a href="https://github.com/anonnion/powerbackup/actions/workflows/test.yml">
<img src="https://github.com/anonnion/powerbackup/workflows/Test%20Suite/badge.svg" alt="Test Suite">
</a>
<a href="https://www.npmjs.com/package/powerbackup">
<img src="https://img.shields.io/npm/v/powerbackup.svg" alt="npm version">
</a>
<a href="https://www.npmjs.com/package/powerbackup">
<img src="https://img.shields.io/npm/dm/powerbackup.svg" alt="npm downloads">
</a>
<a href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT">
</a>
<a href="https://nodejs.org/">
<img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg" alt="Node.js">
</a>
<a href="https://github.com/anonnion/powerbackup">
<img src="https://img.shields.io/badge/test%20coverage-97.6%25-brightgreen.svg" alt="Test Coverage">
</a>
</div>
<div class="cta-buttons">
<a href="https://github.com/anonnion/powerbackup" class="btn btn-primary">
๐ฆ Get Started
</a>
<a href="https://github.com/anonnion/powerbackup/blob/master/README.md" class="btn btn-secondary">
๐ Documentation
</a>
</div>
</div>
</div>
</header>
<!-- Features Section -->
<section class="features">
<div class="container">
<div class="section-header">
<h2 class="section-title">Enterprise-Grade Features</h2>
<p class="section-subtitle">
Comprehensive backup and restore capabilities designed for mission-critical environments
</p>
</div>
<div class="features-grid">
<div class="feature-card fade-in-up">
<h3>๐ Advanced Security</h3>
<p>GPG encryption with both symmetric and asymmetric key support. Secure credential management and audit logging for compliance requirements.</p>
</div>
<div class="feature-card fade-in-up">
<h3>๐ Multi-Database Support</h3>
<p>Native support for MySQL and PostgreSQL with optimized dumping and restoration processes. Extensible architecture for additional database types.</p>
</div>
<div class="feature-card fade-in-up">
<h3>โฐ Automated Scheduling</h3>
<p>Enterprise-grade scheduling with PM2, Systemd, Cron, and Windows Task Scheduler. Configurable retention policies and automated pruning.</p>
</div>
<div class="feature-card fade-in-up">
<h3>๐งช Safe Testing</h3>
<p>Test restores to temporary databases for verification without affecting production data. Comprehensive data integrity checks and validation.</p>
</div>
<div class="feature-card fade-in-up">
<h3>๐ Granular Control</h3>
<p>Table-level restores with interactive selection. Schema-only backups for quick snapshots and selective data recovery.</p>
</div>
<div class="feature-card fade-in-up">
<h3>๐๏ธ Optimized Performance</h3>
<p>Gzip compression for efficient storage. Incremental backup support and intelligent retention management to minimize storage costs.</p>
</div>
<div class="feature-card fade-in-up">
<h3>โ๏ธ Cloud Integration</h3>
<p>Direct integration with AWS S3 for cloud storage. Support for multiple retention tiers and automated backup rotation.</p>
</div>
<div class="feature-card fade-in-up">
<h3>๐ Comprehensive Monitoring</h3>
<p>Beautiful, structured logging with emoji-enhanced output. Real-time progress indicators and detailed audit trails.</p>
</div>
<div class="feature-card fade-in-up">
<h3>๐ก๏ธ Production Ready</h3>
<p>97.6% test coverage with comprehensive unit and integration tests. Robust error handling and graceful degradation.</p>
</div>
</div>
</div>
</section>
<!-- Demo Section -->
<section class="demo">
<div class="container">
<div class="demo-content">
<h3>๐ Quick Start Guide</h3>
<pre class="copyable"><code># Install globally
npm install -g powerbackup
# Initialize PowerBackup
powerbackup init
# Configure database binary paths (optional)
powerbackup set-binary-path --mysql /path/to/mysql --postgres /path/to/pgsql
# Add your first database
powerbackup add-db
# Create your first backup
powerbackup create-now mydatabase
# Test restore safely
powerbackup test-restore mydatabase
# Get comprehensive help
powerbackup --help</code></pre>
</div>
</div>
</section>
<!-- Stats Section -->
<section class="stats">
<div class="container">
<div class="section-header">
<h2 class="section-title">Performance Metrics</h2>
<p class="section-subtitle">
Proven reliability and performance in enterprise environments
</p>
</div>
<div class="stats-grid">
<div class="stat-card fade-in-up">
<div class="stat-number">97.6%</div>
<div class="stat-label">Test Coverage</div>
</div>
<div class="stat-card fade-in-up">
<div class="stat-number">42</div>
<div class="stat-label">Tests Passed</div>
</div>
<div class="stat-card fade-in-up">
<div class="stat-number">2</div>
<div class="stat-label">Database Types</div>
</div>
<div class="stat-card fade-in-up">
<div class="stat-number">4</div>
<div class="stat-label">Deployment Options</div>
</div>
<div class="stat-card fade-in-up">
<div class="stat-number">
<img src="https://img.shields.io/npm/dm/powerbackup.svg" alt="npm downloads" style="height: 2.5rem; width: auto;">
</div>
<div class="stat-label">Monthly Downloads</div>
</div>
<div class="stat-card fade-in-up">
<div class="stat-number">
<img src="https://img.shields.io/npm/dt/powerbackup.svg" alt="total downloads" style="height: 2.5rem; width: auto;">
</div>
<div class="stat-label">Total Downloads</div>
</div>
</div>
</div>
</section>
<!-- Download Statistics Section -->
<section class="download-stats">
<div class="container">
<div class="section-header">
<h2 class="section-title">Download Statistics</h2>
<p class="section-subtitle">
Join thousands of developers and enterprises who trust PowerBackup for their database backup needs
</p>
</div>
<div class="download-cards">
<div class="download-card fade-in-up">
<h3>๐ฆ NPM Downloads</h3>
<p>PowerBackup is available on npm and has been downloaded by developers worldwide</p>
<div class="download-badges">
<a href="https://www.npmjs.com/package/powerbackup" class="download-badge">
<img src="https://img.shields.io/npm/v/powerbackup.svg" alt="npm version">
</a>
<a href="https://www.npmjs.com/package/powerbackup" class="download-badge">
<img src="https://img.shields.io/npm/dm/powerbackup.svg" alt="monthly downloads">
</a>
<a href="https://www.npmjs.com/package/powerbackup" class="download-badge">
<img src="https://img.shields.io/npm/dt/powerbackup.svg" alt="total downloads">
</a>
</div>
</div>
<div class="download-card fade-in-up">
<h3>๐ GitHub Stars</h3>
<p>Open source community support and continuous development</p>
<div class="download-badges">
<a href="https://github.com/anonnion/powerbackup" class="download-badge">
<img src="https://img.shields.io/github/stars/anonnion/powerbackup.svg" alt="GitHub stars">
</a>
<a href="https://github.com/anonnion/powerbackup" class="download-badge">
<img src="https://img.shields.io/github/forks/anonnion/powerbackup.svg" alt="GitHub forks">
</a>
<a href="https://github.com/anonnion/powerbackup" class="download-badge">
<img src="https://img.shields.io/github/issues/anonnion/powerbackup.svg" alt="GitHub issues">
</a>
</div>
</div>
<div class="download-card fade-in-up">
<h3>๐ง Installation Methods</h3>
<p>Multiple installation options for different environments</p>
<div class="download-badges">
<a href="https://www.npmjs.com/package/powerbackup" class="download-badge">
<img src="https://img.shields.io/badge/npm%20install%20-g%20powerbackup-blue?style=for-the-badge&logo=npm" alt="npm install">
</a>
<a href="https://github.com/anonnion/powerbackup" class="download-badge">
<img src="https://img.shields.io/badge/GitHub-clone%20repository-green?style=for-the-badge&logo=github" alt="GitHub clone">
</a>
<a href="https://github.com/anonnion/powerbackup/releases" class="download-badge">
<img src="https://img.shields.io/badge/Releases-latest%20version-orange?style=for-the-badge&logo=github" alt="Releases">
</a>
</div>
</div>
</div>
</div>
</section>
<!-- Enterprise Section -->
<section class="enterprise">
<div class="container">
<div class="enterprise-content">
<h2>Built for Enterprise</h2>
<p>
PowerBackup is designed to meet the rigorous demands of enterprise environments.
With comprehensive security features, automated scheduling, and extensive monitoring capabilities,
it provides the reliability and scalability needed for mission-critical database operations.
</p>
<div class="cta-buttons">
<a href="https://github.com/anonnion/powerbackup/blob/master/DEPLOYMENT.md" class="btn btn-primary">
๐ Deployment Guide
</a>
<a href="https://github.com/anonnion/powerbackup/blob/master/CONTRIBUTING.md" class="btn btn-secondary">
๐ค Contribute
</a>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="container">
<div class="footer-content">
<div class="footer-links">
<a href="https://github.com/anonnion/powerbackup">GitHub Repository</a>
<a href="https://github.com/anonnion/powerbackup/blob/master/README.md">Documentation</a>
<a href="https://github.com/anonnion/powerbackup/blob/master/CONTRIBUTING.md">Contributing</a>
<a href="https://github.com/anonnion/powerbackup/blob/master/LICENSE">License</a>
</div>
<p>Built with enterprise-grade reliability and modern development practices</p>
<p>© 2025 PowerBackup Enterprise Team. All rights reserved.</p>
</div>
</div>
</footer>
<!-- JavaScript -->
<script>
// Intersection Observer for animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe elements for animation
document.querySelectorAll('.fade-in-up').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(el);
});
// Copy functionality for code blocks
document.querySelectorAll('.copyable').forEach(pre => {
pre.addEventListener('click', function() {
const text = this.textContent;
navigator.clipboard.writeText(text).then(() => {
// Show feedback
const originalText = this.textContent;
this.textContent = 'Copied!';
setTimeout(() => {
this.textContent = originalText;
}, 1000);
});
});
});
// Smooth scrolling for 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'
});
}
});
});
</script>
</body>
</html>