Skip to content

Commit ed85b76

Browse files
committed
feat: design a cinematic 3D spatial experience
- Install Three.js and GSAP for animations - Create global Scene.svelte with wireframe cube, grid plane and volumetric dust - Add ProductMonoliths.svelte for interactive 3D product cards with hover tilt - Transition design tokens to pure monochrome (black background, white wireframes) - Add text glitch animations and depth-of-field styling - Update typography to feel architectural and severe - Implement scroll-based cinematic camera drift - Fallback gracefully when WebGL is unavailable
1 parent 5149e09 commit ed85b76

File tree

11 files changed

+843
-249
lines changed

11 files changed

+843
-249
lines changed

package-lock.json

Lines changed: 15 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
"vite": "^7.3.1"
1616
},
1717
"dependencies": {
18-
"geist": "^1.7.0"
18+
"geist": "^1.7.0",
19+
"gsap": "^3.14.2",
20+
"three": "^0.183.1"
1921
}
2022
}

src/app.css

Lines changed: 184 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,77 +4,75 @@
44
font-weight: 100 900;
55
font-style: normal;
66
font-display: swap;
7+
font-style: normal;
78
}
89

910
/* ═══════════════════════════════════════════
1011
DESIGN TOKENS
1112
═══════════════════════════════════════════ */
1213

