Skip to content

Commit 28e4b95

Browse files
committed
feat: implement HieroMarkScene component and update HeroSection to use it
Signed-off-by: Ntege Daniel <danientege785@gmail.com>
1 parent 6bc9398 commit 28e4b95

6 files changed

Lines changed: 234 additions & 136 deletions

File tree

src/app/globals.css

Lines changed: 176 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -311,181 +311,233 @@
311311
}
312312

313313
/* ============================================
314-
Hero consensus lattice — components/HeroSection/ConsensusLattice
314+
Hero brand scene — components/HeroSection/HieroMarkScene
315315
316-
A real 3D scene rather than a picture of one: five node timelines standing
317-
around a circle, five rings for the consensus rounds, and gossip crossing
318-
between them, all in the browser's own perspective so depth comes from the
319-
projection instead of from shading.
320-
321-
The scene turns through a limited arc — roughly ±15° — rather than spinning.
322-
That is a rendering decision as much as a calm one: at that amplitude a flat
323-
disc foreshortens by under 4%, so every point can stay a plain round div
324-
and none of the ~50 elements needs a counter-rotation to keep facing front.
316+
Hedera's homepage gives the right side of its hero to one tall, luminous
317+
visual and lets a dark gradient blend that object back into the copy. This
318+
follows the same composition with Hiero's own material: the real monogram
319+
is embedded in a ledger plane, while rails and event nodes connect it to
320+
the gossip field already spread behind the hero.
325321
============================================ */
326322

327-
/* Below `xl` the lattice is a band of its own between the credential and the
328-
wordmark. The space above the wordmark was empty at those widths and the
329-
object was bled so far past the right edge that only a cropped sliver of it
330-
stayed on screen; giving it a row in the flow fixes both at once, and the
331-
hero is content-height there so no gap is left over to fill.
323+
.hero-mark-scene {
324+
@apply pointer-events-none relative mt-1 h-[clamp(12rem,38vw,17rem)] w-full;
325+
@apply xl:absolute xl:inset-y-0 xl:right-[-3%] xl:left-auto xl:mt-0;
326+
@apply xl:h-auto xl:w-[60%] xl:-z-10;
332327

333-
From `xl` there is a free half to stand it in, so it lifts out of the flow
334-
and takes the right of the frame, bled past the edge — the object carries
335-
on past the frame rather than sitting inside it like a stock illustration. */
336-
.hero-lattice {
337-
@apply pointer-events-none relative grid w-full place-items-center;
338-
@apply mt-3 h-34 perspective-[74rem] sm:h-[clamp(9.5rem,24vh,16rem)];
339-
@apply xl:mt-0;
340-
@apply xl:absolute xl:inset-y-0 xl:right-[-4%] xl:left-auto xl:-z-10;
341-
@apply xl:h-auto xl:w-[min(48rem,56%)];
328+
mask-image: linear-gradient(
329+
to right,
330+
transparent 0%,
331+
black 19%,
332+
black 100%
333+
);
342334
}
343335

