Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8116eee6c1 | ||
|
|
7930c73db2 | ||
|
|
84a2a2d0b7 | ||
|
|
bdd370ec98 | ||
|
|
71807bdeb5 |
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@@ -171,15 +171,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate release body
|
- name: Generate release body
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ needs.native.outputs.packaging_mode }}" == "development" ]]; then
|
./scripts/atlas/generate-release-body.sh "${GITHUB_REF_NAME#V}" "${{ needs.native.outputs.packaging_mode }}" RELEASE_BODY.md
|
||||||
{
|
|
||||||
echo "Native macOS assets in this tag were packaged in development mode because Developer ID release-signing credentials were not configured for this run."
|
|
||||||
echo
|
|
||||||
echo "These \`.zip\`, \`.dmg\`, and \`.pkg\` files are intended for internal testing or developer use. macOS Gatekeeper may require \`Open Anyway\` or a right-click \`Open\` flow before launch."
|
|
||||||
} > RELEASE_BODY.md
|
|
||||||
else
|
|
||||||
echo "Native macOS assets in this tag were packaged in CI using Developer ID signing and notarization, then uploaded alongside the existing command-line release artifacts." > RELEASE_BODY.md
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
run: ls -R bin/
|
run: ls -R bin/
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ const { channel, label, version, date } = Astro.props;
|
|||||||
padding: var(--atlas-space-xxs) var(--atlas-space-sm);
|
padding: var(--atlas-space-xxs) var(--atlas-space-sm);
|
||||||
border-radius: var(--atlas-radius-sm);
|
border-radius: var(--atlas-radius-sm);
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
background: var(--atlas-glass-bg);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge__dot {
|
.badge__dot {
|
||||||
@@ -47,27 +50,26 @@ const { channel, label, version, date } = Astro.props;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.badge--stable {
|
.badge--stable {
|
||||||
background: rgba(20, 144, 133, 0.15);
|
|
||||||
color: var(--atlas-color-accent);
|
color: var(--atlas-color-accent);
|
||||||
border: 1px solid rgba(20, 144, 133, 0.3);
|
border: 1px solid rgba(20, 144, 133, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge--stable .badge__dot {
|
.badge--stable .badge__dot {
|
||||||
background-color: var(--atlas-color-accent);
|
background-color: var(--atlas-color-accent);
|
||||||
|
animation: pulse-dot 2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge--prerelease {
|
.badge--prerelease {
|
||||||
background: rgba(245, 158, 11, 0.15);
|
|
||||||
color: var(--atlas-color-warning);
|
color: var(--atlas-color-warning);
|
||||||
border: 1px solid rgba(245, 158, 11, 0.3);
|
border: 1px solid rgba(245, 158, 11, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge--prerelease .badge__dot {
|
.badge--prerelease .badge__dot {
|
||||||
background-color: var(--atlas-color-warning);
|
background-color: var(--atlas-color-warning);
|
||||||
|
animation: pulse-dot 2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge--none {
|
.badge--none {
|
||||||
background: rgba(148, 163, 184, 0.1);
|
|
||||||
color: var(--atlas-color-text-secondary);
|
color: var(--atlas-color-text-secondary);
|
||||||
border: 1px solid rgba(148, 163, 184, 0.2);
|
border: 1px solid rgba(148, 163, 184, 0.2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,8 +49,10 @@ const linkAttrs = external ? { target: '_blank', rel: 'noopener noreferrer' } :
|
|||||||
.cta--primary {
|
.cta--primary {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
padding: var(--atlas-space-md) var(--atlas-space-xxl);
|
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);
|
box-shadow: var(--atlas-shadow-cta);
|
||||||
|
animation: gradient-shift 3s ease infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cta--primary:hover {
|
.cta--primary:hover {
|
||||||
@@ -64,17 +66,40 @@ const linkAttrs = external ? { target: '_blank', rel: 'noopener noreferrer' } :
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cta--secondary {
|
.cta--secondary {
|
||||||
color: var(--atlas-color-brand);
|
color: var(--atlas-color-accent);
|
||||||
padding: var(--atlas-space-md) var(--atlas-space-xxl);
|
padding: var(--atlas-space-md) var(--atlas-space-xxl);
|
||||||
background-color: rgba(20, 144, 133, 0.04);
|
background: var(--atlas-glass-bg);
|
||||||
border: 1.5px solid rgba(20, 144, 133, 0.3);
|
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 {
|
.cta--secondary:hover {
|
||||||
background-color: rgba(20, 144, 133, 0.08);
|
background: var(--atlas-color-bg-raised);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cta--secondary:hover::before {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
.cta--secondary:active {
|
.cta--secondary:active {
|
||||||
transform: scale(0.97);
|
transform: scale(0.97);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,9 +61,18 @@ const copy = t(locale);
|
|||||||
|
|
||||||
.dev__card {
|
.dev__card {
|
||||||
padding: var(--atlas-space-xl);
|
padding: var(--atlas-space-xl);
|
||||||
background: var(--atlas-color-bg-base);
|
background: var(--atlas-glass-bg);
|
||||||
border: 1px solid var(--atlas-color-border);
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--atlas-glass-border);
|
||||||
border-radius: var(--atlas-radius-lg);
|
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 {
|
.dev__card-title {
|
||||||
|
|||||||
@@ -48,17 +48,38 @@ const copy = t(locale);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.faq__item {
|
.faq__item {
|
||||||
border: 1px solid var(--atlas-color-border);
|
border: 1px solid var(--atlas-glass-border);
|
||||||
border-radius: var(--atlas-radius-lg);
|
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;
|
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] {
|
.faq__item[open] {
|
||||||
border-color: var(--atlas-color-border-emphasis);
|
border-color: var(--atlas-color-border-emphasis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.faq__item[open]::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.faq__question {
|
.faq__question {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -83,6 +104,7 @@ const copy = t(locale);
|
|||||||
|
|
||||||
.faq__item[open] .faq__chevron {
|
.faq__item[open] .faq__chevron {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
|
color: var(--atlas-color-brand);
|
||||||
}
|
}
|
||||||
|
|
||||||
.faq__answer {
|
.faq__answer {
|
||||||
|
|||||||
@@ -24,17 +24,40 @@ const { title, value, example, trustCue } = Astro.props;
|
|||||||
<style>
|
<style>
|
||||||
.feature-card {
|
.feature-card {
|
||||||
padding: var(--atlas-space-xl);
|
padding: var(--atlas-space-xl);
|
||||||
background: var(--atlas-color-bg-surface);
|
background: var(--atlas-glass-bg);
|
||||||
border: 1px solid var(--atlas-color-border);
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--atlas-glass-border);
|
||||||
border-radius: var(--atlas-radius-xl);
|
border-radius: var(--atlas-radius-xl);
|
||||||
box-shadow: var(--atlas-shadow-raised);
|
box-shadow: var(--atlas-shadow-raised);
|
||||||
|
position: relative;
|
||||||
transition: transform var(--atlas-motion-fast),
|
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 {
|
.feature-card:hover {
|
||||||
transform: scale(1.008);
|
transform: scale(1.02);
|
||||||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08);
|
box-shadow: var(--atlas-glow-card-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-card:hover::before {
|
||||||
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-card__title {
|
.feature-card__title {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const downloadUrl = getDownloadUrl(manifest);
|
|||||||
const REPO_URL = 'https://github.com/CSZHK/CleanMyPc';
|
const REPO_URL = 'https://github.com/CSZHK/CleanMyPc';
|
||||||
---
|
---
|
||||||
|
|
||||||
<footer class="footer band--dark">
|
<footer class="footer">
|
||||||
<div class="footer__inner container">
|
<div class="footer__inner container">
|
||||||
<div class="footer__top">
|
<div class="footer__top">
|
||||||
<div class="footer__brand">
|
<div class="footer__brand">
|
||||||
@@ -49,10 +49,26 @@ const REPO_URL = 'https://github.com/CSZHK/CleanMyPc';
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.footer {
|
.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);
|
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 {
|
.footer__inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
|||||||
---
|
---
|
||||||
|
|
||||||
<section class="hero band--dark" id="hero">
|
<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__inner container">
|
||||||
<div class="hero__content">
|
<div class="hero__content">
|
||||||
<ChannelBadge
|
<ChannelBadge
|
||||||
@@ -103,6 +108,42 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
|||||||
padding-top: calc(80px + var(--atlas-space-section-gap));
|
padding-top: calc(80px + var(--atlas-space-section-gap));
|
||||||
padding-bottom: var(--atlas-space-section-gap);
|
padding-bottom: var(--atlas-space-section-gap);
|
||||||
overflow: hidden;
|
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 {
|
.hero__inner {
|
||||||
@@ -123,6 +164,8 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--atlas-space-lg);
|
gap: var(--atlas-space-lg);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero__headline {
|
.hero__headline {
|
||||||
@@ -130,7 +173,17 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
|||||||
font-weight: var(--atlas-text-hero-weight);
|
font-weight: var(--atlas-text-hero-weight);
|
||||||
line-height: var(--atlas-leading-tight);
|
line-height: var(--atlas-leading-tight);
|
||||||
letter-spacing: var(--atlas-tracking-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 {
|
.hero__subheadline {
|
||||||
@@ -170,15 +223,21 @@ const publishedDate = formatDate(manifest.publishedAt, locale);
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero__frame {
|
.hero__frame {
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: var(--atlas-radius-xxl);
|
border-radius: var(--atlas-radius-xxl);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: var(--atlas-shadow-prominent);
|
background: var(--atlas-glass-bg);
|
||||||
border: 1px solid var(--atlas-color-border-emphasis);
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--atlas-glass-border);
|
||||||
max-width: 100%;
|
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 {
|
.hero__screenshot {
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ const copy = t(locale);
|
|||||||
<div class="how__inner container">
|
<div class="how__inner container">
|
||||||
<h2 class="how__title">{copy.howItWorks.sectionTitle}</h2>
|
<h2 class="how__title">{copy.howItWorks.sectionTitle}</h2>
|
||||||
|
|
||||||
<div class="how__steps">
|
<div class="how__steps stagger-parent">
|
||||||
{copy.howItWorks.steps.map((step, i) => (
|
{copy.howItWorks.steps.map((step, i) => (
|
||||||
<div class="how__step">
|
<div class="how__step fade-in">
|
||||||
<div class="how__step-number" aria-hidden="true">{String(i + 1).padStart(2, '0')}</div>
|
<div class="how__step-card">
|
||||||
<h3 class="how__step-label">{step.label}</h3>
|
<div class="how__step-number" aria-hidden="true">{String(i + 1).padStart(2, '0')}</div>
|
||||||
<p class="how__step-desc">{step.description}</p>
|
<h3 class="how__step-label">{step.label}</h3>
|
||||||
|
<p class="how__step-desc">{step.description}</p>
|
||||||
|
</div>
|
||||||
{i < copy.howItWorks.steps.length - 1 && (
|
{i < copy.howItWorks.steps.length - 1 && (
|
||||||
<div class="how__connector" aria-hidden="true" />
|
<div class="how__connector" aria-hidden="true" />
|
||||||
)}
|
)}
|
||||||
@@ -54,12 +56,32 @@ const copy = t(locale);
|
|||||||
position: relative;
|
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 {
|
.how__step-number {
|
||||||
font-family: var(--atlas-font-mono);
|
font-family: var(--atlas-font-mono);
|
||||||
font-size: var(--atlas-text-section);
|
font-size: var(--atlas-text-section);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--atlas-color-brand);
|
background: var(--atlas-gradient-brand);
|
||||||
opacity: 0.3;
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
opacity: 0.5;
|
||||||
margin-bottom: var(--atlas-space-md);
|
margin-bottom: var(--atlas-space-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,11 +107,12 @@ const copy = t(locale);
|
|||||||
.how__connector {
|
.how__connector {
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 28px;
|
top: 50%;
|
||||||
right: -12px;
|
right: -12px;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background: var(--atlas-color-border-emphasis);
|
background: var(--atlas-gradient-brand);
|
||||||
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -38,6 +38,22 @@ const navItems = [
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="navbar__actions">
|
<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}`}>
|
<a href={altPath} class="navbar__lang" aria-label={`Switch to ${altLabel}`}>
|
||||||
{altLabel}
|
{altLabel}
|
||||||
</a>
|
</a>
|
||||||
@@ -83,6 +99,18 @@ const navItems = [
|
|||||||
ticking = true;
|
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>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -98,9 +126,9 @@ const navItems = [
|
|||||||
}
|
}
|
||||||
|
|
||||||
.navbar.is-scrolled {
|
.navbar.is-scrolled {
|
||||||
background-color: rgba(13, 15, 17, 0.85);
|
background-color: var(--atlas-navbar-bg);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(20px);
|
||||||
-webkit-backdrop-filter: blur(12px);
|
-webkit-backdrop-filter: blur(20px);
|
||||||
border-bottom: 1px solid var(--atlas-color-border);
|
border-bottom: 1px solid var(--atlas-color-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +185,33 @@ const navItems = [
|
|||||||
flex-shrink: 0;
|
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 {
|
.navbar__lang {
|
||||||
font-family: var(--atlas-font-mono);
|
font-family: var(--atlas-font-mono);
|
||||||
font-size: var(--atlas-text-caption);
|
font-size: var(--atlas-text-caption);
|
||||||
@@ -189,7 +244,7 @@ const navItems = [
|
|||||||
right: 0;
|
right: 0;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: var(--atlas-space-xl);
|
padding: var(--atlas-space-xl);
|
||||||
background-color: rgba(13, 15, 17, 0.95);
|
background-color: var(--atlas-mobile-menu-bg);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px);
|
||||||
border-bottom: 1px solid var(--atlas-color-border);
|
border-bottom: 1px solid var(--atlas-color-border);
|
||||||
gap: var(--atlas-space-lg);
|
gap: var(--atlas-space-lg);
|
||||||
|
|||||||
@@ -69,16 +69,20 @@ const REPO_URL = 'https://github.com/CSZHK/CleanMyPc';
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--atlas-space-xxs);
|
gap: var(--atlas-space-xxs);
|
||||||
padding: var(--atlas-space-xl);
|
padding: var(--atlas-space-xl);
|
||||||
background: var(--atlas-color-bg-surface);
|
background: var(--atlas-glass-bg);
|
||||||
border: 1px solid var(--atlas-color-border);
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--atlas-glass-border);
|
||||||
border-radius: var(--atlas-radius-lg);
|
border-radius: var(--atlas-radius-lg);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
position: relative;
|
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 {
|
a.oss__card:hover {
|
||||||
border-color: var(--atlas-color-border-emphasis);
|
box-shadow: var(--atlas-glow-card-hover);
|
||||||
|
transform: translateY(-2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.oss__card-label {
|
.oss__card-label {
|
||||||
|
|||||||
@@ -50,9 +50,37 @@ const copy = t(locale);
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
gap: var(--atlas-space-lg);
|
gap: var(--atlas-space-lg);
|
||||||
padding: var(--atlas-space-xxl);
|
padding: var(--atlas-space-xxl);
|
||||||
background: var(--atlas-color-bg-surface);
|
background: var(--atlas-glass-bg);
|
||||||
border: 1px solid var(--atlas-color-border);
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--atlas-glass-border);
|
||||||
border-radius: var(--atlas-radius-xl);
|
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 {
|
.problem__before {
|
||||||
@@ -63,7 +91,10 @@ const copy = t(locale);
|
|||||||
|
|
||||||
.problem__arrow {
|
.problem__arrow {
|
||||||
color: var(--atlas-color-brand);
|
color: var(--atlas-color-brand);
|
||||||
opacity: 0.6;
|
}
|
||||||
|
|
||||||
|
.problem__arrow svg {
|
||||||
|
stroke: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.problem__after {
|
.problem__after {
|
||||||
|
|||||||
@@ -79,9 +79,18 @@ const manifest = getRelease();
|
|||||||
|
|
||||||
.safety__card {
|
.safety__card {
|
||||||
padding: var(--atlas-space-xl);
|
padding: var(--atlas-space-xl);
|
||||||
background: var(--atlas-color-bg-surface);
|
background: var(--atlas-glass-bg);
|
||||||
border: 1px solid var(--atlas-color-border);
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--atlas-glass-border);
|
||||||
border-radius: var(--atlas-radius-xl);
|
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 {
|
.safety__card-title {
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ const copy = t(locale);
|
|||||||
<div class="gallery__inner container">
|
<div class="gallery__inner container">
|
||||||
<h2 class="gallery__title">{copy.screenshots.sectionTitle}</h2>
|
<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) => (
|
{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">
|
<div class="gallery__frame">
|
||||||
<img
|
<img
|
||||||
src={item.src}
|
src={item.src}
|
||||||
@@ -72,15 +72,38 @@ const copy = t(locale);
|
|||||||
.gallery__frame {
|
.gallery__frame {
|
||||||
border-radius: var(--atlas-radius-xl);
|
border-radius: var(--atlas-radius-xl);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid var(--atlas-color-border);
|
background: var(--atlas-glass-bg);
|
||||||
box-shadow: var(--atlas-shadow-raised);
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
border: 1px solid var(--atlas-glass-border);
|
||||||
|
position: relative;
|
||||||
transition: transform var(--atlas-motion-fast),
|
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 {
|
.gallery__frame:hover {
|
||||||
transform: scale(1.005);
|
transform: scale(1.02);
|
||||||
box-shadow: var(--atlas-shadow-prominent);
|
box-shadow: var(--atlas-glow-card-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery__frame:hover::before {
|
||||||
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gallery__img {
|
.gallery__img {
|
||||||
|
|||||||
@@ -44,8 +44,37 @@ const items = [
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--atlas-color-text-secondary);
|
color: var(--atlas-color-text-secondary);
|
||||||
padding: var(--atlas-space-xs) var(--atlas-space-lg);
|
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);
|
border-radius: var(--atlas-radius-full);
|
||||||
white-space: nowrap;
|
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>
|
</style>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const altUrl = new URL(altPath, Astro.site);
|
|||||||
---
|
---
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang={htmlLang}>
|
<html lang={htmlLang} data-theme="dark">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
@@ -69,11 +69,21 @@ const altUrl = new URL(altPath, Astro.site);
|
|||||||
"description": description,
|
"description": description,
|
||||||
"url": canonicalUrl.href
|
"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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
<!-- Scroll-reveal observer -->
|
<!-- Scroll-reveal observer with stagger support -->
|
||||||
<script>
|
<script>
|
||||||
const observer = new IntersectionObserver(
|
const observer = new IntersectionObserver(
|
||||||
(entries) => {
|
(entries) => {
|
||||||
@@ -88,6 +98,16 @@ const altUrl = new URL(altPath, Astro.site);
|
|||||||
);
|
);
|
||||||
|
|
||||||
document.querySelectorAll('.fade-in').forEach((el) => observer.observe(el));
|
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>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -51,6 +51,16 @@
|
|||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Theme Defaults ────────────────────────────────── */
|
||||||
|
|
||||||
|
html {
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="light"] {
|
||||||
|
color-scheme: light;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Base ──────────────────────────────────────────── */
|
/* ── Base ──────────────────────────────────────────── */
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -59,6 +69,27 @@ body {
|
|||||||
font-weight: var(--atlas-text-body-weight);
|
font-weight: var(--atlas-text-body-weight);
|
||||||
color: var(--atlas-color-text-primary);
|
color: var(--atlas-color-text-primary);
|
||||||
background-color: var(--atlas-color-bg-base);
|
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 {
|
h1, h2, h3 {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* ══════════════════════════════════════════════════════
|
/* ══════════════════════════════════════════════════════
|
||||||
Atlas Landing Page — Design Tokens
|
Atlas Landing Page — Design Tokens
|
||||||
Source of truth: AtlasBrand.swift + AtlasColors.xcassets
|
Source of truth: AtlasBrand.swift + AtlasColors.xcassets
|
||||||
Theme: "Precision Utility" (dark-only)
|
Theme: "Precision Utility" (dark + light)
|
||||||
══════════════════════════════════════════════════════ */
|
══════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
@@ -36,6 +36,15 @@
|
|||||||
--atlas-color-border: rgba(241, 245, 249, 0.08);
|
--atlas-color-border: rgba(241, 245, 249, 0.08);
|
||||||
--atlas-color-border-emphasis: rgba(241, 245, 249, 0.14);
|
--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 ──────────────────────────────────── */
|
/* ── Typography ──────────────────────────────────── */
|
||||||
--atlas-font-display: 'Space Grotesk', system-ui, sans-serif;
|
--atlas-font-display: 'Space Grotesk', system-ui, sans-serif;
|
||||||
--atlas-font-body: 'Instrument Sans', 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-standard: 220ms cubic-bezier(0.2, 0, 0, 1);
|
||||||
--atlas-motion-slow: 350ms cubic-bezier(0.2, 0, 0, 1);
|
--atlas-motion-slow: 350ms cubic-bezier(0.2, 0, 0, 1);
|
||||||
--atlas-stagger-delay: 80ms;
|
--atlas-stagger-delay: 80ms;
|
||||||
|
--atlas-duration-float: 6s;
|
||||||
|
|
||||||
/* ── Layout ──────────────────────────────────────── */
|
/* ── Layout ──────────────────────────────────────── */
|
||||||
--atlas-width-reading: 920px;
|
--atlas-width-reading: 920px;
|
||||||
--atlas-width-content: 1080px;
|
--atlas-width-content: 1080px;
|
||||||
--atlas-width-workspace: 1200px;
|
--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 {
|
.band--dark {
|
||||||
background-color: var(--atlas-color-bg-base);
|
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 {
|
.band--surface {
|
||||||
background-color: var(--atlas-color-bg-surface);
|
background-color: var(--atlas-color-bg-surface);
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Accessibility ─────────────────────────────────── */
|
/* ── Accessibility ─────────────────────────────────── */
|
||||||
@@ -85,3 +95,91 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
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; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,15 +10,22 @@ Drive `v1.0.3` from release-prepared source state to a pushed release tag and ob
|
|||||||
- [x] Rebuild native artifacts and verify the bundled app reports `1.0.3 (4)`.
|
- [x] Rebuild native artifacts and verify the bundled app reports `1.0.3 (4)`.
|
||||||
- [x] Reinstall the local DMG candidate and verify the installed app reports `1.0.3 (4)`.
|
- [x] Reinstall the local DMG candidate and verify the installed app reports `1.0.3 (4)`.
|
||||||
- [x] Run `./scripts/atlas/full-acceptance.sh` on the release candidate.
|
- [x] Run `./scripts/atlas/full-acceptance.sh` on the release candidate.
|
||||||
- [ ] Clean the worktree by resolving remaining README and screenshot collateral updates.
|
- [x] Clean the worktree by resolving remaining README and screenshot collateral updates.
|
||||||
- [ ] Commit release-collateral updates required for a clean tagging state.
|
- [x] Commit release-collateral updates required for a clean tagging state.
|
||||||
- [ ] Create annotated tag `V1.0.3`.
|
- [x] Create annotated tag `V1.0.3`.
|
||||||
- [ ] Push `main` and `V1.0.3` to `origin`.
|
- [x] Push `main` and `V1.0.3` to `origin`.
|
||||||
- [ ] Observe the GitHub `release.yml` workflow result.
|
- [x] Observe the GitHub `release.yml` workflow result.
|
||||||
- [ ] Confirm whether GitHub published a normal release or a prerelease fallback.
|
- [x] Confirm whether GitHub published a normal release or a prerelease fallback.
|
||||||
|
|
||||||
## Known Release Gate
|
## Known Release Gate
|
||||||
|
|
||||||
- Local signing preflight still reports missing `Developer ID Application`, `Developer ID Installer`, and `ATLAS_NOTARY_PROFILE`.
|
- Local signing preflight still reports missing `Developer ID Application`, `Developer ID Installer`, and `ATLAS_NOTARY_PROFILE`.
|
||||||
- GitHub Actions may still produce a formal signed release if the required repository secrets are configured.
|
- GitHub Actions may still produce a formal signed release if the required repository secrets are configured.
|
||||||
- If those secrets are missing, the tag push will publish a development-signed prerelease instead of a formal signed release.
|
- If those secrets are missing, the tag push will publish a development-signed prerelease instead of a formal signed release.
|
||||||
|
|
||||||
|
## Outcome
|
||||||
|
|
||||||
|
- Git tag `V1.0.3` was pushed successfully.
|
||||||
|
- GitHub published `https://github.com/CSZHK/CleanMyPc/releases/tag/V1.0.3`.
|
||||||
|
- The published release is `prerelease=true`, not a formal signed release.
|
||||||
|
- The release body confirms GitHub Actions fell back to development-mode native packaging because `Developer ID` release-signing credentials were not configured for that run.
|
||||||
|
|||||||
@@ -97,6 +97,13 @@ KEEP_INSTALLED_APP=1 ./scripts/atlas/verify-dmg-install.sh
|
|||||||
|
|
||||||
Tagged pushes matching `V*` now reuse the same packaging flow in CI and attach native release assets to the GitHub Release created by `.github/workflows/release.yml`.
|
Tagged pushes matching `V*` now reuse the same packaging flow in CI and attach native release assets to the GitHub Release created by `.github/workflows/release.yml`.
|
||||||
|
|
||||||
|
The GitHub Release body is generated from the matching version section in `CHANGELOG.md`, then appends the actual packaging mode note:
|
||||||
|
|
||||||
|
- `developer-id` -> signed/notarized packaging note
|
||||||
|
- `development` -> prerelease fallback note
|
||||||
|
|
||||||
|
If a changelog section is missing for the pushed tag version, the workflow falls back to a short placeholder instead of publishing an empty body.
|
||||||
|
|
||||||
Required GitHub Actions secrets:
|
Required GitHub Actions secrets:
|
||||||
|
|
||||||
- `ATLAS_RELEASE_APP_CERT_P12_BASE64`
|
- `ATLAS_RELEASE_APP_CERT_P12_BASE64`
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
FIXTURE_SCRIPT="$SCRIPT_DIR/apps-manual-fixtures.sh"
|
FIXTURE_SCRIPT="$SCRIPT_DIR/apps-manual-fixtures.sh"
|
||||||
|
|
||||||
print_guide() {
|
print_guide() {
|
||||||
cat <<'EOF'
|
cat << 'EOF'
|
||||||
Apps Evidence Acceptance Guide
|
Apps Evidence Acceptance Guide
|
||||||
|
|
||||||
1. Run Atlas and open the Apps screen.
|
1. Run Atlas and open the Apps screen.
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ write_info_plist() {
|
|||||||
local plist_path="$1"
|
local plist_path="$1"
|
||||||
local bundle_id="$2"
|
local bundle_id="$2"
|
||||||
local app_name="$3"
|
local app_name="$3"
|
||||||
cat > "$plist_path" <<EOF
|
cat > "$plist_path" << EOF
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
@@ -85,7 +85,7 @@ create_leftovers() {
|
|||||||
;;
|
;;
|
||||||
launch)
|
launch)
|
||||||
mkdir -p "$LAUNCH_AGENTS_ROOT"
|
mkdir -p "$LAUNCH_AGENTS_ROOT"
|
||||||
cat > "$LAUNCH_AGENTS_ROOT/$bundle_id.plist" <<EOF
|
cat > "$LAUNCH_AGENTS_ROOT/$bundle_id.plist" << EOF
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
|
|||||||
82
scripts/atlas/generate-release-body.sh
Executable file
82
scripts/atlas/generate-release-body.sh
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
|
CHANGELOG_FILE="$ROOT_DIR/CHANGELOG.md"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat << 'EOF'
|
||||||
|
Usage:
|
||||||
|
./scripts/atlas/generate-release-body.sh <version> <packaging-mode> [output-file]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
./scripts/atlas/generate-release-body.sh 1.0.3 development
|
||||||
|
./scripts/atlas/generate-release-body.sh 1.0.3 developer-id /tmp/RELEASE_BODY.md
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $# -lt 2 || $# -gt 3 ]]; then
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION="$1"
|
||||||
|
PACKAGING_MODE="$2"
|
||||||
|
OUTPUT_FILE="${3:-$ROOT_DIR/RELEASE_BODY.md}"
|
||||||
|
|
||||||
|
if [[ ! -f "$CHANGELOG_FILE" ]]; then
|
||||||
|
echo "Missing changelog: $CHANGELOG_FILE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$PACKAGING_MODE" != "development" && "$PACKAGING_MODE" != "developer-id" ]]; then
|
||||||
|
echo "Unsupported packaging mode: $PACKAGING_MODE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
extract_changelog_section() {
|
||||||
|
local version="$1"
|
||||||
|
awk -v version="$version" '
|
||||||
|
$0 ~ "^## \\[" version "\\] - " {
|
||||||
|
printing = 1
|
||||||
|
}
|
||||||
|
printing {
|
||||||
|
if ($0 ~ "^## \\[" version "\\] - ") {
|
||||||
|
print "# Atlas for Mac " version
|
||||||
|
print ""
|
||||||
|
next
|
||||||
|
}
|
||||||
|
if ($0 ~ "^## \\[" && $0 !~ "^## \\[" version "\\] - ") {
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
print
|
||||||
|
}
|
||||||
|
' "$CHANGELOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
CHANGELOG_SECTION="$(extract_changelog_section "$VERSION")"
|
||||||
|
|
||||||
|
if [[ -z "${CHANGELOG_SECTION//[$'\n\r\t ']/}" ]]; then
|
||||||
|
{
|
||||||
|
echo "# Atlas for Mac $VERSION"
|
||||||
|
echo
|
||||||
|
echo "Release notes for this version were not found in CHANGELOG.md."
|
||||||
|
} > "$OUTPUT_FILE"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$CHANGELOG_SECTION" > "$OUTPUT_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
echo
|
||||||
|
echo "## Packaging Status"
|
||||||
|
echo
|
||||||
|
if [[ "$PACKAGING_MODE" == "development" ]]; then
|
||||||
|
echo "Native macOS assets in this tag were packaged in development mode because Developer ID release-signing credentials were not configured for this run."
|
||||||
|
echo
|
||||||
|
echo "These \`.zip\`, \`.dmg\`, and \`.pkg\` files are intended for internal testing or developer use. macOS Gatekeeper may require \`Open Anyway\` or a right-click \`Open\` flow before launch."
|
||||||
|
else
|
||||||
|
echo "Native macOS assets in this tag were packaged in CI using Developer ID signing and notarization, then uploaded alongside the existing command-line release artifacts."
|
||||||
|
fi
|
||||||
|
} >> "$OUTPUT_FILE"
|
||||||
|
|
||||||
|
printf 'Generated release body for %s (%s) at %s\n' "$VERSION" "$PACKAGING_MODE" "$OUTPUT_FILE"
|
||||||
Reference in New Issue
Block a user