Skip to content

Commit 34f580f

Browse files
Lingz450claude
andcommitted
3D + gradient design layer: tilting hero terminal, aurora, spotlight
One design thesis: every gradient runs blueprint blue -> cyan -> verified green (plan -> live), matching the brand tokens in both themes. - Hero terminal now sits on a 3D stage: cursor-follow perspective tilt with status chips floating at different translateZ depths - Aurora: three slow-drifting blurred orbs behind hero/CTA sections - Scroll reveals rise off a shallow 3D plane (perspective + rotateX) - Cursor spotlight on all cards via one delegated listener + CSS vars - Gradient scroll-progress hairline along the top edge - Industries marquee strip, gradient count-up stats, primary-button light sweep, breathing hero-headline gradient, hover glow on cards All transform/opacity based, no new dependencies; touch devices skip tilt/spotlight and reduced motion disables every ambient animation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent cbadda2 commit 34f580f

10 files changed

Lines changed: 478 additions & 9 deletions

File tree

src/app/globals.css

Lines changed: 232 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
--paper: #f7f8f6;
1313
--surface: #ffffff;
1414
--blueprint: #1b3fae;
15+
--accent-2: #0e7490;
1516
--verified: #0e9f6e;
1617
--slate: #5b6472;
1718
--grid: #e3e7e2;
@@ -30,6 +31,7 @@
3031
--paper: #0b0f17;
3132
--surface: #121826;
3233
--blueprint: #6f8eff;
34+
--accent-2: #45c4e0;
3335
--verified: #25c08a;
3436
--slate: #97a1b0;
3537
--grid: #232b3a;
@@ -103,11 +105,15 @@ html {
103105
background: var(--paper);
104106
}
105107