344-
.hero-lattice-tilt {
345-
--tilt-x: 0deg;
346-
--tilt-y: 0deg;
336+
/* A soft pool of brand light makes the white mark feel lit by the scene,
337+
rather than laid on top of it. */
338+
.hero-mark-scene::before {
339+
@apply absolute top-1/2 right-[-10%] h-[125%] w-[88%] -translate-y-1/2;
340+
341+
content: "";
342+
background: radial-gradient(
343+
ellipse,
344+
rgb(255 158 199 / 50%) 0%,
345+
rgb(217 45 106 / 24%) 40%,
346+
transparent 72%
347+
);
348+
}
347349

348-
/* Long enough that the object follows the pointer rather than snapping to
349-
it, which is what makes it read as mass. */
350-
@apply transform-3d transition-transform duration-500;
351-
@apply ease-[cubic-bezier(0.22,0.85,0.28,1)] motion-reduce:transition-none;
350+
/* The angled ledger plane gives the mark a setting and depth. Its grid is
351+
deliberately sparse enough to remain texture behind the logo. */
352+
.hero-mark-grid {
353+
@apply absolute top-[12%] right-[-7%] h-[76%] w-[78%];
354+
@apply border border-white/14 shadow-[0_34px_70px_rgb(25_1_10_/_28%)];
352355

353-
transform: rotateX(var(--tilt-x)) rotateY(var(--tilt-y));
356+
clip-path: polygon(11% 0, 100% 0, 89% 100%, 0 100%);
357+
background:
358+
repeating-linear-gradient(
359+
90deg,
360+
transparent 0 4.9rem,
361+
rgb(255 255 255 / 7%) 4.9rem calc(4.9rem + 1px)
362+
),
363+
repeating-linear-gradient(
364+
0deg,
365+
transparent 0 4rem,
366+
rgb(255 255 255 / 6%) 4rem calc(4rem + 1px)
367+
),
368+
linear-gradient(135deg, rgb(255 255 255 / 9%), rgb(255 255 255 / 1%));
369+
transform: perspective(60rem) rotateY(-12deg) rotateZ(-5deg);
354370
}
355371

356-
/* The scene is authored at a fixed size in px so the geometry stays exact,
357-
then scaled once here to meet the viewport. A ladder rather than a fluid
358-
clamp: `scale` takes a number, and a number cannot be calc'd against vw. */
359-
.hero-lattice-stage {
360-
@apply relative h-0 w-0 transform-3d;
361-
@apply scale-[0.42] sm:scale-[0.5] md:scale-[0.56];
362-
@apply xl:scale-[0.88] min-[90rem]:scale-100;
372+
.hero-mark-rail {
373+
@apply absolute right-[-12%] h-px w-[88%] origin-right rotate-[-13deg];
363374

364-
transform: rotateX(9deg);
365-
animation: hero-lattice-turn 26s ease-in-out infinite alternate;
375+
background: linear-gradient(
376+
to right,
377+
transparent,
378+
rgb(255 255 255 / 25%) 20%,
379+
rgb(255 207 228 / 76%) 64%,
380+
transparent
381+
);
382+
box-shadow: 0 0 18px rgb(255 156 198 / 35%);
366383
}
367384

368-
/* A pool of light on the ground plane. It is the one piece of the scene that
369-
is not structure — it is there so the lattice reads as standing in a space
370-
rather than floating in front of a gradient. */
371-
.hero-lattice-stage::before {
372-
@apply absolute top-0 left-0 h-[470px] w-[470px] rounded-full;
373-
@apply -mt-[235px] -ml-[235px];
385+
.hero-mark-rail::after {
386+
@apply absolute top-[-2px] left-[18%] h-[5px] w-[5px] rounded-full bg-white;
387+
@apply shadow-[0_0_12px_rgb(255_174_208_/_95%)];
374388

375389
content: "";
376-
background: radial-gradient(
377-
circle,
378-
rgb(255 150 195 / 40%),
379-
rgb(217 45 106 / 14%) 40%,
380-
transparent 66%
381-
);
382-
transform: translate3d(0, 196px, 0) rotateX(90deg);
383390
}
384391

385-
.hero-lattice-ring,
386-
.hero-lattice-column,
387-
.hero-lattice-node,
388-
.hero-lattice-edge {
389-
@apply absolute top-0 left-0;
392+
.hero-mark-rail--top {
393+
@apply top-[23%];
394+
}
395+
396+
.hero-mark-rail--middle {
397+
@apply top-[52%] right-[-4%] w-[94%];
390398
}
391399

392-
/* Rounds. Lying flat in the ground plane, they project as ellipses, which is
393-
what tells the eye there is a third axis before anything starts moving. */
394-
.hero-lattice-ring {
395-
@apply rounded-full border border-white/30;
396-
@apply shadow-[0_0_24px_rgb(255_130_185_/_16%),inset_0_0_32px_rgb(255_130_185_/_8%)];
400+
.hero-mark-rail--bottom {
401+
@apply top-[79%] right-[-18%] w-[82%];
397402
}
398403

399-
/* Node timelines. Equal length, equal weight, equal distance from a centre
400-
that is deliberately empty. */
401-
.hero-lattice-column {
402-
@apply -ml-[0.5px] w-px;
404+
.hero-mark-emblem,
405+
.hero-mark-echo {
406+
@apply absolute top-1/2 right-[7%] aspect-square w-[min(13rem,56vw)];
403407

404-
background: linear-gradient(
405-
to bottom,
406-
transparent,
407-
rgb(255 255 255 / 52%) 18%,
408-
rgb(255 255 255 / 52%) 82%,
409-
transparent
410-
);
408+
translate: 0 -50%;
411409
}
412410

413-
.hero-lattice-node {
414-
@apply -mt-1.5 -ml-1.5 h-3 w-3 rounded-full;
415-
@apply shadow-[0_0_12px_rgb(255_160_200_/_90%),0_0_30px_rgb(217_45_106_/_60%)];
411+
/* The echo is a low-contrast second plane, not a second logo. It gives the
412+
solid mark a trailing edge like the layered forms in the reference. */
413+
.hero-mark-echo {
414+
@apply right-[2%] opacity-12;
416415

417-
background: radial-gradient(
418-
circle,
419-
var(--color-white) 0 30%,
420-
rgb(255 210 230 / 95%) 46%,
421-
rgb(233 92 148 / 70%) 62%,
422-
transparent 72%
423-
);
416+
filter: blur(0.4px);
417+
scale: 1.13;
418+
translate: 0 -43%;
424419
}
425420

426-
.hero-lattice-edge {
427-
@apply -mt-[0.5px] h-px origin-left;
421+
.hero-mark-emblem {
422+
@apply grid place-items-center rounded-[clamp(1.5rem,3vw,3rem)];
423+
@apply border border-white/22;
424+
@apply shadow-[0_34px_85px_rgb(29_2_12_/_45%),inset_0_1px_0_rgb(255_255_255_/_20%)];
428425

429-
background: linear-gradient(
430-
to right,
431-
rgb(255 255 255 / 6%),
432-
rgb(255 186 214 / 85%),
433-
rgb(255 255 255 / 6%)
434-
);
426+
background:
427+
radial-gradient(
428+
circle at 30% 18%,
429+
rgb(255 255 255 / 17%),
430+
transparent 38%
431+
),
432+
linear-gradient(145deg, rgb(104 12 48 / 72%), rgb(50 4 20 / 44%));
433+
backdrop-filter: blur(6px);
435434
}
436435

437-
/* One gossip event travelling the edge it was sent along. The timelines and
438-
rounds are the structure; this is the only thing in the scene that is an
439-
event, so it is the only thing that moves along a path. */
440-
.hero-lattice-edge::after {
441-
@apply absolute top-[-2px] left-0 h-[5px] w-[5px] rounded-full bg-white;
442-
@apply shadow-[0_0_10px_rgb(255_170_205_/_90%)];
436+
.hero-mark-emblem::before {
437+
@apply absolute inset-[5%] rounded-[inherit] border border-white/8;
443438

444439
content: "";
445-
animation: hero-lattice-gossip 4.4s ease-in-out infinite;
446-
animation-delay: var(--edge-delay, 0ms);
447440
}
448441

449-
@keyframes hero-lattice-turn {
442+
.hero-mark-image {
443+
@apply h-[72%] w-[72%] object-contain;
444+
445+
filter: brightness(0) invert(1) drop-shadow(0 0 24px rgb(255 181 213 / 34%));
446+
}
447+
448+
.hero-mark-node {
449+
@apply absolute h-2.5 w-2.5 rounded-full bg-white;
450+
@apply shadow-[0_0_12px_rgb(255_174_208_/_95%),0_0_34px_rgb(217_45_106_/_75%)];
451+
}
452+
453+
.hero-mark-node--one {
454+
@apply top-[19%] right-[43%];
455+
}
456+
457+
.hero-mark-node--two {
458+
@apply top-[39%] right-[12%] h-1.5 w-1.5;
459+
}
460+
461+
.hero-mark-node--three {
462+
@apply right-[49%] bottom-[20%] h-1.5 w-1.5;
463+
}
464+
465+
.hero-mark-node--four {
466+
@apply right-[5%] bottom-[12%];
467+
}
468+
469+
@media (min-width: 80rem) {
470+
.hero-mark-emblem,
471+
.hero-mark-echo {
472+
@apply right-[8%] w-[min(33rem,66%)];
473+
}
474+
475+
.hero-mark-echo {
476+
@apply right-[3%];
477+
}
478+
}
479+
480+
@media (prefers-reduced-motion: no-preference) {
481+
.hero-mark-emblem {
482+
animation: hero-mark-float 8s ease-in-out infinite alternate;
483+
}
484+
485+
.hero-mark-grid {
486+
animation: hero-mark-plane 12s ease-in-out infinite alternate;
487+
}
488+
489+
.hero-mark-rail::after {
490+
animation: hero-mark-signal 5.5s ease-in-out infinite;
491+
}
492+
493+
.hero-mark-rail--middle::after {
494+
animation-delay: -1.8s;
495+
}
496+
497+
.hero-mark-rail--bottom::after {
498+
animation-delay: -3.6s;
499+
}
500+
}
501+
502+
@keyframes hero-mark-float {
503+
from {
504+
translate: 0 -50%;
505+
rotate: -1deg;
506+
}
507+
508+
to {
509+
translate: -0.4rem calc(-50% - 0.6rem);
510+
rotate: 1.25deg;
511+
}
512+
}
513+
514+
@keyframes hero-mark-plane {
450515
from {
451-
transform: rotateX(9deg) rotateY(-15deg);
516+
transform: perspective(60rem) rotateY(-12deg) rotateZ(-5deg) translateX(0);
452517
}
453518

454519
to {
455-
transform: rotateX(9deg) rotateY(15deg);
520+
transform: perspective(60rem) rotateY(-9deg) rotateZ(-3.5deg)
521+
translateX(-0.6rem);
456522
}
457523
}
458524

459-
@keyframes hero-lattice-gossip {
525+
@keyframes hero-mark-signal {
460526
0%,
461-
8% {
527+
10% {
462528
opacity: 0;
463-
transform: translateX(0);
529+
translate: 0;
464530
}
465531

466-
18%,
532+
20%,
467533
72% {
468534
opacity: 1;
469535
}
470536

471-
82%,
537+
90%,
472538
100% {
473539
opacity: 0;
474-
transform: translateX(var(--edge-length, 0));
475-
}
476-
}
477-
478-
@media (prefers-reduced-motion: reduce) {
479-
.hero-lattice-stage {
480-
animation: none;
481-
transform: rotateX(9deg) rotateY(-9deg);
482-
}
483-
484-
.hero-lattice-edge::after {
485-
@apply opacity-100;
486-
487-
animation: none;
488-
transform: translateX(calc(var(--edge-length, 0px) / 2));
540+
translate: 34vw;
489541
}
490542
}
491543

src/components/HeroSection/HeroTraces.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
*
44
* A flat field of gossip traces — events and the links between them — spread
55
* across the whole hero behind the type. It is the same material as the
6-
* ConsensusLattice beside it, drawn without perspective and at a fraction of
7-
* the brightness, so the object in the frame reads as a close-up of a network
8-
* that carries on past the edges rather than an illustration parked on a
9-
* gradient.
6+
* HieroMarkScene beside it, drawn without perspective and at a fraction of the
7+
* brightness, so the framed mark reads as part of a network that carries on
8+
* past the edges rather than an illustration parked on a gradient.
109
*
1110
* No JS: the scatter comes from a seeded generator evaluated once at module
1211
* scope, so the markup is identical on the server and in the browser and the

0 commit comments

Comments
 (0)