240 lines
13 KiB
Plaintext
240 lines
13 KiB
Plaintext
---
|
|
import Badge from '@/components/primitives/Badge.astro';
|
|
import Card from '@/components/primitives/Card.astro';
|
|
import Cluster from '@/components/primitives/Cluster.astro';
|
|
import Container from '@/components/primitives/Container.astro';
|
|
import Headline from '@/components/content/Headline.astro';
|
|
import HeroDashboard from '@/components/content/HeroDashboard.astro';
|
|
import Lead from '@/components/content/Lead.astro';
|
|
import Metric from '@/components/content/Metric.astro';
|
|
import PrimaryCTA from '@/components/content/PrimaryCTA.astro';
|
|
import SecondaryCTA from '@/components/content/SecondaryCTA.astro';
|
|
import type { HeroContent, MetricItem } from '@/types/site';
|
|
|
|
interface Props {
|
|
calloutDescription?: string;
|
|
calloutTitle?: string;
|
|
hero: HeroContent;
|
|
metrics?: MetricItem[];
|
|
}
|
|
|
|
const { calloutDescription, calloutTitle, hero, metrics = [] } = Astro.props;
|
|
const isHomepageHero = Astro.url.pathname === '/';
|
|
const heroHeadlineSize = isHomepageHero ? 'page' : 'display';
|
|
const heroLeadSize = isHomepageHero ? 'body' : 'lead';
|
|
const heroPrimaryAnchor = hero.primaryAnchor ?? 'headline';
|
|
---
|
|
|
|
<section
|
|
class:list={[
|
|
isHomepageHero ? 'hero-gradient pt-2 sm:pt-8 lg:pt-14' : 'pt-8 sm:pt-10 lg:pt-14',
|
|
]}
|
|
data-hero-root
|
|
data-hero-surface={isHomepageHero ? 'homepage' : 'page'}
|
|
data-homepage-hero={isHomepageHero ? 'true' : undefined}
|
|
data-hero-primary-anchor={isHomepageHero && heroPrimaryAnchor === 'composition' ? 'composition' : undefined}
|
|
data-section={isHomepageHero ? 'hero' : undefined}
|
|
>
|
|
<Container width="wide">
|
|
{isHomepageHero ? (
|
|
<div class="space-y-6 sm:space-y-8 lg:space-y-10" data-disclosure-layer="1" data-hero-layout>
|
|
<div class="grid gap-6 lg:grid-cols-[minmax(0,0.82fr)_minmax(22rem,1.18fr)] lg:items-start lg:gap-10">
|
|
<div class="motion-rise flex flex-col gap-5 sm:gap-6 lg:max-w-[40rem]" data-hero-panel="text">
|
|
<div class="space-y-5" data-hero-anchor-group>
|
|
<div data-hero-text-core>
|
|
<div data-hero-eyebrow data-hero-segment="eyebrow">
|
|
<Badge>{hero.eyebrow}</Badge>
|
|
</div>
|
|
<div class="mt-3 space-y-4 sm:mt-5 sm:space-y-5">
|
|
<div
|
|
data-hero-heading
|
|
data-hero-primary-anchor={heroPrimaryAnchor === 'headline' ? 'headline' : undefined}
|
|
data-hero-segment="headline"
|
|
>
|
|
<Headline
|
|
as="h1"
|
|
size="page"
|
|
class="max-w-[13ch] text-balance text-[length:clamp(2.7rem,4.6vw,4.8rem)] leading-[0.94] tracking-[-0.045em]"
|
|
>
|
|
{hero.titleHtml ? <Fragment set:html={hero.titleHtml} /> : hero.title}
|
|
</Headline>
|
|
</div>
|
|
<div
|
|
data-hero-copy-role="supporting"
|
|
data-hero-supporting-copy
|
|
data-hero-segment="supporting-copy"
|
|
>
|
|
<Lead class="max-w-[36rem] text-[1.02rem] leading-8 text-[var(--color-copy)] sm:text-[1.08rem]">
|
|
{hero.description}
|
|
</Lead>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{(hero.primaryCta || hero.secondaryCta) && (
|
|
<div data-hero-cta-pair data-hero-segment="cta-pair">
|
|
<Cluster data-cta-cluster gap="sm" class="items-center sm:gap-[var(--space-cluster)]">
|
|
<PrimaryCTA cta={hero.primaryCta} size="lg" />
|
|
{hero.secondaryCta && (
|
|
<SecondaryCTA cta={hero.secondaryCta} />
|
|
)}
|
|
</Cluster>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="motion-rise lg:pt-1"
|
|
style="animation-delay: 120ms;"
|
|
data-hero-panel="dashboard"
|
|
data-hero-primary-anchor={heroPrimaryAnchor === 'product-visual' ? 'product-visual' : undefined}
|
|
data-hero-visual
|
|
data-hero-visual-style="governance-surface"
|
|
data-hero-segment="product-near-visual"
|
|
>
|
|
<div class="overflow-hidden rounded-[2rem] border border-[color:var(--color-border)] bg-[linear-gradient(180deg,rgba(255,255,255,0.9),rgba(246,248,252,0.94))] p-3 shadow-[var(--shadow-panel-strong)] sm:p-4">
|
|
{hero.visualFocus && (
|
|
<div class="mb-3 rounded-[1.45rem] border border-[color:var(--color-border-subtle)] bg-white/88 px-4 py-4 sm:px-5">
|
|
<p class="m-0 text-[0.72rem] font-semibold uppercase tracking-[var(--tracking-eyebrow)] text-[var(--color-brand-500)]">
|
|
{hero.visualFocus.eyebrow}
|
|
</p>
|
|
<p class="mt-2 max-w-[42rem] text-sm font-semibold leading-6 text-[var(--color-ink-900)] sm:text-[0.98rem]">
|
|
{hero.visualFocus.title}
|
|
</p>
|
|
<ul class="mt-3 grid gap-2 p-0 sm:grid-cols-3">
|
|
{hero.visualFocus.points.map((point) => (
|
|
<li class="list-none rounded-[1rem] border border-[color:var(--color-border-subtle)] bg-[var(--surface-muted)] px-3 py-2 text-sm font-medium leading-5 text-[var(--color-ink-800)]">
|
|
{point}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
)}
|
|
<HeroDashboard />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{hero.trustSubclaims && hero.trustSubclaims.length > 0 && (
|
|
<div class="motion-rise space-y-2" data-hero-segment="trust-subclaims" data-hero-trust-signals>
|
|
<ul class="flex flex-wrap gap-3 p-0">
|
|
{hero.trustSubclaims.map((claim) => (
|
|
<li class="list-none rounded-full border border-[color:var(--color-border)] bg-white/80 px-4 py-1.5 text-sm font-medium text-[var(--color-ink-800)]">
|
|
{claim}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : (
|
|
<!-- Subpage hero: card-based 2-col layout -->
|
|
<div
|
|
class="grid gap-5 sm:gap-6 lg:grid-cols-[minmax(0,1.08fr)_minmax(20rem,0.92fr)] lg:items-start"
|
|
data-disclosure-layer="1"
|
|
data-hero-layout
|
|
>
|
|
<Card class="motion-rise overflow-hidden" data-hero-panel="text">
|
|
<div class="space-y-4 sm:space-y-6">
|
|
<div data-hero-text-core>
|
|
<div data-hero-eyebrow data-hero-segment="eyebrow">
|
|
<Badge>{hero.eyebrow}</Badge>
|
|
</div>
|
|
<div class="mt-3 space-y-4 sm:mt-4 sm:space-y-5">
|
|
<div data-hero-heading data-hero-segment="headline">
|
|
<Headline
|
|
as="h1"
|
|
size={heroHeadlineSize}
|
|
class="max-w-3xl text-balance"
|
|
>
|
|
{hero.titleHtml ? <Fragment set:html={hero.titleHtml} /> : hero.title}
|
|
</Headline>
|
|
</div>
|
|
<div data-hero-copy-role="supporting" data-hero-supporting-copy data-hero-segment="supporting-copy">
|
|
<Lead class="max-w-2xl" size={heroLeadSize}>
|
|
{hero.description}
|
|
</Lead>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{(hero.primaryCta || hero.secondaryCta) && (
|
|
<div data-hero-cta-pair data-hero-segment="cta-pair">
|
|
<Cluster data-cta-cluster gap="sm" class="sm:gap-[var(--space-cluster)]">
|
|
<PrimaryCTA cta={hero.primaryCta} />
|
|
{hero.secondaryCta && (
|
|
<SecondaryCTA cta={hero.secondaryCta} />
|
|
)}
|
|
</Cluster>
|
|
</div>
|
|
)}
|
|
{hero.highlights && hero.highlights.length > 0 && !hero.trustSubclaims?.length && (
|
|
<ul class="grid gap-3 p-0 sm:grid-cols-3">
|
|
{hero.highlights.map((highlight) => (
|
|
<li class="list-none rounded-[1.1rem] border border-[color:var(--color-line)] bg-white/70 px-4 py-3 text-sm font-medium text-[var(--color-ink-800)]">
|
|
{highlight}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
|
|
<div class="grid gap-4 sm:gap-5" data-hero-panel="supporting">
|
|
{hero.productVisual && (
|
|
<Card
|
|
variant="accent"
|
|
class="motion-rise overflow-hidden"
|
|
data-hero-segment="product-near-visual"
|
|
data-hero-visual
|
|
>
|
|
<img
|
|
src={hero.productVisual.src}
|
|
alt={hero.productVisual.alt}
|
|
class="max-h-[22rem] w-full rounded-[var(--radius-lg)] object-cover object-top"
|
|
loading="eager"
|
|
/>
|
|
</Card>
|
|
)}
|
|
|
|
{hero.trustSubclaims && hero.trustSubclaims.length > 0 && (
|
|
<Card variant="subtle" class="motion-rise" data-hero-segment="trust-subclaims">
|
|
<div class="space-y-3" data-hero-trust-signals>
|
|
<p class="m-0 text-[0.72rem] font-semibold uppercase tracking-[var(--tracking-eyebrow)] text-[var(--color-copy)]">
|
|
Early trust
|
|
</p>
|
|
<ul class="grid gap-2.5 p-0">
|
|
{hero.trustSubclaims.map((claim) => (
|
|
<li class="list-none rounded-[1rem] border border-[color:var(--color-line)] bg-white/82 px-4 py-3 text-sm font-medium text-[var(--color-ink-800)]">
|
|
{claim}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</Card>
|
|
)}
|
|
|
|
{!hero.productVisual && (calloutTitle || calloutDescription) && (
|
|
<Card variant="accent" class="motion-rise">
|
|
<p class="m-0 text-sm font-semibold uppercase tracking-[0.15em] text-[var(--color-brand)]">
|
|
Trust-first launch surface
|
|
</p>
|
|
{calloutTitle && (
|
|
<h2 class="mt-4 font-[var(--font-display)] text-3xl font-bold leading-tight text-[var(--color-ink-900)]">
|
|
{calloutTitle}
|
|
</h2>
|
|
)}
|
|
{calloutDescription && (
|
|
<p class="mt-3 text-base leading-7 text-[var(--color-copy)]">{calloutDescription}</p>
|
|
)}
|
|
</Card>
|
|
)}
|
|
|
|
{metrics.length > 0 && (
|
|
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-1">
|
|
{metrics.map((metric) => <Metric item={metric} />)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</Container>
|
|
</section>
|