The rail and the "next, you are wondering" links are gone (owner: flat, and the question stood twice in a row). The page now reads from top to bottom: Every chapter opens with one sentence, and the sentences follow each other as the way of a project: you need someone who builds it, first we find out what you need, sometimes it is less work by hand, sometimes a meeting, then it always runs the same way, in the end something runs, a few questions remain, and it starts with an email. One line runs down the whole page and draws itself as the visitor scrolls. Under each sentence it crosses the page, stands a figure on the line (diamond, hexagon, screen, circle, square, triangle) and continues down the other side; a glowing dot travels at its head and comes to rest in front of the last sentence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
96 lines
3.2 KiB
TypeScript
96 lines
3.2 KiB
TypeScript
import * as React from "react";
|
|
import { BinaryTicker } from "@/src/components/bits/BinaryTicker";
|
|
import { BitSeam } from "@/src/components/bits/BitSeam";
|
|
import { BitWipe } from "@/src/components/bits/BitWipe";
|
|
import { DecodeText } from "@/src/components/bits/DecodeText";
|
|
import { Reveal } from "@/src/components/Reveal";
|
|
import { ChapterIntro } from "@/src/components/story/ChapterIntro";
|
|
import type { Figure } from "@/src/components/story/threadPath";
|
|
|
|
interface BlockProps {
|
|
/** Two-digit section index, shown with its binary form. */
|
|
index: string;
|
|
label: string;
|
|
title: React.ReactNode;
|
|
/** Makes the section a chapter of the story: its sentence and the figure the thread forms. */
|
|
chapter?: { line: string; figure: Figure; flip: boolean };
|
|
id?: string;
|
|
/** `dark` turns the section into a dark stage. */
|
|
tone?: "light" | "dark";
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
/**
|
|
* Block: one section of the homepage. A single left axis, one kicker line,
|
|
* one oversized headline, then the content. No sidebars.
|
|
*/
|
|
export const Block: React.FC<BlockProps> = ({
|
|
index,
|
|
label,
|
|
title,
|
|
chapter,
|
|
id,
|
|
tone = "light",
|
|
children,
|
|
}) => {
|
|
const dark = tone === "dark";
|
|
return (
|
|
<section
|
|
id={id}
|
|
className={`relative scroll-mt-24 border-t ${
|
|
dark
|
|
? "overflow-clip border-slate-800 bg-slate-900"
|
|
: "overflow-x-clip border-slate-200 bg-white"
|
|
}`}
|
|
>
|
|
{dark && (
|
|
<div
|
|
className="pointer-events-none absolute inset-0 opacity-70"
|
|
style={{
|
|
backgroundImage: "radial-gradient(#1e293b 1px, transparent 1px)",
|
|
backgroundSize: "20px 20px",
|
|
}}
|
|
aria-hidden="true"
|
|
/>
|
|
)}
|
|
{dark && <BitSeam />}
|
|
<div className="relative mx-auto w-full max-w-[1400px] px-5 py-14 md:px-12 md:py-36">
|
|
{chapter && (
|
|
<div className="-mt-14 md:-mt-36">
|
|
<ChapterIntro {...chapter} dark={dark} />
|
|
</div>
|
|
)}
|
|
<Reveal>
|
|
<div className="mb-8 flex items-center gap-4 md:mb-12">
|
|
<span
|
|
className={`font-mono text-[11px] font-bold tracking-[0.2em] ${dark ? "text-white" : "text-slate-900"}`}
|
|
>
|
|
{index}
|
|
</span>
|
|
<span
|
|
className={`h-px w-10 ${dark ? "bg-slate-700" : "bg-slate-300"}`}
|
|
/>
|
|
<DecodeText
|
|
text={label}
|
|
className={`font-mono text-[11px] uppercase tracking-[0.25em] ${dark ? "text-slate-400" : "text-slate-500"}`}
|
|
/>
|
|
<BinaryTicker
|
|
value={parseInt(index, 10)}
|
|
alive
|
|
className={`ml-auto hidden font-mono text-[10px] tracking-[0.3em] md:block ${dark ? "text-slate-600" : "text-slate-300"}`}
|
|
/>
|
|
</div>
|
|
</Reveal>
|
|
<BitWipe delay={0.1} tone={dark ? "light" : "dark"}>
|
|
<h2
|
|
className={`m-0 max-w-6xl text-4xl font-bold leading-[0.95] tracking-tighter md:text-7xl lg:text-[6.5rem] ${dark ? "text-white" : "text-slate-900"}`}
|
|
>
|
|
{title}
|
|
</h2>
|
|
</BitWipe>
|
|
<div className="mt-10 md:mt-24">{children}</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|