1314
:root {
14-
/* ── Colors: Dark mode (default) ── */
15+
/* Colors - Pure Monochrome */
1516
--bg: #000000;
16-
--surface: #080808;
17-
--surface-2: #111111;
18-
--border: rgba(255, 255, 255, 0.1);
17+
--surface: rgba(25, 25, 25, 0.4);
18+
--surface-2: rgba(40, 40, 40, 0.5);
19+
--border: rgba(255, 255, 255, 0.15);
20+
--border-glow: rgba(255, 255, 255, 0.8);
21+
1922
--text-primary: #ffffff;
20-
--text-secondary: rgba(255, 255, 255, 0.55);
21-
--text-muted: rgba(255, 255, 255, 0.25);
22-
--text-ghost: rgba(255, 255, 255, 0.12);
23-
24-
/* ── Colors: Light sections (inverted) ── */
25-
--light-bg: #ffffff;
26-
--light-border: #e5e5e5;
27-
--light-text-primary: #000000;
28-
--light-text-body: #333333;
29-
--light-text-secondary: #555555;
30-
--light-text-muted: #999999;
31-
--light-text-dim: #888888;
32-
33-
/* ── Typography ── */
34-
--font-mono: 'Geist Mono', ui-monospace, monospace;
35-
36-
--fs-hero: clamp(3.5rem, 11vw, 8rem);
23+
--text-secondary: rgba(255, 255, 255, 0.65);
24+
--text-muted: rgba(255, 255, 255, 0.35);
25+
--text-ghost: rgba(255, 255, 255, 0.15);
26+
27+
/* Typography Scale */
28+
--fs-hero: clamp(4rem, 12vw, 10rem);
3729
--fs-hero-product: clamp(4rem, 12vw, 9rem);
3830
--fs-hero-large: clamp(5rem, 18vw, 12rem);
31+
3932
--fs-h2: clamp(2rem, 5vw, 4rem);
4033
--fs-h2-large: clamp(2.5rem, 6vw, 5rem);
41-
--fs-thesis: clamp(1.75rem, 3.5vw, 3.25rem);
34+
--fs-thesis: clamp(2rem, 4vw, 4rem);
35+
4236
--fs-lead: clamp(1.3rem, 2.5vw, 1.7rem);
4337
--fs-tagline: clamp(0.95rem, 2vw, 1.1rem);
4438
--fs-pillar-title: clamp(0.95rem, 1.5vw, 1.15rem);
45-
--fs-body: 0.9rem;
39+
40+
--fs-body: 0.95rem;
4641
--fs-body-sm: 0.875rem;
4742
--fs-body-xs: 0.85rem;
48-
--fs-spec: 0.72rem;
49-
--fs-label: 0.65rem;
50-
--fs-label-sm: 0.62rem;
51-
--fs-label-xs: 0.58rem;
52-
--fs-nav: 0.65rem;
53-
--fs-wordmark: 0.875rem;
54-
--fs-btn: 0.7rem;
43+
44+
--fs-spec: 0.75rem;
45+
--fs-label: 0.7rem;
46+
--fs-label-sm: 0.65rem;
47+
--fs-label-xs: 0.6rem;
48+
49+
--fs-btn: 0.75rem;
50+
--fs-nav: 0.7rem;
51+
--fs-wordmark: 0.9rem;
5552
--fs-scroll-hint: 0.65rem;
56-
--fs-footer-link: 0.68rem;
57-
--fs-footer-copy: 0.6rem;
5853

54+
/* Line Height */
5955
--lh-tight: 0.95;
60-
--lh-heading: 1.05;
61-
--lh-default: 1.6;
62-
--lh-relaxed: 1.75;
56+
--lh-heading: 1.1;
57+
--lh-default: 1.5;
58+
--lh-relaxed: 1.65;
6359
--lh-loose: 1.85;
6460

65-
--ls-tight: -0.01em;
61+
/* Letter Spacing */
62+
--ls-tight: -0.02em;
6663
--ls-default: 0.02em;
67-
--ls-moderate: 0.04em;
64+
--ls-moderate: 0.06em;
6865
--ls-wide: 0.1em;
6966
--ls-wider: 0.18em;
7067
--ls-widest: 0.25em;
7168

69+
/* Font Weight */
7270
--fw-normal: 400;
7371
--fw-medium: 500;
7472
--fw-semibold: 600;
7573
--fw-bold: 700;
7674

77-
/* ── Spacing ── */
75+
/* Spacing Scale */
7876
--space-xs: 0.25rem;
7977
--space-sm: 0.5rem;
8078
--space-md: 0.75rem;
@@ -85,31 +83,161 @@
8583
--space-4xl: 3rem;
8684
--space-5xl: 4rem;
8785
--space-6xl: 6rem;
88-
--space-7xl: 7rem;
86+
--space-7xl: 8rem;
8987

90-
--pad-section: 6rem 2.5rem;
91-
--pad-section-lg: 7rem 2.5rem;
92-
--pad-hero: 5rem 2.5rem;
88+
/* Padding Shortcuts */
89+
--pad-section: var(--space-6xl) var(--space-3xl);
90+
--pad-section-lg: var(--space-7xl) var(--space-3xl);
91+
--pad-hero: var(--space-5xl) var(--space-3xl);
9392

94-
/* ── Layout ── */
93+
/* Layout */
9594
--max-w: 1200px;
96-
--max-w-prose: 760px;
97-
--max-w-body: 480px;
98-
--max-w-tagline: 600px;
99-
--nav-h: 60px;
95+
--max-w-prose: 800px;
96+
--max-w-body: 520px;
97+
--max-w-tagline: 640px;
98+
--nav-h: 80px;
10099

101-
/* ── Transitions ── */
102-
--transition-fast: 0.15s;
103-
--ease-default: ease;
104-
105-
/* ── Z-index ── */
100+
/* Z-Index */
106101
--z-nav: 100;
102+
--z-modal: 200;
103+
104+
/* Transitions - Heavy Easing */
105+
--ease-cinematic: cubic-bezier(0.85, 0, 0.15, 1);
106+
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
107+
--transition-fast: 0.3s var(--ease-out-expo);
108+
--transition-slow: 0.8s var(--ease-cinematic);
109+
110+
/* Buttons */
111+
--btn-pad: 1rem 2rem;
112+
113+
--font-mono: 'Geist Mono Variable', monospace;
114+
}
115+
116+
/* Base Styles */
117+
*, *::before, *::after {
118+
box-sizing: border-box;
119+
margin: 0;
120+
padding: 0;
121+
}
122+
123+
body {
124+
background: var(--bg);
125+
color: var(--text-primary);
126+
font-family: var(--font-mono);
127+
-webkit-font-smoothing: antialiased;
128+
-moz-osx-font-smoothing: grayscale;
129+
line-height: var(--lh-default);
130+
overflow-x: hidden;
131+
}
132+
133+
::selection {
134+
background: var(--text-primary);
135+
color: var(--bg);
136+
}
137+
138+
/* Hide scrollbar for cinematic feel */
139+
::-webkit-scrollbar {
140+
width: 0px;
141+
background: transparent;
142+
}
107143

