// iterations.jsx — design iterations for A/B testing // · FormBlockMetroA — flat metro line, every field is a stop // · FormBlockMetroB — grouped "stations", line connects sections // · FAQMetro — accordion on a metro rail // · FAQCategorized — open two-column grid grouped by topic // // Globals consumed: React, I (icons), BlockMeta (from blocks.jsx). // All forms use REAL controlled inputs so the metro line lights up // vertically as the visitor fills fields / opens questions. const { useState, useRef, useLayoutEffect, useEffect } = React; // ───────────────────────────────────────────────────────────── // Shared rail hook — measures dot centers and returns the // geometry needed to draw the track + scroll-style fill line. // `activeIndex` = deepest lit node; fill runs from node 0 to it. // ───────────────────────────────────────────────────────────── function useRail(activeIndex, deps) { const railRef = useRef(null); const dotRefs = useRef([]); const [centers, setCenters] = useState([]); useLayoutEffect(() => { const measure = () => { const base = railRef.current ? railRef.current.getBoundingClientRect().top : 0; const cs = dotRefs.current.map(d => d ? (d.getBoundingClientRect().top - base + d.offsetHeight / 2) : null); setCenters(cs); }; measure(); const r = () => measure(); window.addEventListener('resize', r); const t = setTimeout(measure, 60); // after fonts settle return () => { window.removeEventListener('resize', r); clearTimeout(t); }; }, deps); // eslint-disable-line const valid = centers.filter(c => c != null); const top = valid.length ? valid[0] : 0; const bottom = valid.length ? valid[valid.length - 1] : 0; const fill = (activeIndex >= 0 && centers[activeIndex] != null) ? centers[activeIndex] - top : 0; return { railRef, dotRefs, top, height: bottom - top, fill }; } function deepestActive(flags) { let idx = -1; flags.forEach((f, i) => { if (f) idx = i; }); return idx; } // ───────────────────────────────────────────────────────────── // Small field atoms (controlled) // ───────────────────────────────────────────────────────────── function Req() { return *; } function TextField({ label, type = 'text', placeholder, value, onChange, onFocus, onBlur, required }) { return ( ); } function SelectField({ label, value, onChange, onFocus, onBlur, required, options }) { return ( ); } function TextareaField({ label, placeholder, value, onChange, onFocus, onBlur, required }) { return (