Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions app/(home)/BoundarySigil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import s from './home.module.css';

/*
* The Boundary Sigil — a summoning circle that is literally the architecture
* diagram. Each ring is a real runtime layer (outermost = closest to the user),
* read from the same stack the StackDiagram lists: surfaces, cast codes, the
* local API, the daemon, the ledger + harnesses, and the familiar at center.
* The dashed outer circle is the coven boundary itself.
*
* Decorative duplicate of information presented in the Runtime Stack section,
* so it is aria-hidden. All motion is disabled under prefers-reduced-motion.
*/

const CX = 280;
const CY = 280;

// Content rings, outermost first. `offset` scatters labels around the top arc.
const RINGS = [
{ r: 208, label: 'surfaces', offset: '3%', delay: 0.15 },
{ r: 174, label: 'cast codes', offset: '86%', delay: 0.3 },
{ r: 140, label: 'local api', offset: '8%', delay: 0.45 },
{ r: 106, label: 'daemon', offset: '78%', delay: 0.6 },
{ r: 72, label: 'ledger · harnesses', offset: '2%', delay: 0.75 },
];

// Session nodes resting on their orbits — [ring radius, angle in degrees].
const NODES: Array<[number, number]> = [
[208, 130],
[174, 305],
[140, 75],
[106, 210],
];

function polar(r: number, deg: number): [number, number] {
const rad = (deg * Math.PI) / 180;
return [CX + r * Math.cos(rad), CY + r * Math.sin(rad)];
}

export function BoundarySigil() {
return (
<svg
className={s.sigil}
viewBox="0 0 560 560"
role="presentation"
aria-hidden="true"
>
<defs>
{RINGS.map(({ r }) => (
<path
key={r}
id={`sigil-tp-${r}`}
d={`M ${CX} ${CY - r} a ${r} ${r} 0 1 1 -0.01 0`}
fill="none"
/>
))}
</defs>

{/* The boundary: dashed outer circle + cardinal ticks, rotating slowly */}
<g className={s.sigilBoundary}>
<circle cx={CX} cy={CY} r={240} className={s.sigilDashed} />
<line x1={CX} y1={32} x2={CX} y2={48} className={s.sigilTick} />
<line x1={CX} y1={512} x2={CX} y2={528} className={s.sigilTick} />
<line x1={32} y1={CY} x2={48} y2={CY} className={s.sigilTick} />
<line x1={512} y1={CY} x2={528} y2={CY} className={s.sigilTick} />
</g>

{/* Layer rings, drawn in from the outside toward the familiar */}
{RINGS.map(({ r, delay }) => (
<circle
key={r}
cx={CX}
cy={CY}
r={r}
pathLength={1}
className={s.sigilRing}
style={{ animationDelay: `${delay}s` }}
/>
))}

{/* Ring labels — mono, knocked out of the ring line beneath them */}
{RINGS.map(({ r, label, offset }) => (
<text key={label} className={s.sigilLabel}>
<textPath href={`#sigil-tp-${r}`} startOffset={offset}>
{label}
</textPath>
</text>
))}

{/* Sessions resting on their orbits */}
{NODES.map(([r, deg]) => {
const [x, y] = polar(r, deg);
return <circle key={`${r}-${deg}`} cx={x} cy={y} r={3.2} className={s.sigilNode} />;
})}

{/* The familiar: the one ember-gold mark on the page */}
<circle cx={CX} cy={CY} r={26} className={s.sigilPulse} />
<circle cx={CX} cy={CY} r={4.5} className={s.sigilCore} />
<text x={CX} y={CY + 24} className={s.sigilCenterLabel} textAnchor="middle">
familiar
</text>
</svg>
);
}
63 changes: 8 additions & 55 deletions app/(home)/HomeInteractive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ import s from './home.module.css';
const VIOLET = 'var(--home-violet)';
const VIOLET_TEXT = 'var(--home-violet-text)';
const VIOLET_DIM = 'var(--home-violet-soft)';
const BORDER = '1px solid var(--home-border)';

// ─── Types ────────────────────────────────────────────────────────────────────