106-
/* Scroll-reveal (JS toggles .reveal-in via IntersectionObserver) */
108+
/* Scroll-reveal (JS toggles .reveal-in via IntersectionObserver).
109+
Content rises off a shallow 3D plane — a hint of depth, not a flip. */
107110
.reveal {
108111
opacity: 0;
109-
transform: translateY(12px);
110-
transition: opacity 0.35s ease-out, transform 0.35s ease-out;
112+
transform: perspective(900px) translateY(18px) rotateX(5deg) scale(0.995);
113+
transform-origin: 50% 100%;
114+
transition:
115+
opacity 0.5s ease-out,
116+
transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
111117
}
112118
.reveal-in {
113119
opacity: 1;
@@ -172,6 +178,172 @@ html {
172178
box-shadow: 0 0 0 4px color-mix(in srgb, var(--blueprint) 20%, transparent);
173179
}
174180

181+
/* ---- 3D + gradient design layer -------------------------------------- */
182+
183+
/* Brand gradient text: blueprint (plan) → cyan → verified green (live) */
184+
.text-gradient {
185+
background-image: linear-gradient(
186+
120deg,
187+
var(--blueprint),
188+
var(--accent-2) 55%,
189+
var(--verified)
190+
);
191+
-webkit-background-clip: text;
192+
background-clip: text;
193+
-webkit-text-fill-color: transparent;
194+
color: transparent;
195+
}
196+
197+
@keyframes hero-gradient {
198+
from {
199+
background-position: 0% 0%;
200+
}
201+
to {
202+
background-position: 100% 100%;
203+
}
204+
}
205+
206+
/* Aurora: three blurred orbs drifting very slowly behind hero sections */
207+
.aurora {
208+
position: absolute;
209+
inset: -10%;
210+
overflow: hidden;
211+
pointer-events: none;
212+
}
213+
.aurora i {
214+
position: absolute;
215+
border-radius: 9999px;
216+
filter: blur(70px);
217+
opacity: 0.35;
218+
will-change: transform;
219+
animation: aurora-drift 24s ease-in-out infinite alternate;
220+
}
221+
.dark .aurora i {
222+
opacity: 0.45;
223+
}
224+
.aurora i:nth-child(1) {
225+
width: 34rem;
226+
height: 34rem;
227+
left: -6rem;
228+
top: -6rem;
229+
background: radial-gradient(
230+
circle,
231+
color-mix(in srgb, var(--blueprint) 55%, transparent),
232+
transparent 70%
233+
);
234+
}
235+
.aurora i:nth-child(2) {
236+
width: 28rem;
237+
height: 28rem;
238+
right: -5rem;
239+
top: 15%;
240+
background: radial-gradient(
241+
circle,
242+
color-mix(in srgb, var(--accent-2) 45%, transparent),
243+
transparent 70%
244+
);
245+
animation-duration: 28s;
246+
animation-delay: -9s;
247+
}
248+
.aurora i:nth-child(3) {
249+
width: 24rem;
250+
height: 24rem;
251+
left: 38%;
252+
bottom: -10rem;
253+
background: radial-gradient(
254+
circle,
255+
color-mix(in srgb, var(--verified) 40%, transparent),
256+
transparent 70%
257+
);
258+
animation-duration: 32s;
259+
animation-delay: -16s;
260+
}
261+
@keyframes aurora-drift {
262+
from {
263+
transform: translate3d(0, 0, 0) scale(1);
264+
}
265+
to {
266+
transform: translate3d(3.5rem, 2.5rem, 0) scale(1.12);
267+
}
268+
}
269+
@media (max-width: 640px) {
270+
.aurora i {
271+
filter: blur(50px);
272+
opacity: 0.3;
273+
}
274+
.aurora i:nth-child(3) {
275+
display: none;
276+
}
277+
}
278+
@media (prefers-reduced-motion: reduce) {
279+
.aurora i {
280+
animation: none;
281+
}
282+
}
283+
284+
/* 3D tilt stage (Tilt component) */
285+
.tilt-scene {
286+
perspective: 1100px;
287+
}
288+
.tilt-body {
289+
transform-style: preserve-3d;
290+
transition: transform 0.35s ease-out;
291+
will-change: transform;
292+
}
293+
294+
/* Floating status chips around the hero terminal */
295+
.hero-chip {
296+
display: inline-flex;
297+
align-items: center;
298+
gap: 0.5rem;
299+
border-radius: 9999px;
300+
border: 1px solid var(--grid);
301+
background: color-mix(in srgb, var(--surface) 88%, transparent);
302+
backdrop-filter: blur(6px);
303+
padding: 0.4rem 0.8rem;
304+
font-family: var(--font-mono);
305+
font-size: 0.68rem;
306+
text-transform: uppercase;
307+
letter-spacing: 0.14em;
308+
color: var(--slate);
309+
box-shadow: 0 8px 24px -12px color-mix(in srgb, var(--blueprint) 40%, transparent);
310+
animation: chip-float 5.5s ease-in-out infinite alternate;
311+
}
312+
@keyframes chip-float {
313+
from {
314+
transform: translateY(0);
315+
}
316+
to {
317+
transform: translateY(-7px);
318+
}
319+
}
320+
321+
/* Industries marquee */
322+
.marquee {
323+
overflow: hidden;
324+
-webkit-mask-image: linear-gradient(
325+
90deg,
326+
transparent,
327+
#000 10%,
328+
#000 90%,
329+
transparent
330+
);
331+
mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
332+
}
333+
.marquee-track {
334+
display: flex;
335+
width: max-content;
336+
animation: marquee 36s linear infinite;
337+
}
338+
.marquee:hover .marquee-track {
339+
animation-play-state: paused;
340+
}
341+
@keyframes marquee {
342+
to {
343+
transform: translateX(-50%);
344+
}
345+
}
346+
175347
/* Work grid: cards fade/rise back in when the filter changes */
176348
@keyframes work-item-in {
177349
from {
@@ -204,14 +376,17 @@ html {
204376
font-size: clamp(2.5rem, 6vw, 4.5rem);
205377
}
206378

207-
/* Hero headline: gradient fill + subtle 3D extrude/depth */
379+
/* Hero headline: gradient fill + subtle 3D extrude/depth.
380+
The gradient breathes very slowly (background-position drift). */
208381
.hero-title {
209382
background-image: linear-gradient(
210383
150deg,
211384
var(--ink) 0%,
212385
var(--ink) 35%,
213386
var(--blueprint) 100%
214387
);
388+
background-size: 200% 200%;
389+
animation: hero-gradient 9s ease-in-out infinite alternate;
215390
-webkit-background-clip: text;
216391
background-clip: text;
217392
-webkit-text-fill-color: transparent;
@@ -256,19 +431,70 @@ html {
256431
}
257432

258433
.card {
259-
@apply rounded-card border border-grid bg-surface transition-all duration-300;
434+
@apply relative rounded-card border border-grid bg-surface transition-all duration-300;
435+
}
436+
437+
/* Cursor spotlight: --mx/--my are fed by the Spotlight component */
438+
.card::after {
439+
content: "";
440+
position: absolute;
441+
inset: 0;
442+
border-radius: inherit;
443+
opacity: 0;
444+
transition: opacity 0.3s ease;
445+
pointer-events: none;
446+
background: radial-gradient(
447+
240px circle at var(--mx, 50%) var(--my, 50%),
448+
color-mix(in srgb, var(--blueprint) 9%, transparent),
449+
transparent 70%
450+
);
451+
}
452+
.card:hover::after {
453+
opacity: 1;
260454
}
261455

262456
.card-hover {
263457
@apply hover:-translate-y-0.5 hover:border-blueprint;
264458
}
459+
.card-hover:hover {
460+
box-shadow:
461+
0 18px 46px -18px color-mix(in srgb, var(--blueprint) 35%, transparent),
462+
0 0 0 1px color-mix(in srgb, var(--blueprint) 25%, transparent);
463+
}
265464

266465
.btn {
267466
@apply inline-flex items-center justify-center gap-2 rounded-[10px] px-5 py-3 text-[0.95rem] font-medium transition-all duration-200 focus-visible:outline-2;
268467
}
269468

270469
.btn-primary {
271-
@apply btn bg-blueprint text-white hover:opacity-90;
470+
@apply btn relative overflow-hidden bg-blueprint text-white hover:opacity-95;
471+
background-image: linear-gradient(
472+
135deg,
473+
var(--blueprint) 0%,
474+
color-mix(in srgb, var(--blueprint) 45%, var(--accent-2)) 100%
475+
);
476+
}
477+
478+
/* Light sweep across the primary button on hover */
479+
.btn-primary::after {
480+
content: "";
481+
position: absolute;
482+
top: 0;
483+
bottom: 0;
484+
left: -45%;
485+
width: 45%;
486+
transform: skewX(-20deg) translateX(-130%);
487+
background: linear-gradient(
488+
90deg,
489+
transparent,
490+
rgba(255, 255, 255, 0.35),
491+
transparent
492+
);
493+
pointer-events: none;
494+
}
495+
.btn-primary:hover::after {
496+
transform: skewX(-20deg) translateX(400%);
497+
transition: transform 0.65s ease;
272498
}
273499

274500
.btn-secondary {

src/app/layout.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import "./globals.css";
66
import { Header } from "@/components/header";
77
import { Footer } from "@/components/footer";
88
import { WhatsAppFab } from "@/components/whatsapp-fab";
9+
import { ScrollProgress } from "@/components/scroll-progress";
10+
import { Spotlight } from "@/components/spotlight";
911
import { JsonLd } from "@/components/json-ld";
1012
import { site } from "@/content/site";
1113

@@ -92,6 +94,8 @@ export default function RootLayout({
9294
/>
9395
</filter>
9496
</svg>
97+
<ScrollProgress />
98+
<Spotlight />
9599
<Header />
96100
<main id="main">{children}</main>
97101
<Footer />

0 commit comments

Comments
 (0)