Skip to content

Commit 44c474e

Browse files
feat: add matrix-style background and showcase section to hero, enhancing visual appeal and interactivity
1 parent 31f5e47 commit 44c474e

3 files changed

Lines changed: 404 additions & 0 deletions

File tree

assets/css/style.css

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ a:hover {
6868
text-decoration: underline;
6969
}
7070

71+
/* --- Matrix canvas background (hero only) --- */
72+
.matrix-canvas {
73+
position: absolute;
74+
inset: 0;
75+
width: 100%;
76+
height: 100%;
77+
opacity: 0.28;
78+
mix-blend-mode: screen;
79+
pointer-events: none;
80+
}
81+
7182
/* --- Header --- */
7283
.site-header {
7384
position: sticky;
@@ -355,6 +366,264 @@ main {
355366
justify-content: center;
356367
}
357368

369+
/* --- Hero showcase (3D-ish product rendering) --- */
370+
.hero-showcase {
371+
margin: 2.25rem auto 0;
372+
max-width: 980px;
373+
position: relative;
374+
perspective: 1200px;
375+
}
376+
377+
.showcase-frame {
378+
position: relative;
379+
border-radius: 22px;
380+
border: 1px solid rgba(255, 255, 255, 0.18);
381+
background: linear-gradient(
382+
180deg,
383+
rgba(255, 255, 255, 0.09),
384+
rgba(255, 255, 255, 0.04)
385+
);
386+
backdrop-filter: blur(18px) saturate(160%);
387+
box-shadow:
388+
0 40px 80px rgba(0, 0, 0, 0.35),
389+
0 0 0 1px rgba(255, 255, 255, 0.06) inset,
390+
0 0 140px rgba(79, 70, 229, 0.22);
391+
overflow: hidden;
392+
transform-style: preserve-3d;
393+
transition: transform 0.18s ease;
394+
}
395+
396+
.showcase-frame::before {
397+
content: "";
398+
position: absolute;
399+
inset: 0;
400+
background:
401+
radial-gradient(
402+
ellipse 55% 60% at 20% 20%,
403+
rgba(99, 102, 241, 0.35),
404+
transparent 60%
405+
),
406+
radial-gradient(
407+
ellipse 55% 60% at 80% 20%,
408+
rgba(34, 211, 238, 0.25),
409+
transparent 60%
410+
),
411+
radial-gradient(circle at 50% 100%, rgba(255, 255, 255, 0.09), transparent 55%);
412+
pointer-events: none;
413+
opacity: 0.9;
414+
}
415+
416+
.showcase-topbar {
417+
position: relative;
418+
display: flex;
419+
align-items: center;
420+
gap: 0.55rem;
421+
padding: 0.75rem 1rem;
422+
border-bottom: 1px solid rgba(255, 255, 255, 0.12);
423+
background: rgba(15, 23, 42, 0.35);
424+
}
425+
426+
.dot {
427+
width: 10px;
428+
height: 10px;
429+
border-radius: 999px;
430+
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16) inset;
431+
}
432+
.dot--red {
433+
background: #fb7185;
434+
}
435+
.dot--yellow {
436+
background: #fbbf24;
437+
}
438+
.dot--green {
439+
background: #34d399;
440+
}
441+
442+
.showcase-title {
443+
margin-left: 0.35rem;
444+
font-size: 0.85rem;
445+
font-weight: 700;
446+
color: rgba(226, 232, 240, 0.9);
447+
letter-spacing: -0.02em;
448+
}
449+
450+
.showcase-pill {
451+
margin-left: auto;
452+
font-size: 0.7rem;
453+
font-weight: 800;
454+
letter-spacing: 0.12em;
455+
text-transform: uppercase;
456+
color: #0f172a;
457+
background: linear-gradient(135deg, #67e8f9 0%, #a5b4fc 100%);
458+
padding: 0.28rem 0.6rem;
459+
border-radius: 999px;
460+
}
461+
462+
.showcase-grid {
463+
position: relative;
464+
padding: 1.1rem 1.1rem 1.2rem;
465+
display: grid;
466+
gap: 0.85rem;
467+
grid-template-columns: 1fr;
468+
}
469+
470+
@media (min-width: 820px) {
471+
.showcase-grid {
472+
grid-template-columns: 1.2fr 1fr;
473+
align-items: stretch;
474+
}
475+
}
476+
477+
.metric-tile,
478+
.timeline {
479+
position: relative;
480+
border-radius: 16px;
481+
border: 1px solid rgba(255, 255, 255, 0.16);
482+
background: linear-gradient(
483+
180deg,
484+
rgba(255, 255, 255, 0.08),
485+
rgba(255, 255, 255, 0.04)
486+
);
487+
box-shadow:
488+
0 18px 42px rgba(0, 0, 0, 0.18),
489+
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
490+
padding: 1rem 1rem 1.1rem;
491+
text-align: left;
492+
overflow: hidden;
493+
}
494+
495+
.metric-kicker {
496+
font-size: 0.72rem;
497+
font-weight: 800;
498+
letter-spacing: 0.14em;
499+
text-transform: uppercase;
500+
color: rgba(226, 232, 240, 0.72);
501+
}
502+
503+
.metric-value {
504+
margin-top: 0.35rem;
505+
font-size: 1.6rem;
506+
font-weight: 900;
507+
letter-spacing: -0.03em;
508+
color: #f8fafc;
509+
}
510+
511+
.metric-sub {
512+
margin-top: 0.2rem;
513+
font-size: 0.92rem;
514+
color: rgba(226, 232, 240, 0.72);
515+
}
516+
517+
.spark {
518+
margin-top: 0.85rem;
519+
height: 56px;
520+
border-radius: 12px;
521+
border: 1px solid rgba(255, 255, 255, 0.12);
522+
background:
523+
radial-gradient(circle at 20% 30%, rgba(99, 102, 241, 0.55), transparent 55%),
524+
radial-gradient(circle at 60% 60%, rgba(34, 211, 238, 0.45), transparent 55%),
525+
linear-gradient(135deg, rgba(15, 23, 42, 0.35), rgba(15, 23, 42, 0.15));
526+
position: relative;
527+
overflow: hidden;
528+
}
529+
530+
.spark::before {
531+
content: "";
532+
position: absolute;
533+
inset: -40% -20%;
534+
background: conic-gradient(
535+
from 180deg,
536+
rgba(99, 102, 241, 0.0),
537+
rgba(99, 102, 241, 0.35),
538+
rgba(34, 211, 238, 0.25),
539+
rgba(99, 102, 241, 0.0)
540+
);
541+
animation: spin-spark 10s linear infinite;
542+
opacity: 0.6;
543+
}
544+
545+
@keyframes spin-spark {
546+
to {
547+
transform: rotate(360deg);
548+
}
549+
}
550+
551+
.timeline {
552+
grid-column: 1 / -1;
553+
}
554+
555+
@media (min-width: 820px) {
556+
.timeline {
557+
grid-column: 2;
558+
grid-row: 1 / span 3;
559+
}
560+
}
561+
562+
.timeline-head {
563+
display: flex;
564+
align-items: center;
565+
gap: 0.5rem;
566+
justify-content: flex-start;
567+
color: rgba(226, 232, 240, 0.9);
568+
font-weight: 800;
569+
letter-spacing: -0.02em;
570+
}
571+
572+
.chip {
573+
font-size: 0.7rem;
574+
font-weight: 800;
575+
letter-spacing: 0.1em;
576+
text-transform: uppercase;
577+
padding: 0.2rem 0.45rem;
578+
border-radius: 999px;
579+
border: 1px solid rgba(255, 255, 255, 0.14);
580+
color: rgba(226, 232, 240, 0.8);
581+
background: rgba(15, 23, 42, 0.35);
582+
}
583+
584+
.timeline-list {
585+
margin: 0.75rem 0 0;
586+
padding: 0;
587+
list-style: none;
588+
display: grid;
589+
gap: 0.55rem;
590+
color: rgba(226, 232, 240, 0.76);
591+
font-weight: 600;
592+
}
593+
594+
.timeline-list li {
595+
display: flex;
596+
align-items: center;
597+
gap: 0.55rem;
598+
}
599+
600+
.t-dot {
601+
width: 8px;
602+
height: 8px;
603+
border-radius: 999px;
604+
background: linear-gradient(135deg, #67e8f9 0%, #a5b4fc 100%);
605+
box-shadow:
606+
0 0 0 1px rgba(255, 255, 255, 0.16) inset,
607+
0 0 18px rgba(34, 211, 238, 0.25);
608+
}
609+
610+
.showcase-shadow {
611+
position: absolute;
612+
left: 50%;
613+
bottom: -18px;
614+
width: min(720px, 92vw);
615+
height: 56px;
616+
transform: translateX(-50%);
617+
background: radial-gradient(
618+
ellipse at center,
619+
rgba(0, 0, 0, 0.55),
620+
transparent 65%
621+
);
622+
filter: blur(18px);
623+
opacity: 0.35;
624+
pointer-events: none;
625+
}
626+
358627
/* --- Buttons --- */
359628
.btn {
360629
display: inline-flex;

assets/js/main.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,92 @@
138138
}
139139

140140
wireDirectDownloads();
141+
142+
// --- Matrix-style background (hero only) ---
143+
function startMatrix(canvas) {
144+
if (!canvas) return;
145+
if (window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
146+
return;
147+
}
148+
var ctx = canvas.getContext("2d");
149+
if (!ctx) return;
150+
151+
var dpr = Math.max(1, Math.min(2, window.devicePixelRatio || 1));
152+
var cols = 0;
153+
var drops = [];
154+
var raf = 0;
155+
156+
function resize() {
157+
var w = canvas.clientWidth || canvas.parentElement.clientWidth || window.innerWidth;
158+
var h = canvas.clientHeight || canvas.parentElement.clientHeight || 420;
159+
canvas.width = Math.floor(w * dpr);
160+
canvas.height = Math.floor(h * dpr);
161+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
162+
cols = Math.floor(w / 14);
163+
drops = new Array(cols).fill(0).map(function () {
164+
return Math.random() * h;
165+
});
166+
}
167+
168+
function step() {
169+
var w = canvas.clientWidth || window.innerWidth;
170+
var h = canvas.clientHeight || 420;
171+
ctx.fillStyle = "rgba(12, 18, 34, 0.18)";
172+
ctx.fillRect(0, 0, w, h);
173+
174+
ctx.font = "12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
175+
for (var i = 0; i < drops.length; i++) {
176+
var x = i * 14 + 6;
177+
var y = drops[i];
178+
// Soft aqua/purple palette to match the hero gradients (not pure green).
179+
var hue = (190 + (i % 6) * 18) % 360;
180+
ctx.fillStyle = "hsla(" + hue + ", 90%, 70%, 0.75)";
181+
var code = 0x30A0 + Math.floor(Math.random() * 96);
182+
ctx.fillText(String.fromCharCode(code), x, y);
183+
drops[i] = y + 14 + Math.random() * 10;
184+
if (drops[i] > h + 40 && Math.random() > 0.975) {
185+
drops[i] = -Math.random() * 120;
186+
}
187+
}
188+
raf = window.requestAnimationFrame(step);
189+
}
190+
191+
resize();
192+
step();
193+
194+
window.addEventListener("resize", resize, { passive: true });
195+
return function stop() {
196+
window.cancelAnimationFrame(raf);
197+
};
198+
}
199+
200+
// --- Subtle 3D tilt (hero mock + cards) ---
201+
function wireTilt(el) {
202+
if (!el) return;
203+
if (window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
204+
return;
205+
}
206+
var inner = el.querySelector(".showcase-frame") || el;
207+
var max = 8; // degrees
208+
209+
function onMove(e) {
210+
var rect = el.getBoundingClientRect();
211+
var x = (e.clientX - rect.left) / rect.width;
212+
var y = (e.clientY - rect.top) / rect.height;
213+
var rx = (0.5 - y) * max;
214+
var ry = (x - 0.5) * max;
215+
inner.style.transform = "rotateX(" + rx.toFixed(2) + "deg) rotateY(" + ry.toFixed(2) + "deg)";
216+
}
217+
218+
function reset() {
219+
inner.style.transform = "rotateX(0deg) rotateY(0deg)";
220+
}
221+
222+
el.addEventListener("pointermove", onMove, { passive: true });
223+
el.addEventListener("pointerleave", reset, { passive: true });
224+
el.addEventListener("pointerdown", reset, { passive: true });
225+
}
226+
227+
startMatrix(document.querySelector("[data-matrix]"));
228+
document.querySelectorAll("[data-tilt]").forEach(wireTilt);
141229
})();

0 commit comments

Comments
 (0)