type Feature = {
icon: string;
icon?: string;
title: string;
desc: string;
href: string;
Expand Down Expand Up @@ -139,15 +138,8 @@ export function HeroTerminal() {
<span style={{ marginLeft: '0.5rem', color: 'rgba(255,255,255,0.35)', fontSize: '0.72rem' }}>
coven — zsh
</span>
<span style={{
marginLeft: 'auto',
fontSize: '0.65rem',
fontWeight: 600,
color: VIOLET_TEXT,
letterSpacing: '0.06em',
textTransform: 'uppercase',
}}>
● live
<span className={s.termLive}>
● rec
</span>
</div>

Expand Down Expand Up @@ -184,57 +176,18 @@ export function HeroTerminal() {
// ─── Feature Grid ─────────────────────────────────────────────────────────────

export function FeatureGrid({ features }: { features: Feature[] }) {
const [active, setActive] = useState<string | null>(null);

return (
<div className={s.fg}>
{features.map((f) => (
<Link
key={f.title}
href={f.href}
className={s.fc}
onMouseEnter={() => setActive(f.title)}
onMouseLeave={() => setActive(null)}
style={{
padding: '1.75rem',
background: active === f.title ? 'var(--home-surface-elev)' : 'var(--home-surface)',
}}
>
{/* Icon badge */}
<div
className={s.fcIconWrap}
style={{
width: '42px',
height: '42px',
borderRadius: '11px',
background: active === f.title ? 'var(--home-violet-soft)' : VIOLET_DIM,
border: `1px solid var(--home-border${active === f.title ? '-strong' : ''})`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: '1.1rem',
}}
>
<Icon icon={f.icon} width={20} color={VIOLET} />
</div>

{/* Title row */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '0.45rem' }}>
<span style={{ fontWeight: 700, fontSize: '0.95rem', color: 'var(--home-fg)', letterSpacing: 0 }}>
{f.title}
</span>
<Link key={f.title} href={f.href} className={s.fc}>
{f.tag && <span className={s.fcEyebrow}>{f.tag}</span>}
<div className={s.fcTitleRow}>
<span className={s.fcTitle}>{f.title}</span>
<span className={s.fcArrow}>
<Icon icon="ph:arrow-right" width={14} color={VIOLET} />
</span>
</div>

{/* Description */}
<p style={{ fontSize: '0.84rem', color: 'var(--home-fg-muted)', lineHeight: 1.65, margin: 0 }}>
{f.desc}
</p>

{/* Tag */}
{f.tag && <span className={s.fcTag}>{f.tag}</span>}
<p className={s.fcDesc}>{f.desc}</p>
</Link>
))}
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/(home)/archives/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const archiveLinks = [
export default function ArchivesPage() {
return (
<main className={s.homeMain}>
<section className={s.heroPanel}>
<section className={`${s.heroPanel} ${s.heroPanelSolo}`}>
<div className={s.heroGridBg} />
<p className={s.heroEyebrow}>Coven Records</p>
<h1 className={s.heroTitle}>Archives</h1>
Expand All @@ -42,7 +42,7 @@ export default function ArchivesPage() {
</p>
</section>

<section className={s.introSection}>
<section className={`${s.introSection} ${s.introSectionSolo}`}>
<div style={{ display: 'grid', gap: '0.9rem', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))' }}>
{archiveLinks.map((item) => (
<Link
Expand Down
4 changes: 2 additions & 2 deletions app/(home)/covenant/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const covenantPoints = [
export default function CovenantPage() {
return (
<main className={s.homeMain}>
<section className={s.heroPanel}>
<section className={`${s.heroPanel} ${s.heroPanelSolo}`}>
<div className={s.heroGridBg} />
<p className={s.heroEyebrow}>Working Promises</p>
<h1 className={s.heroTitle}>Covenant</h1>
Expand All @@ -48,7 +48,7 @@ export default function CovenantPage() {
</div>
</section>

<section className={s.introSection}>
<section className={`${s.introSection} ${s.introSectionSolo}`}>
<div style={{ display: 'grid', gap: '0.9rem', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))' }}>
{covenantPoints.map((item) => (
<div
Expand Down
Loading