// Part 3, "Retrieval": ask → graph lights up → exact context comes back.
// Dark, premium restyle continuing the hero / Part-2 living-graph aesthetic.
const { useEffect: useEffectRT, useRef: useRefRT, useState: useStateRT, useCallback: useCallbackRT } = React;

// Brand candy palette (matches hero + Part 2)
const RT_C = { code: '#6E9BFF', docs: '#3FE0AE', res: '#B49BFF' };
const rtHexA = (hex, a) => {
    const n = parseInt(hex.slice(1), 16);
    return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${a})`;
};

function RetrievalSection() {
    const sectionRef = useRefRT(null);
    const eyebrowRef = useRefRT(null);
    const headlineRef = useRefRT(null);
    const subRef = useRefRT(null);

    useEffectRT(() => {
        const threshold = window.innerHeight < 700 ? 0.15 : 0.3;
        const observer = createVisibilityObserver(
            ([entry]) => {
                if (entry.isIntersecting) {
                    if (eyebrowRef.current) {
                        eyebrowRef.current.style.transition = 'opacity 400ms cubic-bezier(0.4,0,0.2,1), transform 400ms cubic-bezier(0.4,0,0.2,1)';
                        eyebrowRef.current.style.opacity = '1';
                        eyebrowRef.current.style.transform = 'translateY(0)';
                    }
                    setTimeout(() => {
                        if (headlineRef.current) {
                            headlineRef.current.style.transition = 'opacity 500ms cubic-bezier(0.4,0,0.2,1), transform 500ms cubic-bezier(0.4,0,0.2,1)';
                            headlineRef.current.style.opacity = '1';
                            headlineRef.current.style.transform = 'translateY(0)';
                        }
                    }, 130);
                    setTimeout(() => {
                        if (subRef.current) {
                            subRef.current.style.transition = 'opacity 500ms cubic-bezier(0.4,0,0.2,1), transform 500ms cubic-bezier(0.4,0,0.2,1)';
                            subRef.current.style.opacity = '1';
                            subRef.current.style.transform = 'translateY(0)';
                        }
                    }, 260);
                    observer.disconnect();
                }
            },
            { threshold }
        );
        if (sectionRef.current) observer.observe(sectionRef.current);
        return () => observer.disconnect();
    }, []);

    return (
        <section ref={sectionRef} data-screen-label="Retrieval Headline" style={{
            position: 'relative', zIndex: 2,
            width: '100%', padding: '110px 24px 10px', boxSizing: 'border-box',
            textAlign: 'center'
        }}>
            <div style={{ maxWidth: '780px', margin: '0 auto' }}>
                <div ref={eyebrowRef} className="font-mono" style={{
                    fontSize: '12px', fontWeight: 600, letterSpacing: '0.28em',
                    textTransform: 'uppercase', color: '#9b8bff', marginBottom: '18px',
                    opacity: 0, transform: 'translateY(12px)'
                }}>Retrieval</div>
                <h2 ref={headlineRef} className="font-bricolage" style={{
                    fontSize: 'clamp(30px, 4.4vw, 56px)', fontWeight: 700, lineHeight: 1.05,
                    letterSpacing: '-0.03em', color: '#fff', margin: 0,
                    opacity: 0, transform: 'translateY(14px)'
                }}>
                    Ask in plain language.<br />Get <span style={{
                        background: 'linear-gradient(100deg,#7b5cff,#6e9bff 45%,#3fe0ae)',
                        WebkitBackgroundClip: 'text', backgroundClip: 'text', color: 'transparent'
                    }}>only</span> the passages that matter.
                </h2>
                <p ref={subRef} className="font-google" style={{
                    fontSize: 'clamp(15px,1.5vw,18px)', lineHeight: 1.6, color: 'rgba(255,255,255,0.62)',
                    maxWidth: '600px', margin: '22px auto 0', textWrap: 'pretty',
                    opacity: 0, transform: 'translateY(14px)'
                }}>
                    Not in your documents? TGM says so, at zero tokens.
                </p>
            </div>
        </section>
    );
}

// The certified demo (release sprint §3.3 / demo runbook §7): real
// questions from the Tier-7 golden set, run against the live demo
// corpus (classic legal texts). Every 'success' chip quotes the
// byte-exact evidence span from the corpus; every 'error' is a
// certified entity-absent trap the live API reports not-covered at 0 tokens.
// Change these together with the golden set or not at all.
const RETRIEVAL_QUERIES = [
    {
        type: 'success', text: 'Under the Code of Hammurabi, what penalty is prescribed for a man who steals the son of a freeman?',
        results: [
            { text: 'code_of_hammurabi.txt · "he shall be put to death"', c: RT_C.docs },
            { text: 'verbatim span, byte-checked against the source', c: RT_C.res },
            { text: 'not_covered: false · joint_coverage: true', c: RT_C.code }
        ],
        flyingNodes: [0, 1, 4], highlightEdges: [0, 6]
    },
    {
        type: 'success', text: "In the Apache License 2.0, what does the term 'You' mean?",
        results: [
            { text: 'apache_license.txt · ""You" (or "Your") shall mean…"', c: RT_C.docs },
            { text: '"…an individual or Legal Entity exercising permissions"', c: RT_C.docs },
            { text: 'not_covered: false · source named on every passage', c: RT_C.code }
        ],
        flyingNodes: [3, 4, 1], highlightEdges: [1, 3]
    },
    {
        type: 'error', text: "What is the legal effect of a 'writ of quandarum' in Blackstone's Commentaries?",
        errorText: 'Not in your documents · 0 tokens'
    },
    {
        type: 'success', text: 'What exclamation does Cicero use in the First Oration against Catiline?',
        results: [
            { text: 'cicero_orations.txt · "O tempora, o mores!"', c: RT_C.res },
            { text: 'served exactly as written, never a paraphrase', c: RT_C.docs },
            { text: 'not_covered: false', c: RT_C.code }
        ],
        flyingNodes: [6, 7, 8], highlightEdges: [5, 8], glowColor: RT_C.res
    },
    {
        type: 'success', text: 'What does Paine say produces society, versus government?',
        results: [
            { text: 'common_sense_paine.txt · "Society is produced by our wants,"', c: RT_C.docs },
            { text: '"…and government by our wickedness"', c: RT_C.docs },
            { text: 'not_covered: false · joint_coverage: true', c: RT_C.code }
        ],
        flyingNodes: [1, 2, 4], highlightEdges: [6, 1], glowColor: RT_C.code
    },
    {
        type: 'success', text: "What is Bastiat's object in writing 'Capital and Interest'?",
        results: [
            { text: 'bastiat_law.txt · "to examine into the real nature of…"', c: RT_C.docs },
            { text: '"…the Interest of Capital"', c: RT_C.docs },
            { text: 'not_covered: false', c: RT_C.res }
        ],
        flyingNodes: [5, 3, 7], highlightEdges: [3, 5]
    },
    {
        type: 'error', text: 'What does Paine say about the Ashford Doctrine of representative recall?',
        errorText: 'Not in your documents · 0 tokens'
    },
    {
        type: 'success', text: 'Where was Cicero when he heard of the death of Hortensius?',
        results: [
            { text: 'cicero_brutus.txt · "arrived at Rhodes, word was brought me"', c: RT_C.docs },
            { text: 'byte-faithful span with its source id', c: RT_C.res },
            { text: 'not_covered: false', c: RT_C.code }
        ],
        flyingNodes: [2, 0, 3], highlightEdges: [0, 7], glowColor: RT_C.code
    }
];

const RETRIEVAL_BASE_NODES = [
    { cx: 0.098, cy: 0.109, color: RT_C.code, label: 'auth.py', Icon: Code },
    { cx: 0.156, cy: 0.435, color: RT_C.code, label: 'router.py', Icon: Code },
    { cx: 0.117, cy: 0.761, color: RT_C.code, label: 'models.py', Icon: Code },
    { cx: 0.430, cy: 0.174, color: RT_C.docs, label: 'Deploy.md', Icon: FileText },
    { cx: 0.488, cy: 0.413, color: RT_C.docs, label: 'API.md', Icon: FileText },
    { cx: 0.410, cy: 0.717, color: RT_C.docs, label: 'Onboard.md', Icon: FileText },
    { cx: 0.742, cy: 0.130, color: RT_C.res, label: 'Paper A', Icon: FlaskConical },
    { cx: 0.801, cy: 0.457, color: RT_C.res, label: 'Paper B', Icon: FlaskConical },
    { cx: 0.703, cy: 0.783, color: RT_C.res, label: 'Bench.csv', Icon: Database },
];

const RETRIEVAL_BASE_EDGES = [
    { n1: 0, n2: 3, qx: 0.311, qy: 0.109, color: RT_C.code },
    { n1: 1, n2: 4, qx: 0.369, qy: 0.391, color: RT_C.code },
    { n1: 2, n2: 5, qx: 0.311, qy: 0.696, color: RT_C.code },
    { n1: 3, n2: 6, qx: 0.633, qy: 0.109, color: RT_C.docs },
    { n1: 4, n2: 7, qx: 0.691, qy: 0.413, color: RT_C.docs },
    { n1: 5, n2: 8, qx: 0.604, qy: 0.761, color: RT_C.docs },
    { n1: 0, n2: 1, qx: 0.098, qy: 0.324, color: RT_C.code },
    { n1: 3, n2: 4, qx: 0.430, qy: 0.346, color: RT_C.docs },
    { n1: 7, n2: 8, qx: 0.879, qy: 0.672, color: RT_C.res },
];

function RetrievalDemoSection() {
    const sectionRef = useRefRT(null);
    const canvasRef = useRefRT(null);
    const queryRef = useRefRT(null);
    const cursorRef = useRefRT(null);
    const resultsLabelRef = useRefRT(null);
    const pillRefs = useRefRT([]);
    const nodeRefs = useRefRT([]);
    const edgeRefs = useRefRT([]);
    const labelRefs = useRefRT([]);
    const dotRefs = useRefRT([]);
    const loopRef = useRefRT(null);
    const isVisibleRef = useRefRT(false);
    // Concurrency control: one live chain at a time.
    const timersRef = useRefRT([]);          // all pending setTimeouts
    const typeIntervalRef = useRefRT(null);  // active typewriter interval
    const genRef = useRefRT(0);              // incremented to invalidate stale chains

    const [canvasSize, setCanvasSize] = useStateRT({ width: 500, height: 460 });

    const computeNodes = useCallbackRT((w, h) =>
        RETRIEVAL_BASE_NODES.map(n => ({ ...n, px: n.cx * w, py: n.cy * h, left: n.cx * w - 24, top: n.cy * h - 24 })), []);
    const computeEdges = useCallbackRT((w, h, nodes) =>
        RETRIEVAL_BASE_EDGES.map(e => ({ ...e, x1: nodes[e.n1].px, y1: nodes[e.n1].py, x2: nodes[e.n2].px, y2: nodes[e.n2].py, qx: e.qx * w, qy: e.qy * h })), []);

    const graphNodes = computeNodes(canvasSize.width, canvasSize.height);
    const graphEdges = computeEdges(canvasSize.width, canvasSize.height, graphNodes);

    useEffectRT(() => {
        if (!canvasRef.current) return;
        const ro = new ResizeObserver(entries => {
            for (const entry of entries) setCanvasSize({ width: entry.contentRect.width, height: entry.contentRect.height });
        });
        ro.observe(canvasRef.current);
        return () => ro.disconnect();
    }, []);

    const queryIndexRef = useRefRT(0);
    const errorPillRef = useRefRT(null);

    const clearAllTimers = useCallbackRT(() => {
        timersRef.current.forEach(id => clearTimeout(id));
        timersRef.current = [];
        if (typeIntervalRef.current) { clearInterval(typeIntervalRef.current); typeIntervalRef.current = null; }
    }, []);

    const stylePill = (pill, r) => {
        pill.textContent = r.text;
        pill.style.background = rtHexA(r.c, 0.1);
        pill.style.border = `1px solid ${rtHexA(r.c, 0.5)}`;
        pill.style.color = '#fff';
        pill.style.boxShadow = `inset 0 0 16px ${rtHexA(r.c, 0.08)}`;
        pill.style.setProperty('--dot', r.c);
    };

    const setActiveDot = (idx) => {
        dotRefs.current.forEach((d, i) => {
            if (!d) return;
            d.style.width = i === idx ? '22px' : '7px';
            d.style.background = i === idx ? 'linear-gradient(90deg,#7b5cff,#3fe0ae)' : 'rgba(255,255,255,0.2)';
        });
    };

    const resetAll = useCallbackRT(() => {
        clearAllTimers();
        if (queryRef.current) queryRef.current.textContent = '';
        if (cursorRef.current) { cursorRef.current.style.opacity = '1'; cursorRef.current.style.display = 'inline'; }
        if (resultsLabelRef.current) {
            resultsLabelRef.current.style.opacity = '0';
            resultsLabelRef.current.style.transform = 'translateY(8px)';
            resultsLabelRef.current.textContent = 'Retrieved context';
            resultsLabelRef.current.style.color = '#9b8bff';
        }
        pillRefs.current.forEach(p => { if (p) { p.style.opacity = '0'; p.style.transform = 'translateY(8px) scale(0.95)'; } });
        if (errorPillRef.current) { errorPillRef.current.style.opacity = '0'; errorPillRef.current.style.transform = 'translateY(8px) scale(0.95)'; }
        edgeRefs.current.forEach((e, idx) => {
            if (!e) return;
            e.style.transition = 'none';
            e.setAttribute('opacity', '0.4');
            e.setAttribute('stroke-width', '1.5');
            e.style.filter = 'none';
            if (idx < RETRIEVAL_BASE_EDGES.length) e.setAttribute('stroke', RETRIEVAL_BASE_EDGES[idx].color);
        });
        document.querySelectorAll('.retrieval-flying-clone').forEach(c => c.remove());
    }, [clearAllTimers]);

    const runQuery = useCallbackRT((index, gen) => {
        if (!isVisibleRef.current || gen !== genRef.current) return;
        resetAll();
        setActiveDot(index);

        // Tracked timer that also bails if this chain has been superseded.
        const T = (fn, ms) => {
            const id = setTimeout(() => {
                if (!isVisibleRef.current || gen !== genRef.current) return;
                fn();
            }, ms);
            timersRef.current.push(id);
            return id;
        };

        const q = RETRIEVAL_QUERIES[index];

        if (q.type === 'success') {
            q.results.forEach((r, i) => { const pill = pillRefs.current[i]; if (pill) { stylePill(pill, r); pill.style.display = 'flex'; } });
            for (let i = q.results.length; i < 5; i++) if (pillRefs.current[i]) pillRefs.current[i].style.display = 'none';
        }

        let charIndex = 0;
        typeIntervalRef.current = setInterval(() => {
            if (gen !== genRef.current || !queryRef.current) { clearInterval(typeIntervalRef.current); typeIntervalRef.current = null; return; }
            charIndex++;
            queryRef.current.textContent = q.text.slice(0, charIndex);
            if (charIndex >= q.text.length) { clearInterval(typeIntervalRef.current); typeIntervalRef.current = null; }
        }, (1200 / q.text.length));

        // Graph activates
        T(() => {
            if (q.type === 'error') {
                edgeRefs.current.forEach(e => {
                    if (!e) return;
                    e.style.transition = 'stroke 400ms, opacity 400ms, stroke-width 400ms, filter 400ms';
                    e.setAttribute('stroke', '#ff6b8b'); e.setAttribute('stroke-width', '2.5');
                    e.style.filter = 'drop-shadow(0 0 5px #ff6b8b)';
                });
                nodeRefs.current.forEach(n => {
                    if (!n) return;
                    n.style.transition = 'transform 75ms ease-in-out';
                    n.style.transform = 'translateX(-3px)';
                    setTimeout(() => { n.style.transform = 'translateX(3px)'; }, 75);
                    setTimeout(() => { n.style.transform = 'translateX(-2px)'; }, 150);
                    setTimeout(() => { n.style.transform = 'translateX(0)'; }, 225);
                });
            } else {
                edgeRefs.current.forEach(e => {
                    if (!e) return;
                    e.style.transition = 'opacity 400ms, stroke-width 400ms, stroke 400ms, filter 400ms';
                    e.setAttribute('opacity', '0.12');
                });
                q.highlightEdges.forEach(idx => {
                    const e = edgeRefs.current[idx];
                    if (!e) return;
                    setTimeout(() => {
                        const color = q.glowColor || RETRIEVAL_BASE_EDGES[idx].color;
                        e.setAttribute('opacity', '1'); e.setAttribute('stroke-width', '3'); e.setAttribute('stroke', color);
                        e.style.filter = `drop-shadow(0 0 6px ${color})`;
                    }, 100);
                });
                q.flyingNodes.forEach(idx => {
                    const n = nodeRefs.current[idx];
                    if (!n) return;
                    n.style.transition = 'transform 200ms ease-out';
                    n.style.transform = 'scale(1.18)';
                    setTimeout(() => { n.style.transition = 'transform 200ms ease-out'; n.style.transform = 'scale(1)'; }, 220);
                });
            }
        }, 1400);

        // Flight + results
        T(() => {
            if (cursorRef.current) cursorRef.current.style.display = 'none';

            if (q.type === 'error') {
                if (resultsLabelRef.current) {
                    resultsLabelRef.current.textContent = 'Result';
                    resultsLabelRef.current.style.color = '#ff6b8b';
                    resultsLabelRef.current.style.transition = 'opacity 400ms ease, transform 400ms ease';
                    resultsLabelRef.current.style.opacity = '1';
                    resultsLabelRef.current.style.transform = 'translateY(0)';
                }
                if (errorPillRef.current) {
                    errorPillRef.current.innerHTML = `<span style="font-size:14px;line-height:1">✕</span> ${q.errorText}`;
                    errorPillRef.current.style.transition = 'opacity 300ms ease, transform 300ms cubic-bezier(0.34,1.56,0.64,1)';
                    errorPillRef.current.style.opacity = '1';
                    errorPillRef.current.style.transform = 'translateY(0) scale(1)';
                }
            } else {
                q.flyingNodes.forEach((nodeIdx, i) => {
                    const originalNode = nodeRefs.current[nodeIdx];
                    if (!originalNode) return;
                    T(() => {
                        const rect = originalNode.getBoundingClientRect();
                        const clone = document.createElement('div');
                        clone.className = 'retrieval-flying-clone';
                        clone.style.cssText = `
                            position: fixed; left: ${rect.left}px; top: ${rect.top}px;
                            width: ${rect.width}px; height: ${rect.height}px;
                            background-color: ${RETRIEVAL_BASE_NODES[nodeIdx].color}; border-radius: 10px;
                            display: flex; align-items: center; justify-content: center;
                            z-index: 100; pointer-events: none;
                            box-shadow: 0 0 18px ${RETRIEVAL_BASE_NODES[nodeIdx].color};
                            transition: left 520ms cubic-bezier(0.4,0,0.2,1), top 520ms cubic-bezier(0.4,0,0.2,1),
                                        width 520ms cubic-bezier(0.4,0,0.2,1), height 520ms cubic-bezier(0.4,0,0.2,1),
                                        opacity 520ms ease, border-radius 520ms ease;
                        `;
                        clone.innerHTML = originalNode.innerHTML;
                        document.body.appendChild(clone);

                        requestAnimationFrame(() => {
                            const pill = pillRefs.current[i];
                            if (pill) {
                                const pr = pill.getBoundingClientRect();
                                clone.style.left = `${pr.left + 12}px`; clone.style.top = `${pr.top + pr.height / 2 - 12}px`;
                                clone.style.width = '24px'; clone.style.height = '24px';
                                clone.style.borderRadius = '12px'; clone.style.opacity = '0';
                            } else { clone.style.left = `${rect.left - 300}px`; clone.style.opacity = '0'; }
                        });

                        T(() => {
                            const pill = pillRefs.current[i];
                            if (pill) {
                                pill.style.transition = 'opacity 200ms ease, transform 300ms cubic-bezier(0.34,1.56,0.64,1)';
                                pill.style.opacity = '1'; pill.style.transform = 'translateY(0) scale(1)';
                            }
                            clone.remove();
                        }, 520);
                    }, i * 90);
                });
            }
        }, 2200);

        // Results label settle
        T(() => {
            if (q.type === 'success') {
                if (resultsLabelRef.current) {
                    resultsLabelRef.current.style.transition = 'opacity 400ms ease, transform 400ms ease';
                    resultsLabelRef.current.style.opacity = '1';
                    resultsLabelRef.current.style.transform = 'translateY(0)';
                }
                edgeRefs.current.forEach((e, idx) => {
                    if (!e) return;
                    e.style.transition = 'opacity 400ms, stroke-width 400ms, filter 400ms, stroke 400ms';
                    e.setAttribute('opacity', '0.4'); e.setAttribute('stroke-width', '1.5'); e.style.filter = 'none';
                    if (idx < RETRIEVAL_BASE_EDGES.length) e.setAttribute('stroke', RETRIEVAL_BASE_EDGES[idx].color);
                });
            }
        }, 3200);

        // Hold + advance
        T(() => {
            pillRefs.current.forEach(p => { if (p) { p.style.transition = 'opacity 400ms'; p.style.opacity = '0'; } });
            if (errorPillRef.current) { errorPillRef.current.style.transition = 'opacity 400ms'; errorPillRef.current.style.opacity = '0'; }
            if (resultsLabelRef.current) { resultsLabelRef.current.style.transition = 'opacity 400ms'; resultsLabelRef.current.style.opacity = '0'; }
            if (queryRef.current) { queryRef.current.style.transition = 'opacity 400ms'; queryRef.current.style.opacity = '0'; }

            if (q.type === 'error') {
                edgeRefs.current.forEach((e, idx) => {
                    if (!e) return;
                    e.style.transition = 'stroke 400ms, opacity 400ms, stroke-width 400ms, filter 400ms';
                    if (idx < RETRIEVAL_BASE_EDGES.length) e.setAttribute('stroke', RETRIEVAL_BASE_EDGES[idx].color);
                    e.setAttribute('opacity', '0.4'); e.setAttribute('stroke-width', '1.5'); e.style.filter = 'none';
                });
            }

            T(() => {
                if (queryRef.current) { queryRef.current.style.transition = 'none'; queryRef.current.style.opacity = '1'; }
                queryIndexRef.current = (queryIndexRef.current + 1) % RETRIEVAL_QUERIES.length;
                T(() => runQuery(queryIndexRef.current, gen), 450);
            }, 500);
        }, 4600);
    }, [resetAll]);

    // Start a fresh chain, invalidating any previous one.
    const runAnimation = useCallbackRT(() => {
        const gen = ++genRef.current;
        clearAllTimers();
        runQuery(queryIndexRef.current, gen);
    }, [runQuery, clearAllTimers]);

    useEffectRT(() => {
        let kickoff = null;
        const observer = createVisibilityObserver(
            ([entry]) => {
                const wasVisible = isVisibleRef.current;
                isVisibleRef.current = entry.isIntersecting;
                if (entry.isIntersecting) {
                    if (wasVisible) return;            // already running, don't start a 2nd chain
                    genRef.current++;                  // invalidate anything stale
                    resetAll();
                    kickoff = setTimeout(() => runAnimation(), 400);
                    timersRef.current.push(kickoff);
                } else {
                    genRef.current++;                  // kill the live chain
                    resetAll();
                }
            },
            { threshold: 0.3 }
        );
        if (sectionRef.current) observer.observe(sectionRef.current);
        return () => { observer.disconnect(); genRef.current++; clearAllTimers(); };
    }, [runAnimation, resetAll, clearAllTimers]);

    return (
        <>
            <style>{`
                .rt-section {
                    position: relative; z-index: 2;
                    width: 100%; padding: 30px 24px 110px; box-sizing: border-box;
                }
                .rt-console {
                    max-width: 1160px; margin: 0 auto;
                    background: linear-gradient(180deg, rgba(255,255,255,0.045), rgba(255,255,255,0.02));
                    border: 1px solid rgba(255,255,255,0.1);
                    border-radius: 26px;
                    box-shadow: 0 30px 80px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.06);
                    backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
                    overflow: hidden;
                }
                .rt-titlebar {
                    display: flex; align-items: center; gap: 10px;
                    padding: 15px 22px; border-bottom: 1px solid rgba(255,255,255,0.07);
                }
                .rt-dot { width: 11px; height: 11px; border-radius: 50%; }
                .rt-live {
                    margin-left: auto; display: inline-flex; align-items: center; gap: 7px;
                    font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: 0.12em;
                    color: rgba(255,255,255,0.5); text-transform: uppercase;
                }
                .rt-live-dot { width: 7px; height: 7px; border-radius: 50%; background: #3fe0ae; box-shadow: 0 0 9px #3fe0ae; animation: rtpulse 1.8s infinite; }
                @keyframes rtpulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:0.4;transform:scale(0.7)} }

                .rt-cols { display: flex; gap: 0; }
                .rt-left { width: 44%; min-width: 300px; padding: 30px 30px 34px; box-sizing: border-box; border-right: 1px solid rgba(255,255,255,0.07); display: flex; flex-direction: column; }
                .rt-right { width: 56%; min-width: 300px; padding: 26px; box-sizing: border-box; }

                .rt-fieldlabel {
                    font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 600;
                    letter-spacing: 0.22em; text-transform: uppercase; color: #9b8bff; margin-bottom: 11px;
                }
                .rt-querybar {
                    display: flex; align-items: center; gap: 11px;
                    background: rgba(0,0,0,0.25); border: 1px solid rgba(255,255,255,0.12);
                    border-radius: 14px; padding: 14px 18px; min-height: 26px;
                    box-shadow: inset 0 0 0 1px rgba(123,92,255,0.06);
                }
                .rt-query-text { font-family: 'Hanken Grotesk', sans-serif; font-size: 16.5px; font-weight: 500; color: #fff; }
                .rt-cursor { color: #7b5cff; font-weight: 300; animation: rtblink 0.7s step-end infinite; }
                @keyframes rtblink { 0%,100%{opacity:1} 50%{opacity:0} }

                .rt-dots { display: flex; gap: 6px; margin-top: 16px; }
                .rt-qdot { width: 7px; height: 7px; border-radius: 4px; background: rgba(255,255,255,0.2); transition: width 0.4s ease, background 0.4s ease; }

                .rt-results { margin-top: 28px; display: flex; flex-direction: column; flex: 1; }
                .rt-pills { display: flex; flex-direction: column; gap: 9px; margin-top: 12px; }
                .rt-pill {
                    display: flex; align-items: center; gap: 11px;
                    border-radius: 13px; padding: 12px 16px;
                    font-family: 'Hanken Grotesk', sans-serif; font-size: 14px; font-weight: 500;
                }
                .rt-pill::before {
                    content: ''; width: 7px; height: 7px; border-radius: 50%;
                    background: var(--dot, #6e9bff); box-shadow: 0 0 8px var(--dot, #6e9bff); flex-shrink: 0;
                }
                .rt-err {
                    display: flex; align-items: center; gap: 9px;
                    border-radius: 13px; padding: 12px 16px;
                    font-family: 'Hanken Grotesk', sans-serif; font-size: 14px; font-weight: 600;
                    background: rgba(255,107,139,0.1); border: 1px solid rgba(255,107,139,0.45); color: #ff8ba3;
                }
                .rt-graph-card {
                    width: 100%; min-height: 420px; aspect-ratio: 1.2 / 1;
                    background:
                        radial-gradient(80% 70% at 50% 40%, rgba(123,92,255,0.06), transparent 70%),
                        rgba(0,0,0,0.18);
                    border-radius: 18px; border: 1px solid rgba(255,255,255,0.08);
                    position: relative; overflow: hidden;
                }
                .rt-node-label { font-family: 'JetBrains Mono', monospace; }

                @media (max-width: 900px) {
                    .rt-cols { flex-direction: column-reverse; }
                    .rt-left, .rt-right { width: 100%; min-width: 0; border-right: none; }
                    .rt-left { border-top: 1px solid rgba(255,255,255,0.07); }
                }
            `}</style>

            <section ref={sectionRef} data-screen-label="Retrieval Demo" className="rt-section">
                <div className="rt-console">
                    {/* title bar */}
                    <div className="rt-titlebar">
                        <span className="rt-dot" style={{ background: '#ff6b8b' }}></span>
                        <span className="rt-dot" style={{ background: '#ffd166' }}></span>
                        <span className="rt-dot" style={{ background: '#3fe0ae' }}></span>
                        <span className="font-mono" style={{ marginLeft: '10px', fontSize: '12px', color: 'rgba(255,255,255,0.45)', letterSpacing: '0.08em' }}>tgm · retrieve</span>
                        <span className="rt-live"><span className="rt-live-dot"></span>Live</span>
                    </div>

                    <div className="rt-cols">
                        {/* LEFT, query + results */}
                        <div className="rt-left">
                            <div className="rt-fieldlabel">Query</div>
                            <div className="rt-querybar">
                                <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#7b5cff" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}>
                                    <circle cx="11" cy="11" r="7"></circle><path d="m21 21-4.3-4.3"></path>
                                </svg>
                                <span ref={queryRef} className="rt-query-text"></span>
                                <span ref={cursorRef} className="rt-cursor">|</span>
                            </div>
                            <div className="rt-dots">
                                {RETRIEVAL_QUERIES.map((_, i) => (
                                    <span key={i} ref={el => dotRefs.current[i] = el} className="rt-qdot"></span>
                                ))}
                            </div>

                            <div className="rt-results">
                                <div ref={resultsLabelRef} className="rt-fieldlabel" style={{ marginBottom: 0, opacity: 0, transform: 'translateY(8px)' }}>Retrieved context</div>
                                <div className="rt-pills">
                                    {[0, 1, 2, 3, 4].map(i => (
                                        <div key={i} ref={el => pillRefs.current[i] = el} className="rt-pill"
                                            style={{ opacity: 0, transform: 'translateY(8px) scale(0.95)', display: i < 3 ? 'flex' : 'none' }}>
                                        </div>
                                    ))}
                                    <div ref={errorPillRef} className="rt-err" style={{ opacity: 0, transform: 'translateY(8px) scale(0.95)' }}>
                                        <span style={{ fontSize: '14px', lineHeight: 1 }}>✕</span>Not in your documents · 0 tokens
                                    </div>
                                </div>
                            </div>
                        </div>

                        {/* RIGHT, knowledge graph */}
                        <div className="rt-right">
                            <div ref={canvasRef} className="rt-graph-card">
                                <svg style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none', overflow: 'visible' }}>
                                    {graphEdges.map((e, i) => (
                                        <path key={`e-${i}`} ref={el => edgeRefs.current[i] = el}
                                            d={`M ${e.x1} ${e.y1} Q ${e.qx} ${e.qy} ${e.x2} ${e.y2}`}
                                            fill="none" stroke={e.color} strokeWidth="1.5" opacity="0.4"></path>
                                    ))}
                                </svg>
                                {graphNodes.map((n, i) => {
                                    const NodeIcon = n.Icon;
                                    return (
                                        <div key={`n-${i}`}>
                                            <div ref={el => nodeRefs.current[i] = el} style={{
                                                position: 'absolute', left: n.left, top: n.top, width: '48px', height: '48px',
                                                backgroundColor: n.color, borderRadius: '12px',
                                                display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 5,
                                                boxShadow: `0 0 16px ${rtHexA(n.color, 0.55)}`
                                            }}>
                                                <NodeIcon size={20} color="#0a0a16" />
                                            </div>
                                            <div ref={el => labelRefs.current[i] = el} className="rt-node-label" style={{
                                                position: 'absolute', left: n.px, top: n.py + 32, transform: 'translateX(-50%)',
                                                fontSize: 'clamp(9px,0.8vw,11px)', color: 'rgba(255,255,255,0.5)', whiteSpace: 'nowrap'
                                            }}>{n.label}</div>
                                        </div>
                                    );
                                })}
                            </div>
                        </div>
                    </div>
                </div>
            </section>
        </>
    );
}

Object.assign(window, { RetrievalSection, RetrievalDemoSection });