108-
/* ── Breakpoints (reference only — used in @media) ── */
109-
/* --bp-mobile: 768px; */
144+
h1, h2, h3, h4, h5, h6 {
145+
font-weight: var(--fw-bold);
146+
line-height: var(--lh-heading);
147+
margin: 0;
148+
}
149+
150+
p {
151+
margin: 0;
152+
}
153+
154+
a {
155+
color: inherit;
156+
text-decoration: underline;
157+
text-underline-offset: 0.2em;
158+
}
159+
160+
/* Utilities */
161+
.text-muted { color: var(--text-muted); }
162+
.text-secondary { color: var(--text-secondary); }
163+
164+
/* Global components previously relying on light themes */
165+
.btn-primary {
166+
display: inline-block;
167+
font-family: var(--font-mono);
168+
font-size: var(--fs-btn);
169+
font-weight: var(--fw-bold);
170+
letter-spacing: var(--ls-wider);
171+
padding: var(--btn-pad);
172+
border: 1px solid var(--text-primary);
173+
background: transparent;
174+
color: var(--text-primary);
175+
text-decoration: none;
176+
text-transform: uppercase;
177+
transition: all var(--transition-slow);
178+
backdrop-filter: blur(4px);
179+
position: relative;
180+
overflow: hidden;
181+
}
182+
183+
.btn-primary::before {
184+
content: '';
185+
position: absolute;
186+
top: 0; left: 0; right: 0; bottom: 0;
187+
background: var(--text-primary);
188+
transform: scaleX(0);
189+
transform-origin: right;
190+
transition: transform var(--transition-slow);
191+
z-index: -1;
192+
}
193+
194+
.btn-primary:hover {
195+
color: var(--bg);
196+
box-shadow: 0 0 20px rgba(255,255,255,0.2);
197+
}
198+
199+
.btn-primary:hover::before {
200+
transform: scaleX(1);
201+
transform-origin: left;
202+
}
203+
204+
.btn-secondary {
205+
display: inline-block;
206+
font-family: var(--font-mono);
207+
font-size: var(--fs-btn);
208+
letter-spacing: var(--ls-wider);
209+
padding: var(--btn-pad);
210+
border: 1px solid var(--border);
211+
background: transparent;
212+
color: var(--text-secondary);
213+
text-decoration: none;
214+
text-transform: uppercase;
215+
transition: all var(--transition-slow);
216+
}
217+
218+
.btn-secondary:hover {
219+
border-color: var(--text-primary);
220+
color: var(--text-primary);
221+
background: rgba(255,255,255,0.05);
222+
}
223+
224+
/* 3D Utility Classes */
225+
.preserve-3d {
226+
transform-style: preserve-3d;
227+
perspective: 1000px;
228+
}
229+
230+
/* Glitch Effect */
231+
@keyframes textGlitch {
232+
0% { transform: translate(0); opacity: 1; }
233+
2% { transform: translate(-2px, 1px); opacity: 0.8; }
234+
4% { transform: translate(2px, -1px); opacity: 0.9; }
235+
6% { transform: translate(0); opacity: 1; }
236+
100% { transform: translate(0); opacity: 1; }
237+
}
110238

111-
/* ── Buttons ── */
112-
--btn-pad: 0.85rem 1.75rem;
239+
.glitch-subtle {
240+
animation: textGlitch 8s infinite var(--ease-cinematic);
113241
}
114242

115243
/* ═══════════════════════════════════════════

0 commit comments

Comments
 (0)