feat: redesign spectra lab with editorial brand aesthetic
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
spectra-lab-local.png
|
spectra-lab-local.png
|
||||||
|
spectra-lab-redesign.png
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
175
app.js
175
app.js
@@ -1,168 +1,43 @@
|
|||||||
const pointerGlow = document.getElementById('pointerGlow');
|
const modeToggle = document.getElementById('modeToggle');
|
||||||
const themeToggle = document.getElementById('themeToggle');
|
const modeLabel = document.getElementById('modeLabel');
|
||||||
const themeLabel = document.getElementById('themeLabel');
|
const workItems = document.querySelectorAll('.work-item');
|
||||||
const sceneCards = document.querySelectorAll('.scene-card');
|
const workIndex = document.getElementById('workIndex');
|
||||||
const counters = document.querySelectorAll('[data-counter]');
|
const workTitle = document.getElementById('workTitle');
|
||||||
const sceneDetailTitle = document.getElementById('sceneDetailTitle');
|
const workCopy = document.getElementById('workCopy');
|
||||||
const sceneDetailCopy = document.getElementById('sceneDetailCopy');
|
const revealBlocks = document.querySelectorAll('.reveal');
|
||||||
const particleCanvas = document.getElementById('particleCanvas');
|
|
||||||
|
|
||||||
const themes = [
|
function applyMode() {
|
||||||
{ className: '', label: 'Aurora' },
|
const isLight = document.body.classList.contains('light-mode');
|
||||||
{ className: 'theme-ember', label: 'Ember' },
|
modeToggle.textContent = isLight ? 'Dark Mode' : 'Light Mode';
|
||||||
{ className: 'theme-tide', label: 'Tide' },
|
modeLabel.textContent = isLight ? 'Editorial Light' : 'Editorial Dark';
|
||||||
];
|
|
||||||
|
|
||||||
let themeIndex = 0;
|
|
||||||
|
|
||||||
function setTheme(index) {
|
|
||||||
document.body.classList.remove('theme-ember', 'theme-tide');
|
|
||||||
const theme = themes[index];
|
|
||||||
if (theme.className) {
|
|
||||||
document.body.classList.add(theme.className);
|
|
||||||
}
|
|
||||||
themeLabel.textContent = theme.label;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function animateCounter(element) {
|
modeToggle?.addEventListener('click', () => {
|
||||||
const target = Number(element.dataset.counter || 0);
|
document.body.classList.toggle('light-mode');
|
||||||
const duration = 1400;
|
applyMode();
|
||||||
const start = performance.now();
|
|
||||||
|
|
||||||
function step(now) {
|
|
||||||
const progress = Math.min((now - start) / duration, 1);
|
|
||||||
const eased = 1 - Math.pow(1 - progress, 3);
|
|
||||||
element.textContent = Math.round(target * eased);
|
|
||||||
if (progress < 1) requestAnimationFrame(step);
|
|
||||||
}
|
|
||||||
|
|
||||||
requestAnimationFrame(step);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mountParticleField() {
|
|
||||||
if (!particleCanvas) return;
|
|
||||||
const ctx = particleCanvas.getContext('2d');
|
|
||||||
if (!ctx) return;
|
|
||||||
|
|
||||||
const particles = [];
|
|
||||||
const particleCount = 48;
|
|
||||||
let width = 0;
|
|
||||||
let height = 0;
|
|
||||||
|
|
||||||
function resize() {
|
|
||||||
width = window.innerWidth;
|
|
||||||
height = window.innerHeight;
|
|
||||||
particleCanvas.width = width * window.devicePixelRatio;
|
|
||||||
particleCanvas.height = height * window.devicePixelRatio;
|
|
||||||
particleCanvas.style.width = `${width}px`;
|
|
||||||
particleCanvas.style.height = `${height}px`;
|
|
||||||
ctx.setTransform(window.devicePixelRatio, 0, 0, window.devicePixelRatio, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function seed() {
|
|
||||||
particles.length = 0;
|
|
||||||
for (let i = 0; i < particleCount; i += 1) {
|
|
||||||
particles.push({
|
|
||||||
x: Math.random() * width,
|
|
||||||
y: Math.random() * height,
|
|
||||||
r: Math.random() * 1.8 + 0.8,
|
|
||||||
vx: (Math.random() - 0.5) * 0.28,
|
|
||||||
vy: (Math.random() - 0.5) * 0.28,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function draw() {
|
|
||||||
ctx.clearRect(0, 0, width, height);
|
|
||||||
|
|
||||||
particles.forEach((particle, index) => {
|
|
||||||
particle.x += particle.vx;
|
|
||||||
particle.y += particle.vy;
|
|
||||||
|
|
||||||
if (particle.x < -20) particle.x = width + 20;
|
|
||||||
if (particle.x > width + 20) particle.x = -20;
|
|
||||||
if (particle.y < -20) particle.y = height + 20;
|
|
||||||
if (particle.y > height + 20) particle.y = -20;
|
|
||||||
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillStyle = 'rgba(255,255,255,0.38)';
|
|
||||||
ctx.arc(particle.x, particle.y, particle.r, 0, Math.PI * 2);
|
|
||||||
ctx.fill();
|
|
||||||
|
|
||||||
for (let j = index + 1; j < particles.length; j += 1) {
|
|
||||||
const other = particles[j];
|
|
||||||
const dx = particle.x - other.x;
|
|
||||||
const dy = particle.y - other.y;
|
|
||||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
||||||
if (distance < 130) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.strokeStyle = `rgba(130, 180, 255, ${0.12 * (1 - distance / 130)})`;
|
|
||||||
ctx.moveTo(particle.x, particle.y);
|
|
||||||
ctx.lineTo(other.x, other.y);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
requestAnimationFrame(draw);
|
|
||||||
}
|
|
||||||
|
|
||||||
resize();
|
|
||||||
seed();
|
|
||||||
draw();
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
resize();
|
|
||||||
seed();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('pointermove', (event) => {
|
|
||||||
pointerGlow.style.transform = `translate(${event.clientX}px, ${event.clientY}px)`;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
sceneCards.forEach((card) => {
|
workItems.forEach((item) => {
|
||||||
card.addEventListener('pointermove', (event) => {
|
item.addEventListener('click', () => {
|
||||||
const rect = card.getBoundingClientRect();
|
workItems.forEach((button) => button.classList.remove('is-active'));
|
||||||
const x = event.clientX - rect.left;
|
item.classList.add('is-active');
|
||||||
const y = event.clientY - rect.top;
|
workIndex.textContent = item.dataset.index || '';
|
||||||
const rotateX = ((y / rect.height) - 0.5) * -8;
|
workTitle.textContent = item.dataset.title || '';
|
||||||
const rotateY = ((x / rect.width) - 0.5) * 10;
|
workCopy.textContent = item.dataset.copy || '';
|
||||||
|
|
||||||
card.style.setProperty('--mx', `${(x / rect.width) * 100}%`);
|
|
||||||
card.style.setProperty('--my', `${(y / rect.height) * 100}%`);
|
|
||||||
card.style.transform = `translateY(-6px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
card.addEventListener('pointerleave', () => {
|
|
||||||
card.style.transform = '';
|
|
||||||
});
|
|
||||||
|
|
||||||
card.addEventListener('click', () => {
|
|
||||||
sceneCards.forEach((item) => item.classList.remove('is-active'));
|
|
||||||
card.classList.add('is-active');
|
|
||||||
sceneDetailTitle.textContent = card.dataset.sceneTitle || '';
|
|
||||||
sceneDetailCopy.textContent = card.dataset.sceneCopy || '';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
themeToggle.addEventListener('click', () => {
|
|
||||||
themeIndex = (themeIndex + 1) % themes.length;
|
|
||||||
setTheme(themeIndex);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const observer = new IntersectionObserver(
|
const observer = new IntersectionObserver(
|
||||||
(entries) => {
|
(entries) => {
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
animateCounter(entry.target);
|
entry.target.classList.add('is-visible');
|
||||||
observer.unobserve(entry.target);
|
observer.unobserve(entry.target);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ threshold: 0.4 },
|
{ threshold: 0.18 },
|
||||||
);
|
);
|
||||||
|
|
||||||
counters.forEach((counter) => observer.observe(counter));
|
revealBlocks.forEach((block) => observer.observe(block));
|
||||||
sceneCards[0]?.classList.add('is-active');
|
applyMode();
|
||||||
setTheme(themeIndex);
|
|
||||||
mountParticleField();
|
|
||||||
|
|||||||
304
index.html
304
index.html
@@ -6,7 +6,7 @@
|
|||||||
<title>Spectra Lab</title>
|
<title>Spectra Lab</title>
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="Spectra Lab — 一个以光谱、玻璃与动效为核心的沉浸式前端概念 Web App。"
|
content="Spectra Lab — 一页式编辑感品牌站,强调作品感、排版和克制动效,而不是 AI 式炫技。"
|
||||||
/>
|
/>
|
||||||
<script>
|
<script>
|
||||||
if (location.pathname === '/spectra-lab') {
|
if (location.pathname === '/spectra-lab') {
|
||||||
@@ -16,162 +16,186 @@
|
|||||||
<link rel="preconnect" href="https://fonts.googleapis.cn" />
|
<link rel="preconnect" href="https://fonts.googleapis.cn" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.cn" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.cn" crossorigin />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.cn/css2?family=Inter:wght@400;500;600;700;800&family=Noto+Sans+SC:wght@400;500;700;800&display=swap"
|
href="https://fonts.googleapis.cn/css2?family=Inter:wght@400;500;600;700;800&family=Noto+Serif+SC:wght@500;700&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<link rel="stylesheet" href="styles.css" />
|
<link rel="stylesheet" href="styles.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas class="particle-canvas" id="particleCanvas"></canvas>
|
<div class="page-shell">
|
||||||
<div class="noise"></div>
|
<header class="topbar">
|
||||||
<div class="gradient-orb orb-a"></div>
|
<a class="brand" href="#top" aria-label="Spectra Lab 首页">
|
||||||
<div class="gradient-orb orb-b"></div>
|
<span class="brand-mark"></span>
|
||||||
<div class="gradient-orb orb-c"></div>
|
<span class="brand-text">Spectra Lab</span>
|
||||||
<div class="pointer-glow" id="pointerGlow"></div>
|
</a>
|
||||||
|
<nav class="nav-links">
|
||||||
|
<a href="#statement">Statement</a>
|
||||||
|
<a href="#works">Works</a>
|
||||||
|
<a href="#system">System</a>
|
||||||
|
<a href="#closing">Closing</a>
|
||||||
|
</nav>
|
||||||
|
<button id="modeToggle" class="mode-toggle" type="button" aria-label="切换页面模式">
|
||||||
|
Light Mode
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
|
||||||
<header class="topbar glass-panel">
|
<main id="top">
|
||||||
<div class="brand">
|
<section class="hero reveal">
|
||||||
<span class="brand-mark"></span>
|
<div class="hero-meta">
|
||||||
<div>
|
<p class="kicker">Front-end concept / 2026</p>
|
||||||
<p class="brand-eyebrow">Spectra Lab</p>
|
<p class="issue">Issue 01 — Reduced Artificiality</p>
|
||||||
<p class="brand-sub">Digital Atmosphere Prototype</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav class="nav-links">
|
|
||||||
<a href="#metrics">Metrics</a>
|
|
||||||
<a href="#gallery">Gallery</a>
|
|
||||||
<a href="#manifesto">Manifesto</a>
|
|
||||||
</nav>
|
|
||||||
<button id="themeToggle" class="ghost-button" type="button">切换光谱</button>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<section class="hero section">
|
|
||||||
<div class="hero-copy">
|
|
||||||
<p class="eyebrow">A cinematic front-end experience</p>
|
|
||||||
<h1>
|
|
||||||
不只是一个页面,<br />
|
|
||||||
而是一座会呼吸的<br />
|
|
||||||
光谱展馆。
|
|
||||||
</h1>
|
|
||||||
<p class="hero-text">
|
|
||||||
Spectra Lab 把动态网格、玻璃拟态、彩色流体光效与编辑感排版叠在一起,做成一个可以真实浏览、真实交互、真实惊艳的 Web App 原型。
|
|
||||||
</p>
|
|
||||||
<div class="hero-actions">
|
|
||||||
<a class="primary-button" href="#gallery">进入展馆</a>
|
|
||||||
<a class="secondary-button" href="#manifesto">查看设计宣言</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="hero-grid">
|
||||||
|
<div class="hero-copy">
|
||||||
<div class="hero-stage glass-panel">
|
<h1>
|
||||||
<div class="stage-ring"></div>
|
把“像 AI 做的页面”<br />
|
||||||
<div class="stage-grid"></div>
|
改成“像真的品牌作品”。
|
||||||
<div class="stage-core">
|
</h1>
|
||||||
<p>Signal Cluster</p>
|
<p class="hero-text">
|
||||||
<h2>07</h2>
|
Spectra Lab 的第二版不再依赖霓虹、玻璃拟态和悬浮指标,而是回到更克制的设计表达:更强的排版、更明确的留白、更少但更准的动效,以及更像真实创意团队会交付的页面气质。
|
||||||
<span>active scenes</span>
|
</p>
|
||||||
|
</div>
|
||||||
|
<aside class="hero-note">
|
||||||
|
<p>
|
||||||
|
这一版的目标不是“更炫”,而是更像作品本身:可阅读、可陈列、可被记住。
|
||||||
|
</p>
|
||||||
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<div class="floating-card card-alpha">
|
</section>
|
||||||
<p>Ambient Index</p>
|
|
||||||
<strong data-counter="94">0</strong>
|
<section id="statement" class="statement section reveal">
|
||||||
<span>cinematic density</span>
|
<div class="section-head">
|
||||||
|
<p class="kicker">Statement</p>
|
||||||
|
<h2>先去掉套路,再谈风格。</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="floating-card card-beta">
|
<div class="statement-grid">
|
||||||
<p>Pulse Drift</p>
|
<p>
|
||||||
<strong data-counter="128">0</strong>
|
大多数 AI 味页面的问题,不是技术不够,而是视觉判断太偷懒:到处发光、到处渐变、到处 floating card,像在证明“我会做效果”,而不是在表达“我知道什么该留下”。
|
||||||
<span>motion vectors</span>
|
</p>
|
||||||
|
<p>
|
||||||
|
所以这一版只保留三件事:结构、节奏、材质。结构决定像不像品牌,节奏决定高级不高级,材质决定页面有没有手感。除此之外,能删的都删。
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="floating-card card-gamma">
|
</section>
|
||||||
<p>Interface Bloom</p>
|
|
||||||
<strong data-counter="63">0</strong>
|
<section id="works" class="works section reveal">
|
||||||
<span>responsive nodes</span>
|
<div class="section-head split-head">
|
||||||
|
<div>
|
||||||
|
<p class="kicker">Selected Works</p>
|
||||||
|
<h2>四个页面切片,组成完整气质。</h2>
|
||||||
|
</div>
|
||||||
|
<p class="section-caption">点击左侧卡片,右侧会切换对应的设计说明。</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="metrics" class="section metrics">
|
<div class="works-layout">
|
||||||
<div class="section-heading">
|
<div class="work-list" role="tablist" aria-label="设计切片列表">
|
||||||
<p class="eyebrow">Live aesthetic telemetry</p>
|
<button
|
||||||
<h2>把“设计感”拆成可感知的前端语言</h2>
|
class="work-item is-active"
|
||||||
</div>
|
type="button"
|
||||||
<div class="metric-grid">
|
data-title="Opening Spread"
|
||||||
<article class="metric-card glass-panel">
|
data-index="01"
|
||||||
<span>Layer Depth</span>
|
data-copy="首页像一本刊物的开篇大跨页:强标题、宽留白、细线和小号说明文字共同建立秩序,而不是用一堆发光元素抢注意力。"
|
||||||
<strong>9.4</strong>
|
>
|
||||||
<p>通过前景、中景、背景与微粒噪声叠出空间感。</p>
|
<span class="work-number">01</span>
|
||||||
</article>
|
<span>
|
||||||
<article class="metric-card glass-panel">
|
<strong>Opening Spread</strong>
|
||||||
<span>Motion Quality</span>
|
<small>封面感与留白</small>
|
||||||
<strong>92%</strong>
|
</span>
|
||||||
<p>减少廉价跳变,用缓动、漂移与轻量视差维持高级感。</p>
|
</button>
|
||||||
</article>
|
<button
|
||||||
<article class="metric-card glass-panel">
|
class="work-item"
|
||||||
<span>Visual Contrast</span>
|
type="button"
|
||||||
<strong>4 Layers</strong>
|
data-title="Quiet Contrast"
|
||||||
<p>用霓光、暗底、玻璃边缘和字体重量做视觉层次。</p>
|
data-index="02"
|
||||||
</article>
|
data-copy="对比来自字重、边界和材质差异,而不是夸张色彩。黑、白、灰、纸感米色,再加少量暗红作点缀,已经足够建立品牌记忆。"
|
||||||
<article class="metric-card glass-panel accent-card">
|
>
|
||||||
<span>Current Mode</span>
|
<span class="work-number">02</span>
|
||||||
<strong id="themeLabel">Aurora</strong>
|
<span>
|
||||||
<p>支持切换不同光谱主题,让同一界面拥有不同情绪。</p>
|
<strong>Quiet Contrast</strong>
|
||||||
</article>
|
<small>克制颜色,而非特效堆叠</small>
|
||||||
</div>
|
</span>
|
||||||
</section>
|
</button>
|
||||||
|
<button
|
||||||
|
class="work-item"
|
||||||
|
type="button"
|
||||||
|
data-title="Measured Motion"
|
||||||
|
data-index="03"
|
||||||
|
data-copy="动效只承担两个任务:引导阅读和提供触感。它不负责表演,也不负责制造噪声,所以 hover、滚动 reveal 和模式切换都很轻。"
|
||||||
|
>
|
||||||
|
<span class="work-number">03</span>
|
||||||
|
<span>
|
||||||
|
<strong>Measured Motion</strong>
|
||||||
|
<small>只做必要的运动</small>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="work-item"
|
||||||
|
type="button"
|
||||||
|
data-title="Material Ending"
|
||||||
|
data-index="04"
|
||||||
|
data-copy="收尾部分不再追加功能堆料,而是用一个有材料感的段落把情绪压住,让整个页面从头到尾有完整的起承转合。"
|
||||||
|
>
|
||||||
|
<span class="work-number">04</span>
|
||||||
|
<span>
|
||||||
|
<strong>Material Ending</strong>
|
||||||
|
<small>收住,而不是越做越满</small>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<section id="gallery" class="section gallery">
|
<article class="work-stage">
|
||||||
<div class="section-heading split">
|
<div class="stage-card">
|
||||||
<div>
|
<p class="stage-kicker">Current focus</p>
|
||||||
<p class="eyebrow">Curated scenes</p>
|
<div class="stage-index" id="workIndex">01</div>
|
||||||
<h2>每一张卡片,都像展馆里的一个独立空间</h2>
|
<h3 id="workTitle">Opening Spread</h3>
|
||||||
|
<p id="workCopy">
|
||||||
|
首页像一本刊物的开篇大跨页:强标题、宽留白、细线和小号说明文字共同建立秩序,而不是用一堆发光元素抢注意力。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
</div>
|
</div>
|
||||||
<p class="section-note">Hover 卡片,看看透视、边缘发光和背景响应;点击则切换下方讲解。</p>
|
</section>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gallery-grid">
|
<section id="system" class="system section reveal">
|
||||||
<article class="scene-card scene-large glass-panel" data-scene-title="Prism Core" data-scene-copy="主舞台由动态网格、发光环和浮动数据组成,强调空间感与叙事中心,是整个页面的视觉引力源。">
|
<div class="section-head">
|
||||||
<div class="scene-tag">01 / Prism Core</div>
|
<p class="kicker">System</p>
|
||||||
<h3>会漂移的主场景</h3>
|
<h2>视觉系统不复杂,但必须一致。</h2>
|
||||||
<p>主舞台不是静态图,而是由网格、发光环、渐变和数据浮层组成的动态构图。</p>
|
</div>
|
||||||
</article>
|
<div class="system-grid">
|
||||||
<article class="scene-card glass-panel" data-scene-title="Quiet Signal" data-scene-copy="把亮点压缩到必要区域,保留大面积暗部和留白,让霓光真正成为视线焦点,而不是噪音。">
|
<article class="system-card">
|
||||||
<div class="scene-tag">02 / Quiet Signal</div>
|
<span>Typography</span>
|
||||||
<h3>深色中的克制亮点</h3>
|
<strong>Serif headline / Sans body</strong>
|
||||||
<p>控制高亮面积,让视觉中心更明确,而不是整屏乱闪。</p>
|
<p>标题用更有书卷感的衬线中文,正文维持干净无衬线,让页面既有性格也不失可读性。</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="scene-card glass-panel" data-scene-title="Editorial Flow" data-scene-copy="通过标题、说明、标签与节奏化留白,让单页也具备杂志封面和展览海报的张力。">
|
<article class="system-card">
|
||||||
<div class="scene-tag">03 / Editorial Flow</div>
|
<span>Palette</span>
|
||||||
<h3>海报式排版</h3>
|
<strong>Ink / Paper / Oxblood</strong>
|
||||||
<p>标题、留白、短段文案与组件比例共同决定气质。</p>
|
<p>颜色压到少数几种:墨黑、纸白、米灰、暗红。这样更像品牌系统,而不是灵感拼贴。</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="scene-card glass-panel" data-scene-title="Tactile Hover" data-scene-copy="hover 不只是位移,而是材质、光线和透视的共同反馈,让界面更像可触摸物体。">
|
<article class="system-card">
|
||||||
<div class="scene-tag">04 / Tactile Hover</div>
|
<span>Motion</span>
|
||||||
<h3>像摸到玻璃一样</h3>
|
<strong>Reveal / Shift / Fade</strong>
|
||||||
<p>卡片 hover 有轻透视、边缘反光、阴影偏移和背景亮度反馈。</p>
|
<p>动效只使用最基本的进入、位移和透明度变化,避免每个区域都在“自我表演”。</p>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<div class="scene-detail glass-panel" id="sceneDetail">
|
<section id="closing" class="closing section reveal">
|
||||||
<p class="eyebrow">Scene focus</p>
|
<div class="closing-panel">
|
||||||
<h3 id="sceneDetailTitle">Prism Core</h3>
|
<p class="kicker">Closing</p>
|
||||||
<p id="sceneDetailCopy">
|
<h2>真正高级的页面,通常都有一点节制。</h2>
|
||||||
主舞台由动态网格、发光环和浮动数据组成,强调空间感与叙事中心,是整个页面的视觉引力源。
|
<p>
|
||||||
</p>
|
如果第一页就把所有招式用完,观者只会记得“效果很多”。但如果页面知道何时收、何时留白、何时只用一条线和一块色面说话,它才更像真正完成度高的作品。
|
||||||
</div>
|
</p>
|
||||||
</section>
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
<section id="manifesto" class="section manifesto glass-panel">
|
<footer class="footer reveal">
|
||||||
<p class="eyebrow">Manifesto</p>
|
<span>Spectra Lab</span>
|
||||||
<h2>真正惊艳的前端,不是堆特效,而是让特效服务于气质。</h2>
|
<span id="modeLabel">Editorial Dark</span>
|
||||||
<p>
|
</footer>
|
||||||
这个原型故意把功能压到第二位,把所有预算投给视觉叙事:版式像海报,交互像展陈,背景像呼吸,按钮像可触摸的材质。主人要的不是“能用就行”的站,而是第一眼就记得住的作品。
|
</div>
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer class="footer">
|
|
||||||
<span>Spectra Lab / Front-end concept build</span>
|
|
||||||
<span>Designed for visual impact</span>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
816
styles.css
816
styles.css
@@ -1,30 +1,33 @@
|
|||||||
:root {
|
:root {
|
||||||
--bg: #070816;
|
--bg: #111111;
|
||||||
--bg-soft: rgba(255, 255, 255, 0.08);
|
--bg-soft: #171717;
|
||||||
--panel: rgba(13, 17, 38, 0.5);
|
--panel: #1d1b1a;
|
||||||
--panel-strong: rgba(17, 21, 46, 0.72);
|
--paper: #f2ece4;
|
||||||
--text: #f3f5ff;
|
--paper-soft: #e6ded3;
|
||||||
--muted: rgba(230, 236, 255, 0.72);
|
--ink: #141414;
|
||||||
--border: rgba(255, 255, 255, 0.14);
|
--line: rgba(255, 255, 255, 0.16);
|
||||||
--shadow: 0 24px 80px rgba(0, 0, 0, 0.45);
|
--line-strong: rgba(255, 255, 255, 0.28);
|
||||||
--accent-a: #7c5cff;
|
--text: #f4efe8;
|
||||||
--accent-b: #2be4ff;
|
--muted: rgba(244, 239, 232, 0.66);
|
||||||
--accent-c: #ff6bd6;
|
--accent: #7f2f2f;
|
||||||
--accent-d: #ffd166;
|
--accent-soft: rgba(127, 47, 47, 0.16);
|
||||||
|
--shadow: 0 30px 80px rgba(0, 0, 0, 0.28);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.theme-ember {
|
body.light-mode {
|
||||||
--accent-a: #ff7a18;
|
--bg: #efe8de;
|
||||||
--accent-b: #ff3cac;
|
--bg-soft: #e7dfd3;
|
||||||
--accent-c: #7b61ff;
|
--panel: #f6f0e7;
|
||||||
--accent-d: #ffe66d;
|
--paper: #ffffff;
|
||||||
}
|
--paper-soft: #f5eee4;
|
||||||
|
--ink: #171717;
|
||||||
body.theme-tide {
|
--line: rgba(23, 23, 23, 0.12);
|
||||||
--accent-a: #4facfe;
|
--line-strong: rgba(23, 23, 23, 0.22);
|
||||||
--accent-b: #00f2fe;
|
--text: #171717;
|
||||||
--accent-c: #00ffa3;
|
--muted: rgba(23, 23, 23, 0.68);
|
||||||
--accent-d: #b2f7ef;
|
--accent: #8d3d38;
|
||||||
|
--accent-soft: rgba(141, 61, 56, 0.11);
|
||||||
|
--shadow: 0 20px 60px rgba(28, 22, 18, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -38,149 +41,78 @@ html {
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
font-family: 'Inter', 'Noto Sans SC', sans-serif;
|
|
||||||
color: var(--text);
|
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at top left, rgba(124, 92, 255, 0.16), transparent 30%),
|
linear-gradient(180deg, rgba(255, 255, 255, 0.03), transparent 18%),
|
||||||
radial-gradient(circle at top right, rgba(43, 228, 255, 0.12), transparent 28%),
|
linear-gradient(180deg, var(--bg) 0%, var(--bg-soft) 100%);
|
||||||
linear-gradient(180deg, #050611 0%, #090b18 45%, #06070d 100%);
|
color: var(--text);
|
||||||
overflow-x: hidden;
|
font-family: 'Inter', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||||||
|
transition: background 260ms ease, color 260ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
body::before {
|
body::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background-image:
|
|
||||||
linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
|
|
||||||
linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
|
|
||||||
background-size: 72px 72px;
|
|
||||||
mask-image: radial-gradient(circle at center, black 40%, transparent 90%);
|
|
||||||
opacity: 0.28;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
background:
|
||||||
|
linear-gradient(90deg, transparent 0, transparent calc(50% - 1px), var(--line) calc(50% - 1px), var(--line) calc(50% + 1px), transparent calc(50% + 1px)),
|
||||||
|
linear-gradient(180deg, transparent 0, transparent 88px, var(--line) 88px, var(--line) 89px, transparent 89px);
|
||||||
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.noise {
|
body::after {
|
||||||
|
content: '';
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 28px;
|
||||||
opacity: 0.08;
|
border: 1px solid var(--line);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background-image:
|
|
||||||
radial-gradient(circle at 20% 20%, rgba(255,255,255,0.22) 0 1px, transparent 1px),
|
|
||||||
radial-gradient(circle at 70% 35%, rgba(255,255,255,0.16) 0 1px, transparent 1px),
|
|
||||||
radial-gradient(circle at 30% 80%, rgba(255,255,255,0.12) 0 1px, transparent 1px);
|
|
||||||
background-size: 180px 180px;
|
|
||||||
mix-blend-mode: screen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.gradient-orb {
|
button,
|
||||||
position: fixed;
|
a {
|
||||||
width: 38rem;
|
color: inherit;
|
||||||
height: 38rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
filter: blur(40px);
|
|
||||||
opacity: 0.28;
|
|
||||||
pointer-events: none;
|
|
||||||
animation: drift 14s ease-in-out infinite alternate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.orb-a {
|
.page-shell {
|
||||||
top: -8rem;
|
width: min(1320px, calc(100% - 48px));
|
||||||
left: -10rem;
|
margin: 0 auto;
|
||||||
background: radial-gradient(circle, var(--accent-a), transparent 62%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.orb-b {
|
|
||||||
top: 24rem;
|
|
||||||
right: -12rem;
|
|
||||||
background: radial-gradient(circle, var(--accent-b), transparent 60%);
|
|
||||||
animation-duration: 18s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.orb-c {
|
|
||||||
bottom: -10rem;
|
|
||||||
left: 22%;
|
|
||||||
background: radial-gradient(circle, var(--accent-c), transparent 58%);
|
|
||||||
animation-duration: 22s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pointer-glow {
|
|
||||||
position: fixed;
|
|
||||||
width: 18rem;
|
|
||||||
height: 18rem;
|
|
||||||
margin-left: -9rem;
|
|
||||||
margin-top: -9rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
pointer-events: none;
|
|
||||||
background: radial-gradient(circle, rgba(255,255,255,0.16), rgba(255,255,255,0.02) 45%, transparent 72%);
|
|
||||||
mix-blend-mode: screen;
|
|
||||||
opacity: 0.75;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.particle-canvas {
|
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0.55;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.topbar,
|
.topbar,
|
||||||
.section,
|
.section,
|
||||||
.footer {
|
.footer {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topbar {
|
.topbar {
|
||||||
width: min(1180px, calc(100% - 32px));
|
|
||||||
margin: 20px auto 0;
|
|
||||||
padding: 16px 18px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
padding: 28px 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand {
|
.brand {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 14px;
|
gap: 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
letter-spacing: 0.14em;
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-mark {
|
.brand-mark {
|
||||||
width: 14px;
|
width: 11px;
|
||||||
height: 14px;
|
height: 11px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: linear-gradient(135deg, var(--accent-b), var(--accent-c));
|
background: var(--accent);
|
||||||
box-shadow: 0 0 18px var(--accent-b), 0 0 40px var(--accent-c);
|
box-shadow: 0 0 0 6px var(--accent-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-eyebrow,
|
.brand-text {
|
||||||
.brand-sub,
|
font-weight: 700;
|
||||||
.eyebrow,
|
|
||||||
.scene-tag,
|
|
||||||
.metric-card span,
|
|
||||||
.footer,
|
|
||||||
.section-note {
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-eyebrow,
|
|
||||||
.eyebrow {
|
|
||||||
margin: 0;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: rgba(255,255,255,0.74);
|
|
||||||
font-size: 0.74rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-sub {
|
|
||||||
margin: 2px 0 0;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
color: rgba(255,255,255,0.52);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-links {
|
.nav-links {
|
||||||
@@ -189,436 +121,318 @@ body::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-links a,
|
.nav-links a,
|
||||||
|
.mode-toggle,
|
||||||
.footer {
|
.footer {
|
||||||
color: rgba(255,255,255,0.65);
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 0.92rem;
|
font-size: 0.92rem;
|
||||||
}
|
|
||||||
|
|
||||||
.ghost-button,
|
|
||||||
.primary-button,
|
|
||||||
.secondary-button {
|
|
||||||
border-radius: 999px;
|
|
||||||
transition: transform 180ms ease, box-shadow 180ms ease, background 180ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ghost-button {
|
|
||||||
border: 1px solid rgba(255,255,255,0.14);
|
|
||||||
background: rgba(255,255,255,0.05);
|
|
||||||
color: var(--text);
|
|
||||||
padding: 12px 16px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.primary-button,
|
|
||||||
.secondary-button {
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 14px 20px;
|
color: var(--muted);
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-button {
|
.mode-toggle {
|
||||||
background: linear-gradient(135deg, var(--accent-a), var(--accent-c));
|
border: 1px solid var(--line);
|
||||||
color: white;
|
background: transparent;
|
||||||
box-shadow: 0 18px 40px rgba(124, 92, 255, 0.28);
|
padding: 10px 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.secondary-button {
|
.mode-toggle:hover,
|
||||||
|
.nav-links a:hover {
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border: 1px solid rgba(255,255,255,0.16);
|
|
||||||
background: rgba(255,255,255,0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.glass-panel {
|
|
||||||
background: linear-gradient(180deg, rgba(255,255,255,0.1), rgba(255,255,255,0.04));
|
|
||||||
border: 1px solid var(--border);
|
|
||||||
box-shadow: var(--shadow);
|
|
||||||
backdrop-filter: blur(24px) saturate(160%);
|
|
||||||
-webkit-backdrop-filter: blur(24px) saturate(160%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
width: min(1180px, calc(100% - 32px));
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 84px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero {
|
.hero {
|
||||||
display: grid;
|
padding: 42px 0 72px;
|
||||||
grid-template-columns: 1.08fr 0.92fr;
|
|
||||||
align-items: center;
|
|
||||||
gap: 42px;
|
|
||||||
min-height: calc(100vh - 110px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-copy h1 {
|
|
||||||
margin: 16px 0 18px;
|
|
||||||
font-size: clamp(3rem, 7vw, 6.25rem);
|
|
||||||
line-height: 0.95;
|
|
||||||
letter-spacing: -0.045em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-text {
|
|
||||||
max-width: 40rem;
|
|
||||||
font-size: 1.05rem;
|
|
||||||
line-height: 1.8;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-actions {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 14px;
|
|
||||||
margin-top: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-stage {
|
|
||||||
position: relative;
|
|
||||||
min-height: 620px;
|
|
||||||
border-radius: 34px;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stage-grid,
|
|
||||||
.stage-ring {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stage-grid {
|
|
||||||
background-image:
|
|
||||||
linear-gradient(rgba(255,255,255,0.07) 1px, transparent 1px),
|
|
||||||
linear-gradient(90deg, rgba(255,255,255,0.07) 1px, transparent 1px);
|
|
||||||
background-size: 36px 36px;
|
|
||||||
mask-image: radial-gradient(circle at center, black 45%, transparent 88%);
|
|
||||||
animation: pulseGrid 12s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stage-ring {
|
|
||||||
inset: 12%;
|
|
||||||
border-radius: 50%;
|
|
||||||
border: 1px solid rgba(255,255,255,0.12);
|
|
||||||
box-shadow:
|
|
||||||
0 0 40px rgba(124,92,255,0.22),
|
|
||||||
inset 0 0 40px rgba(43,228,255,0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stage-core {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
width: 16rem;
|
|
||||||
height: 16rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
text-align: center;
|
|
||||||
background: radial-gradient(circle, rgba(255,255,255,0.16), rgba(255,255,255,0.03));
|
|
||||||
border: 1px solid rgba(255,255,255,0.14);
|
|
||||||
box-shadow: 0 0 60px rgba(124,92,255,0.22);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stage-core p,
|
|
||||||
.stage-core span {
|
|
||||||
margin: 0;
|
|
||||||
color: rgba(255,255,255,0.66);
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 0.78rem;
|
|
||||||
letter-spacing: 0.1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stage-core h2 {
|
|
||||||
margin: 6px 0;
|
|
||||||
font-size: 5rem;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-card {
|
|
||||||
position: absolute;
|
|
||||||
min-width: 180px;
|
|
||||||
padding: 18px 18px 16px;
|
|
||||||
border-radius: 24px;
|
|
||||||
background: linear-gradient(180deg, rgba(255,255,255,0.14), rgba(255,255,255,0.05));
|
|
||||||
border: 1px solid rgba(255,255,255,0.16);
|
|
||||||
box-shadow: 0 18px 40px rgba(0,0,0,0.28);
|
|
||||||
backdrop-filter: blur(18px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-card p,
|
|
||||||
.floating-card span {
|
|
||||||
margin: 0;
|
|
||||||
color: rgba(255,255,255,0.66);
|
|
||||||
font-size: 0.78rem;
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-card strong {
|
|
||||||
display: block;
|
|
||||||
margin: 8px 0 6px;
|
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-alpha { top: 8%; left: 4%; animation: floatCard 8s ease-in-out infinite; }
|
|
||||||
.card-beta { right: 4%; top: 18%; animation: floatCard 11s ease-in-out infinite reverse; }
|
|
||||||
.card-gamma { left: 12%; bottom: 8%; animation: floatCard 9s ease-in-out infinite 0.8s; }
|
|
||||||
|
|
||||||
.section-heading {
|
|
||||||
max-width: 52rem;
|
|
||||||
margin-bottom: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-heading h2,
|
|
||||||
.manifesto h2 {
|
|
||||||
margin: 12px 0 0;
|
|
||||||
font-size: clamp(2rem, 4vw, 3.6rem);
|
|
||||||
line-height: 1.05;
|
|
||||||
letter-spacing: -0.04em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.split {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 20px;
|
|
||||||
align-items: end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-note,
|
|
||||||
.manifesto p,
|
|
||||||
.metric-card p,
|
|
||||||
.scene-card p {
|
|
||||||
color: var(--muted);
|
|
||||||
line-height: 1.75;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-grid,
|
|
||||||
.gallery-grid {
|
|
||||||
display: grid;
|
|
||||||
gap: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-grid {
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-card,
|
|
||||||
.scene-card,
|
|
||||||
.manifesto {
|
|
||||||
border-radius: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-card {
|
|
||||||
padding: 24px;
|
|
||||||
min-height: 220px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-card strong {
|
|
||||||
display: block;
|
|
||||||
margin: 20px 0 14px;
|
|
||||||
font-size: clamp(2rem, 4vw, 3.5rem);
|
|
||||||
letter-spacing: -0.05em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.accent-card {
|
|
||||||
background: linear-gradient(135deg, rgba(124,92,255,0.2), rgba(43,228,255,0.1), rgba(255,255,255,0.06));
|
|
||||||
}
|
|
||||||
|
|
||||||
.gallery-grid {
|
|
||||||
grid-template-columns: 1.2fr 1fr 1fr;
|
|
||||||
grid-auto-rows: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-card {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 24px;
|
|
||||||
transform-style: preserve-3d;
|
|
||||||
transition: transform 220ms ease, border-color 220ms ease, box-shadow 220ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-card::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: -20%;
|
|
||||||
background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%), rgba(255,255,255,0.16), transparent 35%);
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 220ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-card:hover {
|
|
||||||
transform: translateY(-6px) rotateX(4deg) rotateY(-4deg);
|
|
||||||
border-color: rgba(255,255,255,0.24);
|
|
||||||
box-shadow: 0 24px 70px rgba(0,0,0,0.34), 0 0 30px rgba(124,92,255,0.14);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-card:hover::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-card.is-active {
|
|
||||||
border-color: rgba(255,255,255,0.3);
|
|
||||||
box-shadow: 0 24px 70px rgba(0,0,0,0.34), 0 0 34px rgba(124,92,255,0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-large {
|
|
||||||
grid-row: span 2;
|
|
||||||
min-height: 518px;
|
|
||||||
background:
|
|
||||||
linear-gradient(180deg, rgba(255,255,255,0.08), rgba(255,255,255,0.04)),
|
|
||||||
radial-gradient(circle at top right, rgba(43,228,255,0.24), transparent 35%),
|
|
||||||
radial-gradient(circle at bottom left, rgba(124,92,255,0.24), transparent 34%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-tag {
|
|
||||||
color: rgba(255,255,255,0.72);
|
|
||||||
font-size: 0.74rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-card h3 {
|
|
||||||
margin: 18px 0 10px;
|
|
||||||
font-size: 1.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-detail {
|
|
||||||
margin-top: 20px;
|
|
||||||
padding: 24px 26px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-detail h3 {
|
|
||||||
margin: 10px 0 6px;
|
|
||||||
font-size: clamp(1.6rem, 3vw, 2.4rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.manifesto {
|
|
||||||
padding: 34px;
|
|
||||||
margin-top: 14px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hero-meta,
|
||||||
|
.section-head,
|
||||||
.footer {
|
.footer {
|
||||||
width: min(1180px, calc(100% - 32px));
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 26px 0 44px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ghost-button:hover,
|
.kicker,
|
||||||
.primary-button:hover,
|
.issue,
|
||||||
.secondary-button:hover {
|
.stage-kicker,
|
||||||
transform: translateY(-2px);
|
.system-card span {
|
||||||
|
margin: 0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.16em;
|
||||||
|
font-size: 0.74rem;
|
||||||
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes drift {
|
.hero-grid {
|
||||||
0% { transform: translate3d(0, 0, 0) scale(1); }
|
display: grid;
|
||||||
100% { transform: translate3d(24px, -32px, 0) scale(1.08); }
|
grid-template-columns: minmax(0, 1.35fr) minmax(260px, 0.65fr);
|
||||||
|
gap: 36px;
|
||||||
|
margin-top: 26px;
|
||||||
|
padding-top: 22px;
|
||||||
|
border-top: 1px solid var(--line);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes floatCard {
|
.hero-copy h1,
|
||||||
0%, 100% { transform: translateY(0px); }
|
.section-head h2,
|
||||||
50% { transform: translateY(-12px); }
|
.closing-panel h2,
|
||||||
|
.work-stage h3 {
|
||||||
|
font-family: 'Noto Serif SC', 'Songti SC', serif;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulseGrid {
|
.hero-copy h1 {
|
||||||
0% { transform: scale(1) rotate(0deg); opacity: 0.72; }
|
margin: 0;
|
||||||
50% { transform: scale(1.04) rotate(0.8deg); opacity: 0.9; }
|
font-size: clamp(3.5rem, 8vw, 7rem);
|
||||||
100% { transform: scale(1) rotate(0deg); opacity: 0.72; }
|
line-height: 1.03;
|
||||||
|
max-width: 11ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-text,
|
||||||
|
.statement-grid p,
|
||||||
|
.system-card p,
|
||||||
|
.closing-panel p,
|
||||||
|
.work-stage p,
|
||||||
|
.section-caption,
|
||||||
|
.work-item small,
|
||||||
|
.hero-note p {
|
||||||
|
color: var(--muted);
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-text {
|
||||||
|
margin: 28px 0 0;
|
||||||
|
max-width: 46rem;
|
||||||
|
font-size: 1.06rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-note {
|
||||||
|
align-self: end;
|
||||||
|
padding: 22px 0 0 20px;
|
||||||
|
border-left: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
padding: 72px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-head {
|
||||||
|
padding-bottom: 18px;
|
||||||
|
border-bottom: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-head h2,
|
||||||
|
.closing-panel h2 {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
font-size: clamp(2rem, 4vw, 3.6rem);
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statement-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 28px;
|
||||||
|
margin-top: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-head {
|
||||||
|
align-items: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.works-layout {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(320px, 0.9fr) minmax(0, 1.1fr);
|
||||||
|
gap: 28px;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-item {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 56px 1fr;
|
||||||
|
gap: 16px;
|
||||||
|
text-align: left;
|
||||||
|
padding: 18px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 180ms ease, border-color 180ms ease, background 180ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-item:hover,
|
||||||
|
.work-item.is-active {
|
||||||
|
transform: translateX(4px);
|
||||||
|
border-color: var(--line-strong);
|
||||||
|
background: var(--accent-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-number {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--muted);
|
||||||
|
letter-spacing: 0.14em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-item strong {
|
||||||
|
display: block;
|
||||||
|
font-size: 1.12rem;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-stage {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-card,
|
||||||
|
.system-card,
|
||||||
|
.closing-panel {
|
||||||
|
background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-card {
|
||||||
|
min-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 34px;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.06) 100%),
|
||||||
|
linear-gradient(135deg, rgba(255,255,255,0.02), transparent 48%),
|
||||||
|
linear-gradient(180deg, var(--panel), color-mix(in srgb, var(--panel) 80%, black 20%));
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-index {
|
||||||
|
font-size: clamp(4.2rem, 8vw, 8rem);
|
||||||
|
line-height: 0.92;
|
||||||
|
margin: 20px 0 12px;
|
||||||
|
color: color-mix(in srgb, var(--accent) 72%, var(--text) 28%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.work-stage h3 {
|
||||||
|
font-size: clamp(1.8rem, 3vw, 3rem);
|
||||||
|
margin: 0 0 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 18px;
|
||||||
|
margin-top: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-card {
|
||||||
|
padding: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-card strong {
|
||||||
|
display: block;
|
||||||
|
margin: 18px 0 10px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closing-panel {
|
||||||
|
padding: 36px;
|
||||||
|
background:
|
||||||
|
linear-gradient(0deg, rgba(127, 47, 47, 0.08), rgba(127, 47, 47, 0.08)),
|
||||||
|
linear-gradient(180deg, var(--paper-soft), var(--paper));
|
||||||
|
color: var(--ink);
|
||||||
|
border-color: rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.closing-panel .kicker,
|
||||||
|
.closing-panel p {
|
||||||
|
color: rgba(20, 20, 20, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding: 22px 0 42px;
|
||||||
|
border-top: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(24px);
|
||||||
|
transition: opacity 650ms ease, transform 650ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reveal.is-visible {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1100px) {
|
@media (max-width: 1100px) {
|
||||||
.hero,
|
.topbar,
|
||||||
.metric-grid,
|
.hero-meta,
|
||||||
.gallery-grid,
|
.section-head,
|
||||||
.split,
|
.works-layout,
|
||||||
.footer,
|
.hero-grid,
|
||||||
.topbar {
|
.statement-grid,
|
||||||
|
.system-grid,
|
||||||
|
.footer {
|
||||||
grid-template-columns: 1fr !important;
|
grid-template-columns: 1fr !important;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero {
|
.hero-copy h1 {
|
||||||
min-height: auto;
|
max-width: none;
|
||||||
padding-top: 40px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-grid {
|
.hero-note {
|
||||||
|
border-left: none;
|
||||||
|
border-top: 1px solid var(--line);
|
||||||
|
padding-left: 0;
|
||||||
|
padding-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr) !important;
|
grid-template-columns: 1fr;
|
||||||
}
|
|
||||||
|
|
||||||
.gallery-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scene-large {
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
grid-row: auto;
|
|
||||||
min-height: 320px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-stage {
|
|
||||||
min-height: 500px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
.section {
|
body::after {
|
||||||
padding: 64px 0;
|
inset: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topbar {
|
.page-shell {
|
||||||
margin-top: 14px;
|
width: min(100% - 24px, 1320px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-links {
|
.nav-links {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-grid,
|
.hero {
|
||||||
.gallery-grid {
|
padding-top: 20px;
|
||||||
grid-template-columns: 1fr !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-copy h1 {
|
.hero-copy h1 {
|
||||||
font-size: clamp(2.7rem, 14vw, 4.2rem);
|
font-size: clamp(2.6rem, 13vw, 4.4rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-stage {
|
.section {
|
||||||
min-height: 460px;
|
padding: 54px 0;
|
||||||
padding: 18px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stage-core {
|
.work-item {
|
||||||
width: 12rem;
|
grid-template-columns: 40px 1fr;
|
||||||
height: 12rem;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stage-core h2 {
|
.stage-card,
|
||||||
font-size: 3.7rem;
|
.closing-panel {
|
||||||
}
|
|
||||||
|
|
||||||
.floating-card {
|
|
||||||
min-width: 140px;
|
|
||||||
padding: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-card strong {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.manifesto {
|
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
|
||||||
padding-bottom: 30px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user