Converts every last bare-Swedish const array across landing sections
(STATS, TILES, CHAIN, PIPELINE, MODELS, DATASETS, PRINCIPLES, COLUMNS)
and shared components (data-artifact, provenance-badge) to {en,sv} Loc
objects consumed via useT(). Verified by per-file verify agent: 10/10
clean, zero remaining bare-Swedish display text. tsc 0 + build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
101 lines
5.4 KiB
TypeScript
101 lines
5.4 KiB
TypeScript
"use client";
|
|
|
|
import { useReveal } from "@/hooks/use-reveal";
|
|
import { useT } from "@/components/locale-provider";
|
|
|
|
const CHAIN = [
|
|
["01", { en: "Official APIs", sv: "Officiella API:er" }, { en: "GLEIF · Brreg · Companies House", sv: "GLEIF · Brreg · Companies House" }, "var(--prov-3)"],
|
|
["02", { en: "Authorized web", sv: "Auktoriserad webb" }, { en: "robots.txt. Rate limits.", sv: "robots.txt. Rate limits." }, "var(--prov-1)"],
|
|
["03", { en: "Licensed partner data", sv: "Licensierad partnerdata" }, { en: "Contracted access.", sv: "Avtalad åtkomst." }, "var(--prov-2)"],
|
|
["04", { en: "Otherwise: empty", sv: "Annars: tomt" }, { en: "We never guess.", sv: "Vi gissar aldrig." }, "transparent"],
|
|
] as const;
|
|
|
|
const PIPELINE = [
|
|
{ en: "Source racing", sv: "Källracing" },
|
|
{ en: "Extraction", sv: "Extraktion" },
|
|
{ en: "Structuring", sv: "Strukturering" },
|
|
{ en: "Enrichment", sv: "Berikning" },
|
|
{ en: "QA", sv: "QA" },
|
|
] as const;
|
|
|
|
export function TechnologySection() {
|
|
const ref = useReveal<HTMLElement>();
|
|
const t = useT();
|
|
return (
|
|
<section ref={ref} id="motorn" className="dark grain-overlay relative overflow-hidden border-b border-[#262626] bg-[#0a0a0a] text-[#fafafa]">
|
|
{/* graph-paper hairline texture */}
|
|
<div
|
|
aria-hidden
|
|
className="pointer-events-none absolute inset-0 opacity-[0.5]"
|
|
style={{
|
|
backgroundImage:
|
|
"linear-gradient(to right, #161616 1px, transparent 1px), linear-gradient(to bottom, #161616 1px, transparent 1px)",
|
|
backgroundSize: "64px 64px",
|
|
maskImage: "radial-gradient(120% 80% at 80% 0%, #000 0%, transparent 75%)",
|
|
WebkitMaskImage: "radial-gradient(120% 80% at 80% 0%, #000 0%, transparent 75%)",
|
|
}}
|
|
/>
|
|
{/* oversized faint section numeral */}
|
|
<span
|
|
aria-hidden
|
|
className="pointer-events-none absolute -right-2 top-2 select-none font-mono text-[clamp(7rem,22vw,16rem)] font-medium leading-none tracking-[-0.04em] text-[#141414]"
|
|
>
|
|
03
|
|
</span>
|
|
|
|
<div className="relative mx-auto max-w-[80rem] px-6 py-28 lg:py-40">
|
|
<div className="reveal flex items-center gap-3">
|
|
<span aria-hidden className="animate-float inline-block h-2 w-2" style={{ backgroundColor: "var(--accent-red)" }} />
|
|
<p className="font-mono text-[11px] uppercase tracking-[0.16em] text-[#a3a3a3]">{t({ en: "The engine", sv: "Motorn" })}</p>
|
|
</div>
|
|
<h2 className="reveal delay-1 mt-6 max-w-3xl text-[clamp(2.2rem,5vw,4rem)] font-medium leading-[0.98] tracking-[-0.03em]">
|
|
{t({ en: "Lawfully collected.", sv: "Lagligt insamlat." })}
|
|
<br />
|
|
{t({ en: "Traceable at every step.", sv: "Spårbart varje steg." })}
|
|
</h2>
|
|
|
|
{/* sourcing chain */}
|
|
<p className="reveal delay-2 mt-20 font-mono text-[11px] uppercase tracking-[0.16em] text-[#737373]">{t({ en: "The sourcing chain — by priority", sv: "Källkedjan — i prioritet" })}</p>
|
|
<div className="reveal-scale delay-2 mt-6 grid grid-cols-1 border-t border-[#262626] sm:grid-cols-2 lg:grid-cols-4">
|
|
{CHAIN.map(([n, title, sub, color], i) => (
|
|
<div
|
|
key={n}
|
|
className={`reveal delay-${i + 1} group relative border-b border-l border-[#262626] p-6 transition-[background-color] duration-300 hover:bg-[#121212] sm:[&:nth-child(2n)]:border-r lg:[&:nth-child(2n)]:border-r-0 lg:[&:last-child]:border-r`}
|
|
>
|
|
{/* hairline draw on hover */}
|
|
<span aria-hidden className="absolute left-0 top-0 h-px w-0 bg-[#525252] transition-[width] duration-300 ease-out group-hover:w-full" />
|
|
<div className="flex items-center justify-between">
|
|
<span className="font-mono text-[11px] tracking-[0.08em] text-[#737373]">{n}</span>
|
|
<span
|
|
className="inline-block h-2.5 w-2.5"
|
|
style={{
|
|
backgroundColor: color === "transparent" ? "transparent" : color,
|
|
border: color === "transparent" ? "1px solid #525252" : "none",
|
|
}}
|
|
/>
|
|
</div>
|
|
<p className="mt-16 text-[1.0625rem] font-medium leading-tight tracking-[-0.01em]">{t(title)}</p>
|
|
<p className="mt-2 font-mono text-[11px] leading-relaxed text-[#a3a3a3]">{t(sub)}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* pipeline */}
|
|
<p className="reveal delay-3 mt-24 font-mono text-[11px] uppercase tracking-[0.16em] text-[#737373]">{t({ en: "The pipeline", sv: "Pipelinen" })}</p>
|
|
<div className="reveal delay-3 mt-6 flex flex-wrap items-center gap-x-3 gap-y-4">
|
|
{PIPELINE.map((s, i) => (
|
|
<div key={i} className="flex items-center gap-3">
|
|
<span className="font-mono text-[11px] tracking-[0.06em] text-[#525252]">{String(i + 1).padStart(2, "0")}</span>
|
|
<span className="font-mono text-[13px] uppercase tracking-[0.06em] text-[#fafafa]">{t(s)}</span>
|
|
{i < PIPELINE.length - 1 ? <span aria-hidden className="text-[#404040]">/</span> : null}
|
|
</div>
|
|
))}
|
|
</div>
|
|
<p className="reveal delay-4 mt-8 max-w-md font-mono text-[11px] uppercase leading-relaxed tracking-[0.06em] text-[#737373]">
|
|
{t({ en: "QA runs inside the pipeline. Not on the side.", sv: "QA körs i pipelinen. Inte vid sidan om." })}
|
|
</p>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|