feat(landing): glassmorphism visual upgrade with dark/light theme toggle
Comprehensive visual overhaul of the Atlas Landing Site: - Dual-theme token system with light mode support via [data-theme="light"] - Glassmorphism + glow effects across all components (blur, gradient borders, glow shadows) - Theme toggle in navbar with localStorage persistence and system preference detection - Hero section: aurora glow orbs, gradient headline, floating screenshot animation - Animated gradient CTA buttons, glass card hover effects with gradient border reveal - Stagger scroll reveal animations, noise texture overlay, section gradient backgrounds - All 18 component files updated, no new files created
This commit is contained in:
@@ -29,6 +29,9 @@ const { channel, label, version, date } = Astro.props;
|
||||
padding: var(--atlas-space-xxs) var(--atlas-space-sm);
|
||||
border-radius: var(--atlas-radius-sm);
|
||||
line-height: 1.4;
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.badge__dot {
|
||||
@@ -47,27 +50,26 @@ const { channel, label, version, date } = Astro.props;
|
||||
}
|
||||
|
||||
.badge--stable {
|
||||
background: rgba(20, 144, 133, 0.15);
|
||||
color: var(--atlas-color-accent);
|
||||
border: 1px solid rgba(20, 144, 133, 0.3);
|
||||
}
|
||||
|
||||
.badge--stable .badge__dot {
|
||||
background-color: var(--atlas-color-accent);
|
||||
animation: pulse-dot 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.badge--prerelease {
|
||||
background: rgba(245, 158, 11, 0.15);
|
||||
color: var(--atlas-color-warning);
|
||||
border: 1px solid rgba(245, 158, 11, 0.3);
|
||||
}
|
||||
|
||||
.badge--prerelease .badge__dot {
|
||||
background-color: var(--atlas-color-warning);
|
||||
animation: pulse-dot 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.badge--none {
|
||||
background: rgba(148, 163, 184, 0.1);
|
||||
color: var(--atlas-color-text-secondary);
|
||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||
}
|
||||
|
||||
@@ -49,8 +49,10 @@ const linkAttrs = external ? { target: '_blank', rel: 'noopener noreferrer' } :
|
||||
.cta--primary {
|
||||
color: #ffffff;
|
||||
padding: var(--atlas-space-md) var(--atlas-space-xxl);
|
||||
background-color: var(--atlas-color-brand);
|
||||
background: var(--atlas-gradient-brand);
|
||||
background-size: 200% 100%;
|
||||
box-shadow: var(--atlas-shadow-cta);
|
||||
animation: gradient-shift 3s ease infinite;
|
||||
}
|
||||
|
||||
.cta--primary:hover {
|
||||
@@ -64,17 +66,40 @@ const linkAttrs = external ? { target: '_blank', rel: 'noopener noreferrer' } :
|
||||
}
|
||||
|
||||
.cta--secondary {
|
||||
color: var(--atlas-color-brand);
|
||||
color: var(--atlas-color-accent);
|
||||
padding: var(--atlas-space-md) var(--atlas-space-xxl);
|
||||
background-color: rgba(20, 144, 133, 0.04);
|
||||
border: 1.5px solid rgba(20, 144, 133, 0.3);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1.5px solid transparent;
|
||||
background-clip: padding-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.cta--secondary::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
padding: 1.5px;
|
||||
background: var(--atlas-gradient-brand);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.cta--secondary:hover {
|
||||
background-color: rgba(20, 144, 133, 0.08);
|
||||
background: var(--atlas-color-bg-raised);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.cta--secondary:hover::before {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.cta--secondary:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
@@ -61,9 +61,18 @@ const copy = t(locale);
|
||||
|
||||
.dev__card {
|
||||
padding: var(--atlas-space-xl);
|
||||
background: var(--atlas-color-bg-base);
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-lg);
|
||||
transition: box-shadow var(--atlas-motion-standard),
|
||||
transform var(--atlas-motion-fast);
|
||||
}
|
||||
|
||||
.dev__card:hover {
|
||||
box-shadow: var(--atlas-glow-card-hover);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.dev__card-title {
|
||||
|
||||
@@ -48,17 +48,38 @@ const copy = t(locale);
|
||||
}
|
||||
|
||||
.faq__item {
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-lg);
|
||||
background: var(--atlas-color-bg-base);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
overflow: hidden;
|
||||
transition: border-color var(--atlas-motion-fast);
|
||||
transition: border-color var(--atlas-motion-fast),
|
||||
box-shadow var(--atlas-motion-standard);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.faq__item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 3px;
|
||||
background: var(--atlas-gradient-brand);
|
||||
opacity: 0;
|
||||
transition: opacity var(--atlas-motion-standard);
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.faq__item[open] {
|
||||
border-color: var(--atlas-color-border-emphasis);
|
||||
}
|
||||
|
||||
.faq__item[open]::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.faq__question {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -83,6 +104,7 @@ const copy = t(locale);
|
||||
|
||||
.faq__item[open] .faq__chevron {
|
||||
transform: rotate(180deg);
|
||||
color: var(--atlas-color-brand);
|
||||
}
|
||||
|
||||
.faq__answer {
|
||||
|
||||
@@ -24,17 +24,40 @@ const { title, value, example, trustCue } = Astro.props;
|
||||
<style>
|
||||
.feature-card {
|
||||
padding: var(--atlas-space-xl);
|
||||
background: var(--atlas-color-bg-surface);
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-xl);
|
||||
box-shadow: var(--atlas-shadow-raised);
|
||||
position: relative;
|
||||
transition: transform var(--atlas-motion-fast),
|
||||
box-shadow var(--atlas-motion-fast);
|
||||
box-shadow var(--atlas-motion-standard);
|
||||
}
|
||||
|
||||
.feature-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
padding: 1px;
|
||||
background: var(--atlas-gradient-brand);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity var(--atlas-motion-standard);
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: scale(1.008);
|
||||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08);
|
||||
transform: scale(1.02);
|
||||
box-shadow: var(--atlas-glow-card-hover);
|
||||
}
|
||||
|
||||
.feature-card:hover::before {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.feature-card__title {
|
||||
|
||||
@@ -15,7 +15,7 @@ const downloadUrl = getDownloadUrl(manifest);
|
||||
const REPO_URL = 'https://github.com/CSZHK/CleanMyPc';
|
||||
---
|
||||
|
||||
<footer class="footer band--dark">
|
||||
<footer class="footer">
|
||||
<div class="footer__inner container">
|
||||
<div class="footer__top">
|
||||
<div class="footer__brand">
|
||||
@@ -49,10 +49,26 @@ const REPO_URL = 'https://github.com/CSZHK/CleanMyPc';
|
||||
|
||||
<style>
|
||||
.footer {
|
||||
border-top: 1px solid var(--atlas-color-border);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border-top: 1px solid transparent;
|
||||
background-clip: padding-box;
|
||||
position: relative;
|
||||
padding-block: var(--atlas-space-section-gap);
|
||||
}
|
||||
|
||||
.footer::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: var(--atlas-gradient-brand);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.footer__inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -37,6 +37,11 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
||||
---
|
||||
|
||||
<section class="hero band--dark" id="hero">
|
||||
<!-- Background glow orbs -->
|
||||
<div class="hero__glow-orb hero__glow-orb--1" aria-hidden="true"></div>
|
||||
<div class="hero__glow-orb hero__glow-orb--2" aria-hidden="true"></div>
|
||||
<div class="hero__glow-orb hero__glow-orb--3" aria-hidden="true"></div>
|
||||
|
||||
<div class="hero__inner container">
|
||||
<div class="hero__content">
|
||||
<ChannelBadge
|
||||
@@ -103,6 +108,42 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
||||
padding-top: calc(80px + var(--atlas-space-section-gap));
|
||||
padding-bottom: var(--atlas-space-section-gap);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Glow orbs — aurora-like background effect */
|
||||
.hero__glow-orb {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
filter: blur(80px);
|
||||
pointer-events: none;
|
||||
animation: pulse-glow 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.hero__glow-orb--1 {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
top: -100px;
|
||||
left: -100px;
|
||||
background: radial-gradient(circle, rgba(20, 144, 133, 0.2) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.hero__glow-orb--2 {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
top: 50%;
|
||||
right: -80px;
|
||||
background: radial-gradient(circle, rgba(52, 211, 153, 0.15) 0%, transparent 70%);
|
||||
animation-delay: -3s;
|
||||
}
|
||||
|
||||
.hero__glow-orb--3 {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
bottom: -50px;
|
||||
left: 30%;
|
||||
background: radial-gradient(circle, rgba(20, 144, 133, 0.12) 0%, transparent 70%);
|
||||
animation-delay: -5s;
|
||||
}
|
||||
|
||||
.hero__inner {
|
||||
@@ -123,6 +164,8 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--atlas-space-lg);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero__headline {
|
||||
@@ -130,7 +173,17 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
||||
font-weight: var(--atlas-text-hero-weight);
|
||||
line-height: var(--atlas-leading-tight);
|
||||
letter-spacing: var(--atlas-tracking-tight);
|
||||
color: var(--atlas-color-text-primary);
|
||||
background: linear-gradient(135deg, #F1F5F9 0%, #34D399 50%, #149085 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
[data-theme="light"] .hero__headline {
|
||||
background: linear-gradient(135deg, #0F172A 0%, #149085 50%, #0F766E 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.hero__subheadline {
|
||||
@@ -170,15 +223,21 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-width: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero__frame {
|
||||
position: relative;
|
||||
border-radius: var(--atlas-radius-xxl);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--atlas-shadow-prominent);
|
||||
border: 1px solid var(--atlas-color-border-emphasis);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
max-width: 100%;
|
||||
box-shadow: var(--atlas-shadow-prominent), var(--atlas-glow-brand);
|
||||
animation: float var(--atlas-duration-float) ease-in-out infinite;
|
||||
}
|
||||
|
||||
.hero__screenshot {
|
||||
|
||||
@@ -13,12 +13,14 @@ const copy = t(locale);
|
||||
<div class="how__inner container">
|
||||
<h2 class="how__title">{copy.howItWorks.sectionTitle}</h2>
|
||||
|
||||
<div class="how__steps">
|
||||
<div class="how__steps stagger-parent">
|
||||
{copy.howItWorks.steps.map((step, i) => (
|
||||
<div class="how__step">
|
||||
<div class="how__step-number" aria-hidden="true">{String(i + 1).padStart(2, '0')}</div>
|
||||
<h3 class="how__step-label">{step.label}</h3>
|
||||
<p class="how__step-desc">{step.description}</p>
|
||||
<div class="how__step fade-in">
|
||||
<div class="how__step-card">
|
||||
<div class="how__step-number" aria-hidden="true">{String(i + 1).padStart(2, '0')}</div>
|
||||
<h3 class="how__step-label">{step.label}</h3>
|
||||
<p class="how__step-desc">{step.description}</p>
|
||||
</div>
|
||||
{i < copy.howItWorks.steps.length - 1 && (
|
||||
<div class="how__connector" aria-hidden="true" />
|
||||
)}
|
||||
@@ -54,12 +56,32 @@ const copy = t(locale);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.how__step-card {
|
||||
padding: var(--atlas-space-xl);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-xl);
|
||||
position: relative;
|
||||
transition: box-shadow var(--atlas-motion-standard),
|
||||
transform var(--atlas-motion-fast);
|
||||
}
|
||||
|
||||
.how__step-card:hover {
|
||||
box-shadow: var(--atlas-glow-card-hover);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.how__step-number {
|
||||
font-family: var(--atlas-font-mono);
|
||||
font-size: var(--atlas-text-section);
|
||||
font-weight: 700;
|
||||
color: var(--atlas-color-brand);
|
||||
opacity: 0.3;
|
||||
background: var(--atlas-gradient-brand);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
opacity: 0.5;
|
||||
margin-bottom: var(--atlas-space-md);
|
||||
}
|
||||
|
||||
@@ -85,11 +107,12 @@ const copy = t(locale);
|
||||
.how__connector {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
top: 50%;
|
||||
right: -12px;
|
||||
width: 24px;
|
||||
height: 2px;
|
||||
background: var(--atlas-color-border-emphasis);
|
||||
background: var(--atlas-gradient-brand);
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -38,6 +38,22 @@ const navItems = [
|
||||
</ul>
|
||||
|
||||
<div class="navbar__actions">
|
||||
<button class="navbar__theme-toggle" id="theme-toggle" aria-label="Toggle theme" title="Toggle theme">
|
||||
<svg class="navbar__theme-icon navbar__theme-icon--sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="5"/>
|
||||
<line x1="12" y1="1" x2="12" y2="3"/>
|
||||
<line x1="12" y1="21" x2="12" y2="23"/>
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
|
||||
<line x1="1" y1="12" x2="3" y2="12"/>
|
||||
<line x1="21" y1="12" x2="23" y2="12"/>
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
|
||||
</svg>
|
||||
<svg class="navbar__theme-icon navbar__theme-icon--moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<a href={altPath} class="navbar__lang" aria-label={`Switch to ${altLabel}`}>
|
||||
{altLabel}
|
||||
</a>
|
||||
@@ -83,6 +99,18 @@ const navItems = [
|
||||
ticking = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Theme toggle
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
if (themeToggle) {
|
||||
themeToggle.addEventListener('click', () => {
|
||||
const html = document.documentElement;
|
||||
const current = html.getAttribute('data-theme');
|
||||
const next = current === 'dark' ? 'light' : 'dark';
|
||||
html.setAttribute('data-theme', next);
|
||||
localStorage.setItem('atlas-theme', next);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -98,9 +126,9 @@ const navItems = [
|
||||
}
|
||||
|
||||
.navbar.is-scrolled {
|
||||
background-color: rgba(13, 15, 17, 0.85);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
background-color: var(--atlas-navbar-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border-bottom: 1px solid var(--atlas-color-border);
|
||||
}
|
||||
|
||||
@@ -157,6 +185,33 @@ const navItems = [
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.navbar__theme-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: var(--atlas-radius-sm);
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
background: transparent;
|
||||
color: var(--atlas-color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: color var(--atlas-motion-fast),
|
||||
border-color var(--atlas-motion-fast);
|
||||
}
|
||||
|
||||
.navbar__theme-toggle:hover {
|
||||
color: var(--atlas-color-text-primary);
|
||||
border-color: var(--atlas-color-border-emphasis);
|
||||
}
|
||||
|
||||
/* Show sun in dark mode, moon in light mode */
|
||||
.navbar__theme-icon--moon { display: none; }
|
||||
.navbar__theme-icon--sun { display: block; }
|
||||
|
||||
[data-theme="light"] .navbar__theme-icon--sun { display: none; }
|
||||
[data-theme="light"] .navbar__theme-icon--moon { display: block; }
|
||||
|
||||
.navbar__lang {
|
||||
font-family: var(--atlas-font-mono);
|
||||
font-size: var(--atlas-text-caption);
|
||||
@@ -189,7 +244,7 @@ const navItems = [
|
||||
right: 0;
|
||||
flex-direction: column;
|
||||
padding: var(--atlas-space-xl);
|
||||
background-color: rgba(13, 15, 17, 0.95);
|
||||
background-color: var(--atlas-mobile-menu-bg);
|
||||
backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid var(--atlas-color-border);
|
||||
gap: var(--atlas-space-lg);
|
||||
|
||||
@@ -69,16 +69,20 @@ const REPO_URL = 'https://github.com/CSZHK/CleanMyPc';
|
||||
flex-direction: column;
|
||||
gap: var(--atlas-space-xxs);
|
||||
padding: var(--atlas-space-xl);
|
||||
background: var(--atlas-color-bg-surface);
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-lg);
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
transition: border-color var(--atlas-motion-fast);
|
||||
transition: box-shadow var(--atlas-motion-standard),
|
||||
transform var(--atlas-motion-fast);
|
||||
}
|
||||
|
||||
a.oss__card:hover {
|
||||
border-color: var(--atlas-color-border-emphasis);
|
||||
box-shadow: var(--atlas-glow-card-hover);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.oss__card-label {
|
||||
|
||||
@@ -50,9 +50,37 @@ const copy = t(locale);
|
||||
text-align: center;
|
||||
gap: var(--atlas-space-lg);
|
||||
padding: var(--atlas-space-xxl);
|
||||
background: var(--atlas-color-bg-surface);
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-xl);
|
||||
position: relative;
|
||||
transition: box-shadow var(--atlas-motion-standard);
|
||||
}
|
||||
|
||||
.problem__card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
padding: 1px;
|
||||
background: var(--atlas-gradient-brand);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity var(--atlas-motion-standard);
|
||||
}
|
||||
|
||||
.problem__card:hover::before {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.problem__card:hover {
|
||||
box-shadow: var(--atlas-glow-card-hover);
|
||||
}
|
||||
|
||||
.problem__before {
|
||||
@@ -63,7 +91,10 @@ const copy = t(locale);
|
||||
|
||||
.problem__arrow {
|
||||
color: var(--atlas-color-brand);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.problem__arrow svg {
|
||||
stroke: currentColor;
|
||||
}
|
||||
|
||||
.problem__after {
|
||||
|
||||
@@ -79,9 +79,18 @@ const manifest = getRelease();
|
||||
|
||||
.safety__card {
|
||||
padding: var(--atlas-space-xl);
|
||||
background: var(--atlas-color-bg-surface);
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-xl);
|
||||
transition: box-shadow var(--atlas-motion-standard),
|
||||
transform var(--atlas-motion-fast);
|
||||
}
|
||||
|
||||
.safety__card:hover {
|
||||
box-shadow: var(--atlas-glow-card-hover);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.safety__card-title {
|
||||
|
||||
@@ -13,9 +13,9 @@ const copy = t(locale);
|
||||
<div class="gallery__inner container">
|
||||
<h2 class="gallery__title">{copy.screenshots.sectionTitle}</h2>
|
||||
|
||||
<div class="gallery__grid" id="screenshot-gallery">
|
||||
<div class="gallery__grid stagger-parent" id="screenshot-gallery">
|
||||
{copy.screenshots.items.map((item, i) => (
|
||||
<figure class="gallery__item" data-index={i}>
|
||||
<figure class="gallery__item fade-in" data-index={i}>
|
||||
<div class="gallery__frame">
|
||||
<img
|
||||
src={item.src}
|
||||
@@ -72,15 +72,38 @@ const copy = t(locale);
|
||||
.gallery__frame {
|
||||
border-radius: var(--atlas-radius-xl);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
box-shadow: var(--atlas-shadow-raised);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
position: relative;
|
||||
transition: transform var(--atlas-motion-fast),
|
||||
box-shadow var(--atlas-motion-fast);
|
||||
box-shadow var(--atlas-motion-standard);
|
||||
}
|
||||
|
||||
.gallery__frame::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
padding: 1px;
|
||||
background: var(--atlas-gradient-brand);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity var(--atlas-motion-standard);
|
||||
}
|
||||
|
||||
.gallery__frame:hover {
|
||||
transform: scale(1.005);
|
||||
box-shadow: var(--atlas-shadow-prominent);
|
||||
transform: scale(1.02);
|
||||
box-shadow: var(--atlas-glow-card-hover);
|
||||
}
|
||||
|
||||
.gallery__frame:hover::before {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.gallery__img {
|
||||
|
||||
@@ -44,8 +44,37 @@ const items = [
|
||||
font-weight: 500;
|
||||
color: var(--atlas-color-text-secondary);
|
||||
padding: var(--atlas-space-xs) var(--atlas-space-lg);
|
||||
border: 1px solid var(--atlas-color-border);
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-full);
|
||||
white-space: nowrap;
|
||||
transition: box-shadow var(--atlas-motion-standard);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.trust-strip__pill::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
padding: 1px;
|
||||
background: var(--atlas-gradient-brand);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
opacity: 0.2;
|
||||
transition: opacity var(--atlas-motion-standard);
|
||||
}
|
||||
|
||||
.trust-strip__pill:hover {
|
||||
box-shadow: 0 0 20px rgba(20, 144, 133, 0.08);
|
||||
}
|
||||
|
||||
.trust-strip__pill:hover::before {
|
||||
opacity: 0.4;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -18,7 +18,7 @@ const altUrl = new URL(altPath, Astro.site);
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang={htmlLang}>
|
||||
<html lang={htmlLang} data-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
@@ -69,11 +69,21 @@ const altUrl = new URL(altPath, Astro.site);
|
||||
"description": description,
|
||||
"url": canonicalUrl.href
|
||||
})} />
|
||||
|
||||
<!-- Theme initialization (prevent flash) -->
|
||||
<script is:inline>
|
||||
(function() {
|
||||
const stored = localStorage.getItem('atlas-theme');
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const theme = stored || (prefersDark ? 'dark' : 'light');
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
|
||||
<!-- Scroll-reveal observer -->
|
||||
<!-- Scroll-reveal observer with stagger support -->
|
||||
<script>
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
@@ -88,6 +98,16 @@ const altUrl = new URL(altPath, Astro.site);
|
||||
);
|
||||
|
||||
document.querySelectorAll('.fade-in').forEach((el) => observer.observe(el));
|
||||
|
||||
// Stagger animation support
|
||||
document.querySelectorAll('.stagger-parent').forEach((parent) => {
|
||||
const children = parent.querySelectorAll('.fade-in');
|
||||
children.forEach((child, i) => {
|
||||
child.style.setProperty('--stagger-index', String(i));
|
||||
child.style.transitionDelay = `calc(var(--atlas-stagger-delay) * ${i})`;
|
||||
observer.observe(child);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -51,6 +51,16 @@
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* ── Theme Defaults ────────────────────────────────── */
|
||||
|
||||
html {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
/* ── Base ──────────────────────────────────────────── */
|
||||
|
||||
body {
|
||||
@@ -59,6 +69,27 @@ body {
|
||||
font-weight: var(--atlas-text-body-weight);
|
||||
color: var(--atlas-color-text-primary);
|
||||
background-color: var(--atlas-color-bg-base);
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Noise texture overlay */
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
opacity: var(--atlas-noise-opacity);
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
||||
background-repeat: repeat;
|
||||
background-size: 256px 256px;
|
||||
}
|
||||
|
||||
/* Ensure content sits above noise */
|
||||
body > * {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* ══════════════════════════════════════════════════════
|
||||
Atlas Landing Page — Design Tokens
|
||||
Source of truth: AtlasBrand.swift + AtlasColors.xcassets
|
||||
Theme: "Precision Utility" (dark-only)
|
||||
Theme: "Precision Utility" (dark + light)
|
||||
══════════════════════════════════════════════════════ */
|
||||
|
||||
:root {
|
||||
@@ -36,6 +36,15 @@
|
||||
--atlas-color-border: rgba(241, 245, 249, 0.08);
|
||||
--atlas-color-border-emphasis: rgba(241, 245, 249, 0.14);
|
||||
|
||||
/* ── Gradients & Effects ─────────────────────────── */
|
||||
--atlas-gradient-brand: linear-gradient(135deg, #149085, #34D399);
|
||||
--atlas-gradient-hero: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(20, 144, 133, 0.15) 0%, transparent 70%);
|
||||
--atlas-glow-brand: 0 0 60px rgba(20, 144, 133, 0.15);
|
||||
--atlas-glow-card-hover: 0 8px 30px rgba(20, 144, 133, 0.12), 0 0 0 1px rgba(52, 211, 153, 0.1);
|
||||
--atlas-glass-bg: rgba(255, 255, 255, 0.04);
|
||||
--atlas-glass-border: rgba(255, 255, 255, 0.08);
|
||||
--atlas-noise-opacity: 0.03;
|
||||
|
||||
/* ── Typography ──────────────────────────────────── */
|
||||
--atlas-font-display: 'Space Grotesk', system-ui, sans-serif;
|
||||
--atlas-font-body: 'Instrument Sans', system-ui, sans-serif;
|
||||
@@ -96,9 +105,46 @@
|
||||
--atlas-motion-standard: 220ms cubic-bezier(0.2, 0, 0, 1);
|
||||
--atlas-motion-slow: 350ms cubic-bezier(0.2, 0, 0, 1);
|
||||
--atlas-stagger-delay: 80ms;
|
||||
--atlas-duration-float: 6s;
|
||||
|
||||
/* ── Layout ──────────────────────────────────────── */
|
||||
--atlas-width-reading: 920px;
|
||||
--atlas-width-content: 1080px;
|
||||
--atlas-width-workspace: 1200px;
|
||||
|
||||
/* ── Navbar ──────────────────────────────────────── */
|
||||
--atlas-navbar-bg: rgba(13, 15, 17, 0.85);
|
||||
--atlas-mobile-menu-bg: rgba(13, 15, 17, 0.95);
|
||||
}
|
||||
|
||||
/* ── Light Theme Overrides ─────────────────────────── */
|
||||
|
||||
[data-theme="light"] {
|
||||
--atlas-color-bg-base: #FAFBFC;
|
||||
--atlas-color-bg-surface: #F1F5F9;
|
||||
--atlas-color-bg-surface-hover: #E2E8F0;
|
||||
--atlas-color-bg-raised: rgba(0, 0, 0, 0.02);
|
||||
--atlas-color-bg-code: #F8FAFC;
|
||||
|
||||
--atlas-color-text-primary: #0F172A;
|
||||
--atlas-color-text-secondary: #475569;
|
||||
--atlas-color-text-tertiary: rgba(71, 85, 105, 0.6);
|
||||
|
||||
--atlas-color-border: rgba(15, 23, 42, 0.08);
|
||||
--atlas-color-border-emphasis: rgba(15, 23, 42, 0.14);
|
||||
|
||||
--atlas-gradient-hero: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(20, 144, 133, 0.08) 0%, transparent 70%);
|
||||
--atlas-glow-brand: 0 0 60px rgba(20, 144, 133, 0.1);
|
||||
--atlas-glow-card-hover: 0 8px 30px rgba(20, 144, 133, 0.08), 0 0 0 1px rgba(52, 211, 153, 0.08);
|
||||
--atlas-glass-bg: rgba(255, 255, 255, 0.7);
|
||||
--atlas-glass-border: rgba(0, 0, 0, 0.08);
|
||||
--atlas-noise-opacity: 0.02;
|
||||
|
||||
--atlas-shadow-raised: 0 10px 18px rgba(0, 0, 0, 0.04);
|
||||
--atlas-shadow-prominent: 0 16px 28px rgba(0, 0, 0, 0.06);
|
||||
--atlas-shadow-cta: 0 6px 12px rgba(20, 144, 133, 0.2);
|
||||
--atlas-shadow-cta-hover: 0 8px 20px rgba(20, 144, 133, 0.3);
|
||||
|
||||
--atlas-navbar-bg: rgba(250, 251, 252, 0.85);
|
||||
--atlas-mobile-menu-bg: rgba(250, 251, 252, 0.95);
|
||||
}
|
||||
|
||||
@@ -23,10 +23,20 @@
|
||||
|
||||
.band--dark {
|
||||
background-color: var(--atlas-color-bg-base);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.band--dark::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: radial-gradient(ellipse 60% 40% at 50% 50%, rgba(20, 144, 133, 0.04) 0%, transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.band--surface {
|
||||
background-color: var(--atlas-color-bg-surface);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* ── Accessibility ─────────────────────────────────── */
|
||||
@@ -85,3 +95,91 @@
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* ── Glass Card ──────────────────────────────────── */
|
||||
|
||||
.glass-card {
|
||||
background: var(--atlas-glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--atlas-glass-border);
|
||||
border-radius: var(--atlas-radius-xl);
|
||||
}
|
||||
|
||||
/* ── Gradient Text ───────────────────────────────── */
|
||||
|
||||
.gradient-text {
|
||||
background: var(--atlas-gradient-brand);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* ── Glow Hover ──────────────────────────────────── */
|
||||
|
||||
.glow-hover {
|
||||
transition: box-shadow var(--atlas-motion-standard),
|
||||
transform var(--atlas-motion-fast);
|
||||
}
|
||||
|
||||
.glow-hover:hover {
|
||||
box-shadow: var(--atlas-glow-card-hover);
|
||||
}
|
||||
|
||||
/* ── Stagger Delays ──────────────────────────────── */
|
||||
|
||||
.stagger-1 { transition-delay: calc(var(--atlas-stagger-delay) * 0); }
|
||||
.stagger-2 { transition-delay: calc(var(--atlas-stagger-delay) * 1); }
|
||||
.stagger-3 { transition-delay: calc(var(--atlas-stagger-delay) * 2); }
|
||||
.stagger-4 { transition-delay: calc(var(--atlas-stagger-delay) * 3); }
|
||||
.stagger-5 { transition-delay: calc(var(--atlas-stagger-delay) * 4); }
|
||||
.stagger-6 { transition-delay: calc(var(--atlas-stagger-delay) * 5); }
|
||||
|
||||
/* ── Float Animation ─────────────────────────────── */
|
||||
|
||||
.float-animation {
|
||||
animation: float var(--atlas-duration-float) ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* ── Gradient Border ─────────────────────────────── */
|
||||
|
||||
.gradient-border {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gradient-border::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
padding: 1px;
|
||||
background: var(--atlas-gradient-brand);
|
||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ── Keyframe Animations ─────────────────────────── */
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-8px); }
|
||||
}
|
||||
|
||||
@keyframes gradient-shift {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
}
|
||||
|
||||
@keyframes pulse-glow {
|
||||
0%, 100% { opacity: 0.15; }
|
||||
50% { opacity: 0.25; }
|
||||
}
|
||||
|
||||
@keyframes pulse-dot {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.4; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user