"use client"; import * as React from "react"; import { motion } from "framer-motion"; import { BitAura } from "@/src/components/bits/BitAura"; import { DecodeText } from "@/src/components/bits/DecodeText"; import { PathScene } from "@/src/components/illustrations/PathScenes"; import { useContent } from "@/src/components/ContentProvider"; import { TopicButton } from "./TopicButton"; import type { ServicePath, ServicePathId } from "@/src/content/types"; const MONO = "font-mono text-[11px] uppercase tracking-[0.2em] text-slate-500"; const STEP_MS = 4800; /** * PathStory: the four steps of one path, each with a drawing that explains it. * The steps advance on their own until the visitor picks one. */ const PathStory: React.FC<{ path: ServicePath; active: boolean }> = ({ path, active, }) => { const [step, setStep] = React.useState(0); const [auto, setAuto] = React.useState(true); const ref = React.useRef(null); const [inView, setInView] = React.useState(false); React.useEffect(() => { const node = ref.current; if (!node) return; const observer = new IntersectionObserver( ([entry]) => setInView(entry?.isIntersecting ?? false), { threshold: 0.35 }, ); observer.observe(node); return () => observer.disconnect(); }, []); React.useEffect(() => { if (!active || !auto || !inView) return; if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return; const timer = window.setInterval( () => setStep((current) => (current + 1) % path.steps.length), STEP_MS, ); return () => window.clearInterval(timer); }, [active, auto, inView, path.steps.length]); const current = path.steps[step]; return (
    {path.steps.map((item, index) => { const selected = index === step; return (
  1. ); })}
); }; /** * PathPicker: the visitor says what they need and gets the answer for exactly that: * what they get, how it runs, what it costs, what to do next. * All three panels stay in the DOM so the content is readable without JavaScript. */ export const PathPicker: React.FC<{ /** The cases to show, in this order. */ ids: readonly ServicePathId[]; /** `offer`: ask for an offer, no figures. `estimate`: the way to a price, with figures. */ pricing: "offer" | "estimate"; }> = ({ ids, pricing }) => { const { services } = useContent(); const { estimate, care } = services; const paths = ids.flatMap((id) => services.paths.filter((path) => path.id === id), ); const [activeId, setActiveId] = React.useState(paths[0]?.id ?? ""); return (
{paths.map((path, index) => { const selected = path.id === activeId; return ( ); })}
{paths.map((path) => { const selected = path.id === activeId; return ( ); })}
); };