import { motion, useReducedMotion } from 'framer-motion'; import { useTheme } from 'next-themes'; import { useTranslation } from 'react-i18next'; import agenticDarkUrl from '../assets/pillars/agentic-dark.svg'; import agenticLightUrl from '../assets/pillars/agentic-light.svg'; import agnosticDarkUrl from '../assets/pillars/agnostic-dark.svg'; import agnosticLightUrl from '../assets/pillars/agnostic-light.svg'; import groundedDarkUrl from '../assets/pillars/grounded-dark.svg'; import groundedLightUrl from '../assets/pillars/grounded-light.svg'; import sovereignDarkUrl from '../assets/pillars/sovereign-dark.svg'; import sovereignLightUrl from '../assets/pillars/sovereign-light.svg'; /** * The four pillars, as a ledger rather than a card grid. * * Registry order is load-bearing (Sovereign, Agnostic, Grounded, Agentic) and * pinned by tests/unit/docs/terminology-census.test.ts. Each row carries the * pillar name, its locked definition, the canonical belief line from * the 4s-claims-architecture spec, and the * pillar's mark from assets/pillars/ (light/dark pairs, per the Logo.tsx * asset convention — decorative, so aria-hidden; the name beside it is the * accessible label). * * Deliberately NOT a four-up card grid: the marks run down the center of the section * as a spine — name and definition to the left, belief to the right — with * hairline segments connecting mark to mark. The spine replaces the earlier * ledger's horizontal rules as the structural device: same commitments- * listed-plainly content, threaded on one axis instead of ruled into rows. * The spine is built from per-row stretch segments (not one absolute line) * because --background is transparent, so a continuous line can't be masked * behind the marks' open interiors. * * No numbering. The pillars are four independent guarantees, not a sequence, * and numbering them would assert an order the content does not have. */ const PILLAR_KEYS = ['sovereign', 'agnostic', 'grounded', 'agentic'] as const; const PILLAR_MARKS: Record<(typeof PILLAR_KEYS)[number], { light: string; dark: string }> = { sovereign: { light: sovereignLightUrl, dark: sovereignDarkUrl }, agnostic: { light: agnosticLightUrl, dark: agnosticDarkUrl }, grounded: { light: groundedLightUrl, dark: groundedDarkUrl }, agentic: { light: agenticLightUrl, dark: agenticDarkUrl }, }; // The marks alternate the two brand accents down the spine (teal, magenta, // teal, magenta); each tagline takes its own mark's accent so the pair reads // as one unit. const PILLAR_ACCENT: Record<(typeof PILLAR_KEYS)[number], string> = { sovereign: 'text-primary', agnostic: 'text-secondary-accent', grounded: 'text-primary', agentic: 'text-secondary-accent', }; export function PillarsSection() { const { t } = useTranslation(); const reduceMotion = useReducedMotion(); const { resolvedTheme } = useTheme(); const markTheme = resolvedTheme === 'light' ? 'light' : 'dark'; return (
{t('landing.pillars.eyebrow')}

{t('landing.pillars.headline')}{' '} {t('landing.pillars.headlineHighlight')}

{PILLAR_KEYS.map((key, i) => (

{t(`landing.pillars.${key}.name`)}

{/* Spine node: the mark on its vertical hairline. Text columns carry the row padding so the segments meet flush between rows and read as one continuous axis. */}
{/* The definition heads the description it defines — the name stands alone on its side of the spine. */}
{t(`landing.pillars.${key}.definition`)}

{t(`landing.pillars.${key}.belief`)}

))}
); }