94 lines
4.3 KiB
TypeScript
94 lines
4.3 KiB
TypeScript
"use client";
|
|
|
|
import { m, useReducedMotion } from "motion/react";
|
|
import { featuredDossier } from "@/lib/portfolio";
|
|
|
|
const fieldRows = [
|
|
{ label: "MISSION", value: featuredDossier.mission },
|
|
{ label: "CONSTRAINT", value: featuredDossier.constraint ?? "—" },
|
|
{ label: "SYSTEM", value: featuredDossier.system },
|
|
{ label: "RESULT", value: featuredDossier.result },
|
|
];
|
|
|
|
export function FeaturedDossier() {
|
|
const shouldReduceMotion = useReducedMotion();
|
|
|
|
return (
|
|
<m.section
|
|
aria-labelledby="featured-dossier-title"
|
|
initial={shouldReduceMotion ? false : { opacity: 0, y: 18 }}
|
|
whileInView={shouldReduceMotion ? undefined : { opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.5, ease: [0.22, 1, 0.36, 1] }}
|
|
viewport={{ once: true, amount: 0.18 }}
|
|
className="mx-auto max-w-7xl px-4 py-20 text-blacksite-text sm:px-6 lg:px-8"
|
|
>
|
|
<article className="overflow-hidden border border-blacksite-line bg-blacksite-surface shadow-[0_32px_120px_rgba(0,0,0,0.42)]">
|
|
<div className="flex items-center justify-between gap-4 border-b border-blacksite-line px-5 py-4 sm:px-7">
|
|
<p className="section-label">FEATURED DOSSIER /.00</p>
|
|
<span aria-hidden="true" className="size-2 rounded-full bg-signal-cyan shadow-[0_0_22px_rgba(0,240,255,0.62)]" />
|
|
</div>
|
|
|
|
<div className="relative overflow-hidden border-b border-blacksite-line px-5 pt-8 sm:px-7 lg:px-10">
|
|
<div aria-hidden="true" className="absolute inset-x-0 top-0 h-px bg-signal-cyan/50" />
|
|
<h2
|
|
id="featured-dossier-title"
|
|
className="font-display translate-y-4 text-[clamp(4.5rem,18vw,15rem)] font-semibold uppercase leading-[0.72] tracking-[-0.08em] text-blacksite-text"
|
|
>
|
|
{featuredDossier.title}
|
|
</h2>
|
|
</div>
|
|
|
|
<div className="grid gap-0 lg:grid-cols-[minmax(0,1fr)_22rem]">
|
|
<div className="divide-y divide-blacksite-line border-b border-blacksite-line lg:border-b-0 lg:border-r">
|
|
{fieldRows.map((row) => (
|
|
<div key={row.label} className="grid gap-3 px-5 py-6 sm:px-7 md:grid-cols-[9rem_minmax(0,1fr)] lg:px-10">
|
|
<p className="section-label text-signal-cyan">{row.label}</p>
|
|
<p className="text-sm leading-7 text-blacksite-muted sm:text-base">{row.value}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<aside className="bg-blacksite-surface2/45 px-5 py-6 sm:px-7 lg:px-8" aria-label="Featured dossier metadata and proof links">
|
|
<div className="border-b border-blacksite-line pb-6">
|
|
<p className="section-label mb-3">METADATA</p>
|
|
<p className="font-mono text-xs uppercase tracking-[0.14em] text-blacksite-text">
|
|
{featuredDossier.role} <span className="text-signal-cyan">·</span> {featuredDossier.year}
|
|
</p>
|
|
<div className="mt-5 flex flex-wrap gap-2">
|
|
{featuredDossier.stack.map((item) => (
|
|
<span
|
|
key={item}
|
|
className="border border-blacksite-line bg-blacksite-surface px-3 py-1 font-mono text-[11px] uppercase tracking-[0.14em] text-blacksite-muted"
|
|
>
|
|
{item}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-6">
|
|
<p className="section-label mb-3">PROOF LINKS</p>
|
|
<div className="grid gap-3">
|
|
{featuredDossier.links.map((link) => (
|
|
<a
|
|
key={link.href}
|
|
href={link.href}
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
className="group flex items-center justify-between gap-4 border border-blacksite-line px-4 py-3 font-mono text-xs uppercase tracking-[0.14em] text-blacksite-text transition-colors hover:border-signal-cyan/70 hover:text-signal-cyan focus-visible:outline-signal-cyan"
|
|
>
|
|
<span>{link.label}</span>
|
|
<span aria-hidden="true" className="text-signal-cyan transition-transform group-hover:translate-x-0.5">
|
|
↗
|
|
</span>
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
</div>
|
|
</article>
|
|
</m.section>
|
|
);
|
|
}
|