Merge version_4_1779657195832 into main #3
@@ -1,94 +0,0 @@
|
||||
import ScrollReveal from "@/components/ui/ScrollReveal";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
|
||||
type BlogArticleProps = {
|
||||
category: string;
|
||||
title: string;
|
||||
excerpt?: string;
|
||||
content: string;
|
||||
imageSrc: string;
|
||||
authorName: string;
|
||||
authorImageSrc: string;
|
||||
date: string;
|
||||
readingTime?: string;
|
||||
backButton?: { text: string; href: string };
|
||||
};
|
||||
|
||||
const BlogArticle = ({
|
||||
category,
|
||||
title,
|
||||
excerpt,
|
||||
content,
|
||||
imageSrc,
|
||||
authorName,
|
||||
authorImageSrc,
|
||||
date,
|
||||
readingTime,
|
||||
backButton = { text: "Back to Blog", href: "/blog" },
|
||||
}: BlogArticleProps) => {
|
||||
return (
|
||||
<article aria-label="Blog article" className="py-20">
|
||||
<div className="flex flex-col gap-10">
|
||||
<ScrollReveal variant="fade-blur">
|
||||
<div className="flex flex-col gap-6 w-content-width md:max-w-4xl mx-auto">
|
||||
<div className="flex items-center gap-2 px-3 py-1 text-sm text-foreground/75 card rounded w-fit">
|
||||
<a
|
||||
href={backButton.href}
|
||||
className="hover:text-foreground transition-colors"
|
||||
>
|
||||
{backButton.text}
|
||||
</a>
|
||||
<span>/</span>
|
||||
<span className="text-foreground">{category}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
|
||||
<h1 className="text-5xl md:text-6xl font-medium leading-tight text-balance">
|
||||
{title}
|
||||
</h1>
|
||||
|
||||
{excerpt && (
|
||||
<p className="text-lg md:text-xl leading-tight text-balance">
|
||||
{excerpt}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-3 mt-3">
|
||||
<ImageOrVideo
|
||||
imageSrc={authorImageSrc}
|
||||
className="size-9 rounded-full object-cover"
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-medium">{authorName}</span>
|
||||
<span className="text-xs text-foreground/75">
|
||||
{date}
|
||||
{readingTime && ` · ${readingTime}`}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal variant="fade-blur">
|
||||
<div className="w-content-width md:max-w-4xl mx-auto aspect-video card rounded overflow-hidden p-3 xl:p-4 2xl:p-5">
|
||||
<ImageOrVideo
|
||||
imageSrc={imageSrc}
|
||||
className="size-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
|
||||
<ScrollReveal variant="fade-blur">
|
||||
<div
|
||||
className="w-content-width md:max-w-4xl mx-auto flex flex-col gap-6 [&>h1]:text-4xl [&>h1]:font-semibold [&>h1]:mt-4 [&>h2]:text-3xl [&>h2]:font-semibold [&>h2]:mt-4 [&>h3]:text-2xl [&>h3]:font-semibold [&>h3]:mt-2 [&>h4]:text-xl [&>h4]:font-semibold [&>h4]:mt-2 [&>p]:text-base [&>p]:leading-relaxed [&>p]:text-foreground/85 [&_strong]:font-semibold [&_em]:italic [&_u]:underline [&>ul]:flex [&>ul]:flex-col [&>ul]:gap-2 [&>ul]:list-disc [&>ul]:pl-6 [&>ul]:text-base [&>ul]:leading-relaxed [&>ul]:text-foreground/85 [&>ol]:flex [&>ol]:flex-col [&>ol]:gap-2 [&>ol]:list-decimal [&>ol]:pl-6 [&>ol]:text-base [&>ol]:leading-relaxed [&>ol]:text-foreground/85"
|
||||
dangerouslySetInnerHTML={{ __html: content }}
|
||||
/>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogArticle;
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import { useButtonClick } from "@/hooks/useButtonClick";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
|
||||
type FooterLink = {
|
||||
label: string;
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
type FooterColumn = {
|
||||
title: string;
|
||||
items: FooterLink[];
|
||||
};
|
||||
|
||||
const FooterLinkItem = ({ label, href, onClick }: FooterLink) => {
|
||||
const handleClick = useButtonClick(href, onClick);
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="text-base text-primary-cta-text hover:opacity-75 transition-opacity cursor-pointer"
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
const FooterBottomLink = ({ label, href, onClick }: FooterLink) => {
|
||||
const handleClick = useButtonClick(href, onClick);
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="text-sm opacity-50 hover:opacity-75 transition-opacity cursor-pointer"
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
const FooterSimpleMedia = ({
|
||||
imageSrc,
|
||||
videoSrc,
|
||||
brand,
|
||||
columns,
|
||||
copyright,
|
||||
links,
|
||||
}: ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never }) & {
|
||||
brand: string;
|
||||
columns: FooterColumn[];
|
||||
copyright: string;
|
||||
links: FooterLink[];
|
||||
}) => {
|
||||
return (
|
||||
<footer aria-label="Site footer" className="relative w-full mt-20 overflow-hidden">
|
||||
<div className="w-full aspect-square md:aspect-16/6 mask-fade-top-long">
|
||||
<ImageOrVideo
|
||||
imageSrc={imageSrc}
|
||||
videoSrc={videoSrc}
|
||||
className="w-full h-full object-cover rounded-none!"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="w-full py-15 primary-button text-primary-cta-text">
|
||||
<div className="w-content-width mx-auto">
|
||||
<div className="flex flex-col md:flex-row gap-10 md:gap-0 justify-between items-start mb-10">
|
||||
<h2 className="text-4xl font-medium">{brand}</h2>
|
||||
|
||||
<div className="w-full md:w-fit flex flex-wrap gap-y-10 md:gap-12">
|
||||
{columns.map((column) => (
|
||||
<div key={column.title} className="w-1/2 md:w-auto flex flex-col items-start gap-3">
|
||||
<h3 className="text-sm opacity-50">{column.title}</h3>
|
||||
{column.items.map((item) => (
|
||||
<FooterLinkItem key={item.label} label={item.label} href={item.href} onClick={item.onClick} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between pt-8 border-t border-primary-cta-text/20">
|
||||
<span className="text-sm opacity-50">{copyright}</span>
|
||||
<div className="flex items-center gap-3">
|
||||
{links.map((link) => (
|
||||
<FooterBottomLink key={link.label} label={link.label} href={link.href} onClick={link.onClick} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
export default FooterSimpleMedia;
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import Button from "@/components/ui/Button";
|
||||
import HeroBackgroundSlot from "@/components/ui/HeroBackgroundSlot";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
|
||||
type HeroBillboardCarouselProps = {
|
||||
tag: string;
|
||||
title: string;
|
||||
description: string;
|
||||
primaryButton: { text: string; href: string };
|
||||
secondaryButton: { text: string; href: string };
|
||||
items: ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never })[];
|
||||
};
|
||||
|
||||
const HeroBillboardCarousel = ({
|
||||
tag,
|
||||
title,
|
||||
description,
|
||||
primaryButton,
|
||||
secondaryButton,
|
||||
items,
|
||||
}: HeroBillboardCarouselProps) => {
|
||||
const duplicated = [...items, ...items, ...items, ...items];
|
||||
|
||||
return (
|
||||
<section
|
||||
aria-label="Hero section"
|
||||
className="relative flex flex-col items-center justify-center gap-8 w-full min-h-svh py-25"
|
||||
>
|
||||
<HeroBackgroundSlot />
|
||||
<div className="flex flex-col items-center gap-2 w-content-width mx-auto text-center">
|
||||
<div className="px-3 py-1 mb-1 text-sm card rounded w-fit">
|
||||
<p>{tag}</p>
|
||||
</div>
|
||||
|
||||
<TextAnimation
|
||||
text={title}
|
||||
variant="fade-blur"
|
||||
gradientText={true}
|
||||
tag="h1"
|
||||
className="text-6xl font-medium text-balance"
|
||||
/>
|
||||
|
||||
<TextAnimation
|
||||
text={description}
|
||||
variant="fade-blur"
|
||||
gradientText={false}
|
||||
tag="p"
|
||||
className="text-base md:text-lg leading-tight text-balance"
|
||||
/>
|
||||
|
||||
<div className="flex flex-wrap justify-center gap-3 mt-3">
|
||||
<Button text={primaryButton.text} href={primaryButton.href} variant="primary"/>
|
||||
<Button text={secondaryButton.text} href={secondaryButton.href} variant="secondary"animationDelay={0.1} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-content-width mx-auto overflow-hidden mask-fade-x">
|
||||
<div className="flex w-max animate-marquee-horizontal" style={{ animationDuration: "60s" }}>
|
||||
{duplicated.map((item, i) => (
|
||||
<div key={i} className="shrink-0 w-60 md:w-75 2xl:w-80 aspect-4/5 mr-3 md:mr-5 p-1.5 card rounded-lg overflow-hidden">
|
||||
<ImageOrVideo
|
||||
imageSrc={item.imageSrc}
|
||||
videoSrc={item.videoSrc}
|
||||
className="w-full h-full rounded-lg object-cover"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroBillboardCarousel;
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import Button from "@/components/ui/Button";
|
||||
import HeroBackgroundSlot from "@/components/ui/HeroBackgroundSlot";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import AutoFillText from "@/components/ui/AutoFillText";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
type HeroBrandCarouselProps = {
|
||||
brand: string;
|
||||
description: string;
|
||||
primaryButton: { text: string; href: string };
|
||||
secondaryButton: { text: string; href: string };
|
||||
items: ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never })[];
|
||||
};
|
||||
|
||||
const INTERVAL = 4000;
|
||||
|
||||
const HeroBrandCarousel = ({
|
||||
brand,
|
||||
description,
|
||||
primaryButton,
|
||||
secondaryButton,
|
||||
items,
|
||||
}: HeroBrandCarouselProps) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setCurrentIndex((prev) => (prev + 1) % items.length);
|
||||
}, INTERVAL);
|
||||
return () => clearInterval(interval);
|
||||
}, [currentIndex, items.length]);
|
||||
|
||||
return (
|
||||
<section
|
||||
aria-label="Hero section"
|
||||
className="relative w-full h-svh overflow-hidden flex flex-col justify-end mb-20"
|
||||
>
|
||||
<HeroBackgroundSlot />
|
||||
{items.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={cls(
|
||||
"absolute inset-0 transition-opacity duration-500",
|
||||
currentIndex === index ? "opacity-100 z-1" : "opacity-0 pointer-events-none"
|
||||
)}
|
||||
aria-hidden={currentIndex !== index}
|
||||
>
|
||||
<ImageOrVideo
|
||||
imageSrc={item.imageSrc}
|
||||
videoSrc={item.videoSrc}
|
||||
className="absolute inset-0 w-full h-full object-cover rounded-none"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div
|
||||
className="absolute z-10 w-full h-[50svh] md:h-[75svh] left-0 bottom-0 backdrop-blur-xl mask-[linear-gradient(to_bottom,transparent,black_60%)]"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
|
||||
<div className="relative z-10 w-content-width mx-auto pb-5">
|
||||
<div className="flex flex-col">
|
||||
<div className="w-full flex flex-col md:flex-row md:justify-between items-start md:items-end gap-3 md:gap-5">
|
||||
<TextAnimation
|
||||
text={description}
|
||||
variant="fade"
|
||||
gradientText={false}
|
||||
tag="p"
|
||||
className="w-full md:w-1/2 text-lg md:text-2xl text-balance font-normal text-primary-cta-text leading-tight"
|
||||
/>
|
||||
|
||||
<div className="w-full md:w-1/2 flex justify-start md:justify-end">
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<Button text={primaryButton.text} href={primaryButton.href} variant="primary"/>
|
||||
<Button text={secondaryButton.text} href={secondaryButton.href} variant="secondary"animationDelay={0.1} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AutoFillText className="font-semibold text-primary-cta-text">{brand}</AutoFillText>
|
||||
|
||||
<div className="flex gap-3 pb-5">
|
||||
{items.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className="relative h-1 w-full rounded overflow-hidden bg-primary-cta-text/20 cursor-pointer"
|
||||
onClick={() => setCurrentIndex(index)}
|
||||
aria-label="Slide"
|
||||
aria-current={currentIndex === index}
|
||||
>
|
||||
<div
|
||||
className={cls(
|
||||
"absolute inset-0 bg-primary-cta-text rounded origin-left",
|
||||
currentIndex === index ? "animate-progress" : (index < currentIndex ? "scale-x-100" : "scale-x-0")
|
||||
)}
|
||||
style={{ animationDuration: `${INTERVAL}ms` }}
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroBrandCarousel;
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import ScrollReveal from "@/components/ui/ScrollReveal";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
type ResultItem = {
|
||||
treatment: string;
|
||||
detail: string;
|
||||
beforeSrc: string;
|
||||
afterSrc: string;
|
||||
};
|
||||
|
||||
interface ResultsComparisonProps {
|
||||
tag: string;
|
||||
title: string;
|
||||
description: string;
|
||||
primaryButton?: { text: string; href: string };
|
||||
secondaryButton?: { text: string; href: string };
|
||||
items: ResultItem[];
|
||||
}
|
||||
|
||||
const ImageLabel = ({ text, side }: { text: string; side: "left" | "right" }) => (
|
||||
<div
|
||||
className={cls(
|
||||
"absolute bottom-2 xl:bottom-3 2xl:bottom-4 px-3 py-1 w-fit text-sm card rounded",
|
||||
side === "left" ? "left-2 xl:left-3 2xl:left-4" : "right-2 xl:right-3 2xl:right-4"
|
||||
)}
|
||||
>
|
||||
<p className="font-medium text-foreground">{text}</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
const ResultsComparison = ({
|
||||
tag,
|
||||
title,
|
||||
description,
|
||||
primaryButton,
|
||||
secondaryButton,
|
||||
items,
|
||||
}: ResultsComparisonProps) => {
|
||||
const duplicated = [...items, ...items, ...items, ...items];
|
||||
|
||||
return (
|
||||
<section aria-label="Results section" className="py-20">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col items-center w-content-width mx-auto gap-2">
|
||||
<div className="px-3 py-1 mb-1 text-sm card rounded w-fit">
|
||||
<p>{tag}</p>
|
||||
</div>
|
||||
|
||||
<TextAnimation
|
||||
text={title}
|
||||
variant="slide-up"
|
||||
gradientText={true}
|
||||
tag="h2"
|
||||
className="text-6xl font-medium text-center text-balance"
|
||||
/>
|
||||
|
||||
<TextAnimation
|
||||
text={description}
|
||||
variant="slide-up"
|
||||
gradientText={false}
|
||||
tag="p"
|
||||
className="md:max-w-6/10 text-lg leading-tight text-center"
|
||||
/>
|
||||
|
||||
{(primaryButton || secondaryButton) && (
|
||||
<div className="flex flex-wrap justify-center gap-3 mt-3">
|
||||
{primaryButton && <Button text={primaryButton.text} href={primaryButton.href} variant="primary"/>}
|
||||
{secondaryButton && <Button text={secondaryButton.text} href={secondaryButton.href} variant="secondary" animationDelay={0.1} />}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ScrollReveal variant="slide-up">
|
||||
<div className="w-content-width mx-auto overflow-hidden mask-fade-x">
|
||||
<div className="flex w-max animate-marquee-horizontal" style={{ animationDuration: "60s" }}>
|
||||
{duplicated.map((item, i) => (
|
||||
<div key={i} className="shrink-0 w-80 md:w-120 2xl:w-140 mr-3 md:mr-5 p-3 xl:p-4 2xl:p-5 card rounded">
|
||||
<div className="relative flex w-full aspect-3/2 mb-3 xl:mb-4 2xl:mb-5">
|
||||
<div className="relative overflow-hidden w-1/2 rounded-l-lg rounded-r-none">
|
||||
<ImageOrVideo imageSrc={item.beforeSrc} className="absolute inset-0 object-cover w-full h-full rounded-l rounded-r-none" />
|
||||
<ImageLabel text="Before" side="left" />
|
||||
</div>
|
||||
<div className="absolute z-10 left-1/2 top-0 bottom-0 w-0.5 bg-background -translate-x-1/2" />
|
||||
<div className="relative overflow-hidden w-1/2 rounded-r-lg rounded-l-none">
|
||||
<ImageOrVideo imageSrc={item.afterSrc} className="absolute inset-0 object-cover w-full h-full rounded-r rounded-l-none" />
|
||||
<ImageLabel text="After" side="right" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<h4 className="truncate text-2xl font-medium leading-tight text-foreground">
|
||||
{item.treatment}
|
||||
</h4>
|
||||
<p className="text-base leading-tight text-foreground/75">
|
||||
{item.detail}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResultsComparison;
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
type LightRaysCornerBackgroundProps = {
|
||||
position: "fixed" | "absolute";
|
||||
};
|
||||
|
||||
const LightRaysCornerBackground = ({ position }: LightRaysCornerBackgroundProps) => {
|
||||
return (
|
||||
<div className={cls(position, "inset-0 -z-10 overflow-hidden pointer-events-none select-none")} aria-hidden="true">
|
||||
<div className="absolute inset-0 bg-background mask-[radial-gradient(50%_50%_at_50%_0%,white_0%,transparent_100%)] bg-[linear-gradient(to_right,color-mix(in_srgb,var(--color-background-accent)_20%,transparent)_1px,transparent_1px),linear-gradient(to_bottom,color-mix(in_srgb,var(--color-background-accent)_10%,transparent)_1px,transparent_1px)] bg-size-[10vw_10vw]" />
|
||||
|
||||
<div className="absolute -top-[571px] -left-[373px] w-[1142px] h-[179vh] -rotate-[38deg] overflow-hidden blur-lg mask-[radial-gradient(50%_109%,#000_0%,#000000f6_0%,transparent_96%)]">
|
||||
<div
|
||||
className="absolute -top-[352px] -bottom-[920px] left-[calc(50%-17.5px)] w-[35px] origin-top-right overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]"
|
||||
style={{ "--ray-opacity": 0.85, transform: "rotate(-18deg)", animation: "rotated-ray-pulse 4s ease-in-out 0s infinite both" } as React.CSSProperties}
|
||||
/>
|
||||
<div
|
||||
className="absolute -top-[352px] -bottom-[920px] left-[calc(50%-17.5px)] w-[35px] origin-top-right overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]"
|
||||
style={{ "--ray-opacity": 0.775, transform: "rotate(-12deg)", animation: "rotated-ray-pulse 3.5s ease-in-out 0.5s infinite both" } as React.CSSProperties}
|
||||
/>
|
||||
<div
|
||||
className="absolute -top-[352px] -bottom-[920px] left-[calc(50%-10px)] w-[20px] origin-top-right overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]"
|
||||
style={{ "--ray-opacity": 0.65, transform: "scale(0.9) rotate(-5deg)", animation: "rotated-ray-pulse 5s ease-in-out 1.2s infinite both" } as React.CSSProperties}
|
||||
/>
|
||||
<div
|
||||
className="absolute -top-[352px] -bottom-[920px] left-[calc(50%-7.5px)] w-[15px] origin-top-right overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]"
|
||||
style={{ "--ray-opacity": 0.25, transform: "rotate(-3deg)", animation: "rotated-ray-pulse 3s ease-in-out 0.3s infinite both" } as React.CSSProperties}
|
||||
/>
|
||||
<div
|
||||
className="absolute -top-[352px] -bottom-[920px] left-[calc(50%-20px)] w-[40px] origin-top-right overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]"
|
||||
style={{ "--ray-opacity": 0.45, transform: "scale(0.79) rotate(0deg)", animation: "rotated-ray-pulse 4.5s ease-in-out 0.8s infinite both" } as React.CSSProperties}
|
||||
/>
|
||||
<div
|
||||
className="absolute -top-[352px] -bottom-[920px] left-[calc(50%-10px)] w-[20px] origin-top-right overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]"
|
||||
style={{ "--ray-opacity": 0.45, transform: "rotate(6deg)", animation: "rotated-ray-pulse 3.2s ease-in-out 1.5s infinite both" } as React.CSSProperties}
|
||||
/>
|
||||
<div
|
||||
className="absolute -top-[352px] -bottom-[920px] left-[calc(50%-17.5px)] w-[35px] origin-top-right overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]"
|
||||
style={{ "--ray-opacity": 0.65, transform: "scale(0.83) rotate(9deg)", animation: "rotated-ray-pulse 4.2s ease-in-out 0.2s infinite both" } as React.CSSProperties}
|
||||
/>
|
||||
<div
|
||||
className="absolute -top-[352px] -bottom-[920px] left-[calc(50%-17.5px)] w-[35px] origin-top-right overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]"
|
||||
style={{ "--ray-opacity": 1, transform: "scale(0.9) rotate(14deg)", animation: "rotated-ray-pulse 3.8s ease-in-out 1s infinite both" } as React.CSSProperties}
|
||||
/>
|
||||
|
||||
<div className="absolute left-[calc(50%-599px)] -top-[352px] -bottom-[46px] w-[1198px] opacity-[0.05] overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]" />
|
||||
<div className="absolute left-[calc(50%-432.5px)] -top-[252px] w-[865px] h-[929px] opacity-15 overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]" />
|
||||
<div className="absolute left-[calc(50%-432.5px)] -top-[252px] w-[865px] h-[929px] opacity-15 overflow-hidden bg-[radial-gradient(50%_50%_at_50%_50%,var(--color-background-accent)_0%,transparent_100%)]" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LightRaysCornerBackground;
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function HomePage() {
|
||||
description="Unlock bespoke itineraries, exclusive destinations, and personalized service designed for the discerning traveler. Your extraordinary adventure begins here."
|
||||
primaryButton={{
|
||||
text: "Plan Your Escape",
|
||||
href: "#contact",
|
||||
href: "https://www.dialedweb.com/",
|
||||
}}
|
||||
secondaryButton={{
|
||||
text: "Explore Destinations",
|
||||
@@ -43,7 +43,7 @@ export default function HomePage() {
|
||||
title="Crafting Your Perfect Journey"
|
||||
primaryButton={{
|
||||
text: "Learn More",
|
||||
href: "#",
|
||||
href: "https://www.dialedweb.com/",
|
||||
}}
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
|
||||
Reference in New Issue
Block a user