STYLED - Add a layered ambient backdrop behind all heroes
Replace the flat, empty hero background with a pure-CSS layered backdrop: faded grid, brand glow, drifting brand orbs, grain, and a bottom fade that blends the hero into page content. Applies to both the home hero and the compact page heroes via HeroMotionBackdrop; respects prefers-reduced-motion.
This commit is contained in:
+127
@@ -295,6 +295,133 @@ html[lang="ar"] .eyebrow {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Layered hero backdrop (HeroMotionBackdrop) ---- */
|
||||||
|
.hero-backdrop-base {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: hsl(var(--background));
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-backdrop-grid {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background-image:
|
||||||
|
linear-gradient(hsl(var(--border) / 0.55) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, hsl(var(--border) / 0.55) 1px, transparent 1px);
|
||||||
|
background-size: 30px 30px;
|
||||||
|
background-position: center top;
|
||||||
|
opacity: 0.55;
|
||||||
|
-webkit-mask-image: radial-gradient(ellipse 78% 58% at 50% 30%, #000 0%, transparent 72%);
|
||||||
|
mask-image: radial-gradient(ellipse 78% 58% at 50% 30%, #000 0%, transparent 72%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .hero-backdrop-grid {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-backdrop-glow {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background:
|
||||||
|
radial-gradient(58% 46% at 50% 20%, hsl(var(--brand-primary) / 0.16), transparent 70%),
|
||||||
|
radial-gradient(46% 42% at 80% 10%, hsl(var(--brand-secondary) / 0.13), transparent 68%),
|
||||||
|
radial-gradient(48% 44% at 16% 18%, hsl(var(--brand-primary) / 0.1), transparent 66%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-orb {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 9999px;
|
||||||
|
filter: blur(64px);
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-orb-1 {
|
||||||
|
top: -10%;
|
||||||
|
inset-inline-start: -8%;
|
||||||
|
height: 32rem;
|
||||||
|
width: 32rem;
|
||||||
|
background: hsl(var(--brand-primary) / 0.18);
|
||||||
|
animation: hero-orb-drift-a 22s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-orb-2 {
|
||||||
|
top: -6%;
|
||||||
|
inset-inline-end: -10%;
|
||||||
|
height: 28rem;
|
||||||
|
width: 28rem;
|
||||||
|
background: hsl(var(--brand-secondary) / 0.15);
|
||||||
|
animation: hero-orb-drift-b 27s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-orb-3 {
|
||||||
|
bottom: -22%;
|
||||||
|
inset-inline-start: 24%;
|
||||||
|
height: 26rem;
|
||||||
|
width: 26rem;
|
||||||
|
background: hsl(var(--brand-primary) / 0.1);
|
||||||
|
animation: hero-orb-drift-a 31s ease-in-out infinite reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-backdrop-noise {
|
||||||
|
position: absolute;
|
||||||
|
inset: -8%;
|
||||||
|
opacity: 0.26;
|
||||||
|
mix-blend-mode: soft-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .hero-backdrop-noise {
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-backdrop-floor {
|
||||||
|
position: absolute;
|
||||||
|
inset-inline: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 40%;
|
||||||
|
background: linear-gradient(to bottom, transparent, hsl(var(--background)) 92%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-backdrop.is-compact .hero-backdrop-grid {
|
||||||
|
opacity: 0.32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-backdrop.is-compact .hero-orb {
|
||||||
|
opacity: 0.7;
|
||||||
|
filter: blur(72px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes hero-orb-drift-a {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translate3d(0, 0, 0) scale(1);
|
||||||
|
}
|
||||||
|
33% {
|
||||||
|
transform: translate3d(70px, -48px, 0) scale(1.1);
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
transform: translate3d(-42px, 26px, 0) scale(0.94);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes hero-orb-drift-b {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translate3d(0, 0, 0) scale(1);
|
||||||
|
}
|
||||||
|
33% {
|
||||||
|
transform: translate3d(-80px, 42px, 0) scale(0.92);
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
transform: translate3d(38px, -24px, 0) scale(1.08);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.hero-orb {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.hero-title-line {
|
.hero-title-line {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-inline: 0.02em;
|
padding-inline: 0.02em;
|
||||||
|
|||||||
@@ -1,13 +1,33 @@
|
|||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
type HeroMotionBackdropProps = {
|
type HeroMotionBackdropProps = {
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function HeroMotionBackdrop({}: HeroMotionBackdropProps) {
|
/**
|
||||||
|
* Layered ambient backdrop rendered behind every hero (home + page).
|
||||||
|
* Pure CSS so it needs no client JS: a faded grid for structure, a soft
|
||||||
|
* brand glow, slowly drifting brand orbs, a grain overlay for texture, and
|
||||||
|
* a bottom fade that blends the hero into the page content. The orb drift is
|
||||||
|
* disabled under `prefers-reduced-motion` (see globals.css).
|
||||||
|
*/
|
||||||
|
export function HeroMotionBackdrop({ compact = false }: HeroMotionBackdropProps) {
|
||||||
return (
|
return (
|
||||||
<div className="hero-sheet pointer-events-none absolute inset-0 overflow-hidden">
|
<div
|
||||||
<div className="hero-sheet-base" />
|
aria-hidden="true"
|
||||||
<div className="hero-sheet-veil" />
|
className={cn(
|
||||||
<div className="hero-sheet-fade" />
|
"hero-backdrop pointer-events-none absolute inset-0 z-0 overflow-hidden",
|
||||||
|
compact && "is-compact",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="hero-backdrop-base" />
|
||||||
|
<div className="hero-backdrop-grid" />
|
||||||
|
<div className="hero-backdrop-glow" />
|
||||||
|
<span className="hero-orb hero-orb-1" />
|
||||||
|
<span className="hero-orb hero-orb-2" />
|
||||||
|
<span className="hero-orb hero-orb-3" />
|
||||||
|
<div className="hero-noise hero-backdrop-noise" />
|
||||||
|
<div className="hero-backdrop-floor" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user