/* A3 Studio (chat) — supporting context: run plan rail + live browser. */
const { Icon, HGroup, VGroup, Filler, Button, Tag } = window.A3DesignSystem_a87aaf;

const PLAN_STATUS = {
    executed: { icon: 'fas fa-circle-check', color: 'var(--p-green-500)' },
    executing: { icon: 'fas fa-spinner-third', color: 'var(--p-yellow-500)', spin: true },
    pending: { icon: 'far fa-circle', color: 'var(--iso-surface-300)' },
    failed: { icon: 'fas fa-circle-xmark', color: 'var(--iso-danger-500)' },
};

function DatasetMenu({ datasets = [], value, onChange }) {
    const [open, setOpen] = React.useState(false);
    const ref = React.useRef(null);
    const sel = datasets.find(d => d.id === value) || { label: value };
    React.useEffect(() => {
        if (!open) return;
        const onDoc = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
        document.addEventListener('mousedown', onDoc);
        return () => document.removeEventListener('mousedown', onDoc);
    }, [open]);
    return (
        <div ref={ref} style={{ position: 'relative' }}>
            <HGroup gap="1" onClick={() => setOpen(o => !o)}
                title="Select input dataset"
                style={{ padding: '5px 8px', borderRadius: 6, cursor: 'pointer', fontSize: 12, color: 'var(--p-text-color)' }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--iso-surface-100)'}
                onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                <Icon name="far fa-table" size={12} color="var(--p-text-muted-color)" />
                <span style={{ flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{sel.label}</span>
                <Icon name="far fa-chevron-down" size={9} color="var(--p-text-muted-color)" style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .12s' }} />
            </HGroup>
            {open && (
                <div style={{ position: 'absolute', bottom: 'calc(100% + 5px)', left: 0, right: 0, zIndex: 60, background: 'var(--iso-surface-0)', border: '1px solid var(--iso-surface-200)', borderRadius: 'var(--radius-md)', boxShadow: 'var(--shadow-md)', padding: 'var(--sp0-5)' }}>
                    {datasets.map(d => {
                        const active = d.id === (sel.id || value);
                        return (
                            <HGroup key={d.id} gap="1" onClick={() => { onChange && onChange(d.id); setOpen(false); }}
                                style={{ padding: '7px 10px', borderRadius: 'var(--radius-sm)', cursor: 'pointer', fontSize: 12.5, background: active ? 'var(--iso-primary-50)' : 'transparent', color: active ? 'var(--iso-primary-color)' : 'var(--p-text-color)', fontWeight: active ? 600 : 400 }}
                                onMouseEnter={e => { if (!active) e.currentTarget.style.background = 'var(--iso-surface-100)'; }}
                                onMouseLeave={e => { if (!active) e.currentTarget.style.background = 'transparent'; }}>
                                <Icon name="far fa-table" size={11} color={active ? 'var(--iso-primary-color)' : 'var(--p-text-muted-color)'} style={{ width: 14 }} />
                                <VGroup gap="0" style={{ flex: 1, minWidth: 0 }}>
                                    <span style={{ fontFamily: 'var(--font-mono)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{d.label}</span>
                                    {d.hint && <span style={{ fontSize: 11, fontWeight: 400, color: 'var(--p-text-muted-color)' }}>{d.hint}</span>}
                                </VGroup>
                                {active && <Icon name="fas fa-check" size={11} color="var(--iso-primary-color)" />}
                            </HGroup>
                        );
                    })}
                </div>
            )}
        </div>
    );
}

/* One workflow's stage group in the orchestrator chain — collapsible,
   open by default only when it's the active (in-progress) workflow. */
function OrchGroup({ g, gi, total, activeFile, onOpenStage }) {
    const gDone = g.stages.filter(s => s.status === 'executed').length;
    const gActive = g.stages.some(s => s.status === 'executing');
    const gComplete = gDone === g.stages.length;
    const [open, setOpen] = React.useState(gActive);
    // Auto-expand a group once it becomes the active (in-progress) workflow.
    React.useEffect(() => { if (gActive) setOpen(true); }, [gActive]);
    return (
        <div style={{ marginBottom: 'var(--sp0-5)' }}>
            <HGroup gap="1" onClick={() => setOpen(o => !o)} title={open ? 'Collapse' : 'Expand'}
                style={{ padding: '5px 10px 3px', cursor: 'pointer', borderRadius: 6 }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--iso-surface-100)'}
                onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                <Icon name="fas fa-chevron-right" size={9} color="var(--p-text-muted-color)" style={{ width: 10, transform: open ? 'rotate(90deg)' : 'none', transition: 'transform .12s' }} />
                <Icon name={gComplete ? 'fas fa-circle-check' : 'far fa-diagram-project'}
                    size={12} color={gComplete ? 'var(--p-green-500)' : gActive ? 'var(--iso-primary-color)' : 'var(--iso-surface-400)'} />
                <span style={{ flex: 1, minWidth: 0, fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 600, color: gActive ? 'var(--iso-primary-color)' : 'var(--p-text-color)' }}>{g.workflow}</span>
                <span style={{ fontSize: 10.5, color: 'var(--p-text-muted-color)' }}>{gDone}/{g.stages.length}</span>
            </HGroup>
            {open && (
                <div style={{ position: 'relative', paddingLeft: 18, marginLeft: 15, borderLeft: '1.5px solid var(--iso-surface-200)' }}>
                    {g.stages.map(s => {
                        const st = PLAN_STATUS[s.status];
                        const active = s.status === 'executing';
                        const fileOpen = activeFile === s.name;
                        return (
                            <HGroup key={s.name} gap="1" onClick={() => onOpenStage && onOpenStage(s.name)}
                                title={`Open ${s.name}.stage.ts`}
                                style={{ padding: '5px 8px', borderRadius: 6, cursor: 'pointer', background: fileOpen ? 'var(--iso-primary-50)' : active ? 'var(--iso-surface-0)' : 'transparent', boxShadow: active ? 'var(--shadow-sm)' : 'none' }}
                                onMouseEnter={e => { if (!fileOpen && !active) e.currentTarget.style.background = 'var(--iso-surface-100)'; }}
                                onMouseLeave={e => { if (!fileOpen && !active) e.currentTarget.style.background = 'transparent'; }}>
                                <Icon name={st.icon} size={12} color={st.color} style={st.spin ? { animation: 'a3-spin .8s linear infinite' } : null} />
                                <span style={{ flex: 1, minWidth: 0, fontFamily: 'var(--font-mono)', fontSize: 11.5, color: fileOpen ? 'var(--iso-primary-color)' : s.status === 'pending' ? 'var(--p-text-muted-color)' : 'var(--p-text-color)', fontWeight: (active || fileOpen) ? 600 : 400 }}>{s.name}</span>
                            </HGroup>
                        );
                    })}
                </div>
            )}
        </div>
    );
}

function PlanRail({ project, plan, workflows = [], orchestratorPlan = [], datasets = [], dataset, onDataset, scope, mode = 'learn', activeFile, onOpenStage, onOpenData, onPickWorkflow }) {
    const done = plan.filter(s => s.status === 'executed').length;
    const isRun = mode === 'run';
    const isOrch = mode === 'orchestrate';
    const orchDone = orchestratorPlan.reduce((n, g) => n + g.stages.filter(s => s.status === 'executed').length, 0);
    const orchTotal = orchestratorPlan.reduce((n, g) => n + g.stages.length, 0);
    const [playing, setPlaying] = React.useState(true);
    const dataGroup = (label, icon, group) => {
        const entries = (scope && scope[group]) || [];
        return (
            <div style={{ marginBottom: 'var(--sp1)' }}>
                <HGroup gap="1" onClick={() => onOpenData && onOpenData(group)}
                    title={`Open ${label} in panel`}
                    style={{ padding: '4px 8px', borderRadius: 6, cursor: 'pointer' }}
                    onMouseEnter={e => e.currentTarget.style.background = 'var(--iso-surface-100)'}
                    onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                    <Icon name={icon} size={11} color="var(--p-text-muted-color)" style={{ width: 14 }} />
                    <span style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.04em', color: 'var(--p-text-muted-color)' }}>{label}</span>
                    <Filler />
                    <Icon name="far fa-arrow-up-right-from-square" size={9} color="var(--iso-surface-400)" />
                </HGroup>
                <div style={{ display: 'flex', flexFlow: 'column' }}>
                    {entries.map(e => (
                        <HGroup key={e.key} gap="1" onClick={() => onOpenData && onOpenData(group)}
                            style={{ padding: '2px 8px 2px 22px', fontFamily: 'var(--font-mono)', fontSize: 11, cursor: 'pointer' }}>
                            <span style={{ color: 'var(--iso-primary-color)', flex: '0 0 auto', maxWidth: '50%', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.key}:</span>
                            <span style={{ flex: 1, minWidth: 0, color: 'var(--p-text-muted-color)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{e.preview}</span>
                        </HGroup>
                    ))}
                </div>
            </div>
        );
    };
    return (
        <div style={{ display: 'flex', flexFlow: 'column', height: '100%', background: 'var(--iso-surface-50)', borderRight: '1px solid var(--iso-surface-200)' }}>
            <div style={{ padding: 'var(--sp2) var(--sp2) var(--sp1-5)' }}>
                <HGroup gap="1">
                    <svg width="15" height="15" viewBox="0 0 128 128" fill="none">
                        <path d="M 63.999985,63.999996 14.844273,35.653537 63.999989,7.3070782 113.15569,35.653537 V 92.346454 L 63.999989,120.69292 14.844273,92.346454 V 54.551177 l 49.155716,28.346457 16.38522,-9.448819 V 54.551177 L 47.61475,35.653537 63.999989,26.204718 96.770448,45.102357 V 82.897634 L 63.999989,101.79528 31.229511,82.897634" stroke="var(--iso-primary-color)" strokeWidth="7.2" strokeLinecap="round" strokeLinejoin="round" />
                    </svg>
                    <span style={{ fontWeight: 700 }}>{isRun || isOrch ? 'All workflows' : project.title}</span>
                </HGroup>
                <div style={{ fontSize: 12, color: 'var(--p-text-muted-color)', marginTop: 4 }}>{isOrch ? `chained · ${workflows.length} workflows` : isRun ? `${workflows.length} workflows · talk to any` : project.site}</div>
            </div>
            <h4 style={{ padding: '0 var(--sp2)', margin: '0 0 var(--sp1)' }}>{isOrch ? `Chain · ${orchDone}/${orchTotal} stages` : isRun ? `Tools · ${workflows.length}` : `Stages · ${done}/${plan.length}`}</h4>
            {isOrch ? (
                <div style={{ padding: '0 var(--sp1)', display: 'flex', flexFlow: 'column' }}>
                    {orchestratorPlan.map((g, gi) => (
                        <OrchGroup key={g.workflow} g={g} gi={gi} total={orchestratorPlan.length} activeFile={activeFile} onOpenStage={onOpenStage} />
                    ))}
                </div>
            ) : isRun ? (
                <div style={{ padding: '0 var(--sp1)', display: 'flex', flexFlow: 'column', gap: 2 }}>
                    {workflows.map(w => (
                        <HGroup key={w.name} gap="1" onClick={() => onPickWorkflow && onPickWorkflow(w.name)}
                            title={`Open ${w.name} in Learn mode`}
                            style={{ padding: '7px 10px', borderRadius: 6, cursor: 'pointer' }}
                            onMouseEnter={e => e.currentTarget.style.background = 'var(--iso-surface-100)'}
                            onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                            <Icon name="far fa-diagram-project" size={12} color="var(--iso-primary-color)" />
                            <VGroup gap="0" style={{ flex: 1, minWidth: 0 }}>
                                <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--p-text-color)' }}>{w.name}</span>
                                <span style={{ fontSize: 10.5, color: 'var(--p-text-muted-color)' }}>{w.desc}</span>
                            </VGroup>
                            <Icon name="far fa-screwdriver-wrench" size={10} color="var(--iso-surface-400)" />
                        </HGroup>
                    ))}
                </div>
            ) : (
                <div style={{ padding: '0 var(--sp1)', display: 'flex', flexFlow: 'column', gap: 2 }}>
                    {plan.map(s => {
                        const st = PLAN_STATUS[s.status];
                        const active = s.status === 'executing';
                        const open = activeFile === s.name;
                        return (
                            <HGroup key={s.name} gap="1" onClick={() => onOpenStage && onOpenStage(s.name)}
                                title={`Open ${s.name}.stage.ts`}
                                style={{ padding: '7px 10px', borderRadius: 6, cursor: 'pointer', background: open ? 'var(--iso-primary-50)' : active ? 'var(--iso-surface-0)' : 'transparent', boxShadow: active ? 'var(--shadow-sm)' : 'none' }}
                                onMouseEnter={e => { if (!open && !active) e.currentTarget.style.background = 'var(--iso-surface-100)'; }}
                                onMouseLeave={e => { if (!open && !active) e.currentTarget.style.background = 'transparent'; }}>
                                <Icon name={st.icon} size={13} color={st.color} style={st.spin ? { animation: 'a3-spin .8s linear infinite' } : null} />
                                <span style={{ flex: 1, minWidth: 0, fontFamily: 'var(--font-mono)', fontSize: 12, color: open ? 'var(--iso-primary-color)' : s.status === 'pending' ? 'var(--p-text-muted-color)' : 'var(--p-text-color)', fontWeight: (active || open) ? 600 : 400 }}>{s.name}</span>
                                <Icon name="far fa-file-code" size={10} color="var(--iso-surface-400)" />
                            </HGroup>
                        );
                    })}
                </div>
            )}
            {isRun ? (
                <div style={{ padding: 'var(--sp1-5) var(--sp2) 0' }}>
                    <HGroup gap="1" style={{ paddingTop: 'var(--sp1-5)', borderTop: '1px solid var(--iso-surface-200)', fontSize: 11, color: 'var(--p-text-muted-color)', lineHeight: 1.5 }}>
                        <Icon name="far fa-plug" size={12} color="var(--iso-primary-color)" />
                        <span>Each workflow is exposed to the agent as a tool</span>
                    </HGroup>
                </div>
            ) : (
                <div style={{ padding: 'var(--sp1-5) var(--sp1-5) var(--sp1-5)' }}>
                    <HGroup gap="1" style={{ paddingTop: 'var(--sp1-5)', borderTop: '1px solid var(--iso-surface-200)' }}>
                        <Button icon={playing ? 'far fa-pause' : 'far fa-play'} iconOnly severity="primary" size="small"
                            title={playing ? 'Pause run' : 'Play run'} onClick={() => setPlaying(p => !p)} />
                        <Button label="Match" icon="far fa-location-dot" variant="text" severity="secondary" size="small" title="Match next stage" />
                        <Filler />
                        <Button icon="far fa-stop" iconOnly variant="text" severity="secondary" size="small" title="Stop session" onClick={() => setPlaying(false)} />
                        <Button icon="far fa-rotate-left" iconOnly variant="text" severity="secondary" size="small" title="Reset run" onClick={() => setPlaying(false)} />
                    </HGroup>
                </div>
            )}
            <Filler />
            {scope && !isRun && (
                <div style={{ padding: 'var(--sp1-5) var(--sp1) var(--sp1)', borderTop: '1px solid var(--iso-surface-200)' }}>
                    <h4 style={{ padding: '0 var(--sp1)', margin: '0 0 var(--sp1)' }}>Workflow data</h4>
                    {dataGroup('Inputs', 'far fa-arrow-right-to-bracket', 'inputs')}
                    {dataGroup('Outputs', 'far fa-arrow-right-from-bracket', 'outputs')}
                    {dataGroup('State', 'far fa-code', 'context')}
                </div>
            )}
            <div style={{ padding: 'var(--sp1) var(--sp1-5)', borderTop: '1px solid var(--iso-surface-200)' }}>
                <DatasetMenu datasets={datasets} value={dataset || project.dataset} onChange={onDataset} />
            </div>
        </div>
    );
}

/* Mocked target page — a full DESKTOP emirates.com flow, designed at
   1280×960 (4:3) and scaled to fit. `screen` selects which stage's
   page is shown so the browser tracks the stage being executed. */
function MockSite({ screen = 'blank' }) {
    if (screen === 'blank') {
        return (
            <div style={{ width: 1280, height: 960, background: '#ffffff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'Arial, sans-serif' }}>
                <div style={{ textAlign: 'center' }}>
                    <svg width="120" height="120" viewBox="0 0 128 128" fill="none" style={{ opacity: .55 }}>
                        <path d="M 63.999985,63.999996 14.844273,35.653537 63.999989,7.3070782 113.15569,35.653537 V 92.346454 L 63.999989,120.69292 14.844273,92.346454 V 54.551177 l 49.155716,28.346457 16.38522,-9.448819 V 54.551177 L 47.61475,35.653537 63.999989,26.204718 96.770448,45.102357 V 82.897634 L 63.999989,101.79528 31.229511,82.897634" stroke="#cbd5e1" strokeWidth="7.2" strokeLinecap="round" strokeLinejoin="round" />
                    </svg>
                    <div style={{ fontSize: 30, fontWeight: 700, color: '#94a3b8', marginTop: 28 }}>about:blank</div>
                    <div style={{ fontSize: 19, color: '#cbd5e1', marginTop: 10 }}>A3 will open a page here when a stage runs.</div>
                </div>
            </div>
        );
    }
    const RED = '#d71920', INK = '#1a1a2e', GOLD = '#c8a45c';
    const field = (label, value, focus, w) => (
        <div style={{ marginBottom: 22, width: w || 'auto' }}>
            <div style={{ fontSize: 17, color: '#475569', marginBottom: 8 }}>{label}</div>
            <div style={{ height: 56, borderRadius: 8, padding: '0 18px', display: 'flex', alignItems: 'center', fontSize: 21, color: '#0f172a', background: '#fff', border: focus ? '3px solid #6366f1' : '1px solid #cbd5e1', boxShadow: focus ? '0 0 0 5px rgba(99,102,241,.15)' : 'none' }}>
                {value}{focus && <span style={{ width: 2.5, height: 26, background: '#6366f1', marginLeft: 2, animation: 'a3caret 1s step-end infinite' }} />}
            </div>
        </div>
    );
    // Which numbered step is active for the current screen.
    const STEP_OF = { 'search': 1, 'results': 2, 'passenger-details': 3, 'seat-map': 3, 'payment': 3, 'confirmation': 4 };
    const activeStep = STEP_OF[screen] || 1;
    const step = (n, label) => {
        const state = n < activeStep || (screen === 'confirmation' && n < 4) ? 'done' : n === activeStep ? 'active' : 'pending';
        return (
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                <div style={{ width: 36, height: 36, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 18, fontWeight: 700,
                    background: state === 'done' ? '#16a34a' : state === 'active' ? RED : '#e2e8f0',
                    color: state === 'pending' ? '#94a3b8' : '#fff' }}>{state === 'done' ? '✓' : n}</div>
                <span style={{ fontSize: 18, fontWeight: state === 'active' ? 700 : 400, color: state === 'pending' ? '#94a3b8' : '#0f172a' }}>{label}</span>
            </div>
        );
    };
    const flightSummary = cta => (
        <div style={{ width: 360, flex: '0 0 auto', background: '#fff', border: '1px solid #e2e8f0', borderRadius: 14, padding: 32, height: 'fit-content' }}>
            <div style={{ fontSize: 22, fontWeight: 700, marginBottom: 16 }}>Your flight</div>
            <div style={{ fontSize: 24, fontWeight: 800, marginBottom: 4, color: INK }}>DXB → LHR</div>
            <div style={{ fontSize: 18, color: GOLD, fontWeight: 700, marginBottom: 16 }}>Emirates · EK0007</div>
            <div style={{ fontSize: 19, color: '#475569', lineHeight: 1.8 }}>
                22 Aug 2026 · 07:45 → 12:10<br />Nonstop · 7h 25m<br />Business · 2 passengers
            </div>
            <div style={{ height: 1, background: '#e2e8f0', margin: '20px 0' }} />
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 20, marginBottom: 6 }}><span style={{ color: '#475569' }}>Fare (Flex)</span><span>£806</span></div>
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 20, marginBottom: 16 }}><span style={{ color: '#475569' }}>Taxes</span><span>£36</span></div>
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 24, fontWeight: 800, marginBottom: 22 }}><span>Total</span><span>£842</span></div>
            <div style={{ height: 64, borderRadius: 9, background: RED, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 22, fontWeight: 700 }}>{cta}</div>
        </div>
    );

    let body;
    if (screen === 'search') {
        body = (
            <div style={{ flex: 1, padding: '48px 56px' }}>
                <div style={{ fontSize: 36, fontWeight: 800, marginBottom: 6, color: INK }}>Where would you like to fly?</div>
                <div style={{ fontSize: 20, color: '#64748b', marginBottom: 32 }}>Book flights to over 140 destinations worldwide.</div>
                <div style={{ background: '#fff', border: `1px solid #e2e8f0`, borderRadius: 12, padding: 8, display: 'flex', gap: 8, alignItems: 'stretch', maxWidth: 1040, boxShadow: '0 4px 16px rgba(2,6,23,.06)' }}>
                    <div style={{ flex: 1.2, background: '#fff', borderRadius: 8, border: '3px solid #6366f1', boxShadow: '0 0 0 5px rgba(99,102,241,.15)', padding: '0 18px', display: 'flex', alignItems: 'center', fontSize: 21 }}>DXB · Dubai<span style={{ width: 2.5, height: 26, background: '#6366f1', marginLeft: 2, animation: 'a3caret 1s step-end infinite' }} /></div>
                    <div style={{ flex: 1.2, background: '#f8fafc', borderRadius: 8, padding: '0 18px', display: 'flex', alignItems: 'center', fontSize: 21, color: '#0f172a' }}>LHR · London</div>
                    <div style={{ flex: 1.4, background: '#f8fafc', borderRadius: 8, padding: '0 18px', display: 'flex', alignItems: 'center', fontSize: 19, color: '#0f172a' }}>22 Aug — one way</div>
                    <div style={{ flex: 1, background: '#f8fafc', borderRadius: 8, padding: '0 18px', display: 'flex', alignItems: 'center', fontSize: 19, color: '#0f172a' }}>2 passengers</div>
                    <div style={{ flex: '0 0 auto', background: RED, color: '#fff', borderRadius: 8, padding: '0 34px', display: 'flex', alignItems: 'center', fontSize: 22, fontWeight: 700 }}>Search</div>
                </div>
                <div style={{ marginTop: 40, display: 'flex', gap: 18 }}>
                    {['London', 'New York', 'Singapore'].map(c => (
                        <div key={c} style={{ flex: 1, height: 150, borderRadius: 12, background: 'linear-gradient(135deg,#fee2e2,#fecaca)', display: 'flex', alignItems: 'flex-end', padding: 18, fontSize: 22, fontWeight: 700, color: RED }}>{c}</div>
                    ))}
                </div>
            </div>
        );
    } else if (screen === 'results') {
        const flights = [
            { dep: '07:45', arr: '12:10', dur: '7h 25m', no: 'EK0007', eco: 612, biz: 842, sel: true },
            { dep: '14:30', arr: '19:05', dur: '7h 35m', no: 'EK0001', eco: 588, biz: 798, sel: false },
            { dep: '21:50', arr: '02:20', dur: '7h 30m', no: 'EK0029', eco: 549, biz: 776, sel: false },
        ];
        body = (
            <div style={{ flex: 1, padding: '32px 56px', overflow: 'hidden' }}>
                <div style={{ fontSize: 24, fontWeight: 700, marginBottom: 4, color: INK }}>DXB → LHR · 18 flights found</div>
                <div style={{ fontSize: 18, color: '#64748b', marginBottom: 24 }}>22 Aug 2026 · 2 passengers · nonstop on Emirates</div>
                <div style={{ display: 'flex', flexFlow: 'column', gap: 16 }}>
                    {flights.map(f => (
                        <div key={f.no} style={{ display: 'flex', gap: 20, alignItems: 'center', background: '#fff', border: f.sel ? `3px solid ${RED}` : '1px solid #e2e8f0', borderRadius: 12, padding: 20 }}>
                            <div style={{ flex: 1 }}>
                                <div style={{ display: 'flex', alignItems: 'center', gap: 18 }}>
                                    <div style={{ fontSize: 28, fontWeight: 800, color: INK }}>{f.dep}</div>
                                    <div style={{ flex: '0 0 120px', textAlign: 'center', color: '#94a3b8', fontSize: 15 }}>──── ✈ ────<br />{f.dur}</div>
                                    <div style={{ fontSize: 28, fontWeight: 800, color: INK }}>{f.arr}</div>
                                </div>
                                <div style={{ fontSize: 16, color: '#64748b', marginTop: 8 }}>Emirates {f.no} · DXB → LHR · Nonstop</div>
                            </div>
                            <div style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
                                <div style={{ textAlign: 'right' }}>
                                    <div style={{ fontSize: 14, color: '#64748b' }}>Economy</div>
                                    <div style={{ fontSize: 22, fontWeight: 700 }}>£{f.eco}</div>
                                </div>
                                <div style={{ textAlign: 'right', borderLeft: `3px solid ${GOLD}`, paddingLeft: 14 }}>
                                    <div style={{ fontSize: 14, color: GOLD, fontWeight: 700 }}>Business</div>
                                    <div style={{ fontSize: 22, fontWeight: 800 }}>£{f.biz}</div>
                                </div>
                                <div style={{ marginLeft: 8, background: f.sel ? RED : '#fff', color: f.sel ? '#fff' : RED, border: `2px solid ${RED}`, borderRadius: 7, padding: '10px 22px', fontSize: 17, fontWeight: 700 }}>{f.sel ? 'Selected' : 'Select'}</div>
                            </div>
                        </div>
                    ))}
                </div>
            </div>
        );
    } else if (screen === 'seat-map') {
        const rows = [19, 20, 21, 22, 23, 24, 25];
        const cols = ['A', 'B', 'C', 'D', 'F', 'G', 'H', 'K'];
        body = (
            <div style={{ flex: 1, display: 'flex', gap: 40, padding: '36px 56px' }}>
                <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 34, fontWeight: 700, marginBottom: 6, color: INK }}>Choose your seat</div>
                    <div style={{ fontSize: 19, color: '#64748b', marginBottom: 28 }}>Business cabin · Boeing 777-300ER</div>
                    <div style={{ background: '#fff', border: '1px solid #e2e8f0', borderRadius: 16, padding: '28px 36px', display: 'inline-block' }}>
                        <div style={{ display: 'flex', gap: 10, marginBottom: 14, paddingLeft: 44 }}>
                            {cols.map((c, i) => (
                                <React.Fragment key={c}>
                                    <div style={{ width: 44, textAlign: 'center', fontSize: 16, color: '#94a3b8', fontWeight: 700 }}>{c}</div>
                                    {i === 2 || i === 4 ? <div style={{ width: 24 }} /> : null}
                                </React.Fragment>
                            ))}
                        </div>
                        {rows.map(r => (
                            <div key={r} style={{ display: 'flex', gap: 10, marginBottom: 10, alignItems: 'center' }}>
                                <div style={{ width: 34, fontSize: 15, color: '#94a3b8', fontWeight: 700 }}>{r}</div>
                                {cols.map((c, i) => {
                                    const seat = `${r}${c}`;
                                    const sel = seat === '23A';
                                    const taken = ['20F', '21B', '24G', '19K'].includes(seat);
                                    return (
                                        <React.Fragment key={c}>
                                            <div style={{ width: 44, height: 44, borderRadius: 8, fontSize: 12, display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700,
                                                background: sel ? RED : taken ? '#e2e8f0' : '#fff',
                                                color: sel ? '#fff' : taken ? '#cbd5e1' : GOLD,
                                                border: sel ? `2px solid ${RED}` : taken ? '1px solid #e2e8f0' : `1px solid ${GOLD}` }}>{sel ? '23A' : taken ? '✕' : ''}</div>
                                            {i === 2 || i === 4 ? <div style={{ width: 24 }} /> : null}
                                        </React.Fragment>
                                    );
                                })}
                            </div>
                        ))}
                        <div style={{ marginTop: 16, fontSize: 15, color: '#475569' }}>Selected: <b style={{ color: RED }}>23A</b> · window</div>
                    </div>
                </div>
                {flightSummary('Confirm seat')}
            </div>
        );
    } else if (screen === 'payment') {
        body = (
            <div style={{ flex: 1, display: 'flex', gap: 40, padding: '48px 56px' }}>
                <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 34, fontWeight: 700, marginBottom: 6, color: INK }}>Payment details</div>
                    <div style={{ fontSize: 19, color: '#64748b', marginBottom: 36 }}>Secure checkout — your booking is held for 20 minutes.</div>
                    {field('Cardholder name', 'Layla Al-Rashid', false, 460)}
                    {field('Card number', '4242 4242 4242 4242', true, 460)}
                    <div style={{ display: 'flex', gap: 24 }}>
                        {field('Expiry', '07 / 28', false, 200)}
                        {field('CVC', '•••', false, 200)}
                    </div>
                </div>
                {flightSummary('Pay £842')}
            </div>
        );
    } else if (screen === 'confirmation') {
        body = (
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '48px 56px' }}>
                <div style={{ width: 640, background: '#fff', border: '1px solid #e2e8f0', borderRadius: 16, overflow: 'hidden', boxShadow: '0 10px 30px rgba(2,6,23,.12)' }}>
                    <div style={{ background: RED, color: '#fff', padding: '24px 32px', display: 'flex', alignItems: 'center', gap: 14 }}>
                        <span style={{ fontSize: 22, fontWeight: 700 }}>Booking confirmed ✓</span>
                        <div style={{ flex: 1 }} />
                        <span style={{ fontSize: 16, color: '#fff', fontWeight: 700, background: 'rgba(255,255,255,.2)', padding: '4px 12px', borderRadius: 999 }}>e-Ticket</span>
                    </div>
                    <div style={{ padding: 32 }}>
                        <div style={{ display: 'flex', alignItems: 'baseline', gap: 16, marginBottom: 4 }}>
                            <div style={{ fontSize: 30, fontWeight: 800, color: INK }}>DXB → LHR</div>
                            <div style={{ fontSize: 18, color: GOLD, fontWeight: 700 }}>Emirates EK0007</div>
                        </div>
                        <div style={{ color: '#64748b', fontSize: 18, marginBottom: 24 }}>L. AL-RASHID · 22 Aug 2026 · 07:45 → 12:10</div>
                        <div style={{ display: 'flex', gap: 48, marginBottom: 24 }}>
                            <div><div style={{ fontSize: 14, color: '#64748b' }}>Booking ref</div><div style={{ fontSize: 22, fontWeight: 700 }}>EK-5530</div></div>
                            <div><div style={{ fontSize: 14, color: '#64748b' }}>Cabin</div><div style={{ fontSize: 22, fontWeight: 700 }}>Business · Flex</div></div>
                            <div><div style={{ fontSize: 14, color: '#64748b' }}>Seat</div><div style={{ fontSize: 22, fontWeight: 700 }}>23A</div></div>
                            <div><div style={{ fontSize: 14, color: '#64748b' }}>Total</div><div style={{ fontSize: 22, fontWeight: 700 }}>£842</div></div>
                        </div>
                        <div style={{ display: 'flex', gap: 48 }}>
                            <div><div style={{ fontSize: 14, color: '#64748b' }}>Passenger</div><div style={{ fontSize: 22, fontWeight: 700 }}>Layla Al-Rashid</div></div>
                            <div><div style={{ fontSize: 14, color: '#64748b' }}>Skywards</div><div style={{ fontSize: 22, fontWeight: 700 }}>4471 9920 1183</div></div>
                            <div><div style={{ fontSize: 14, color: '#64748b' }}>Party</div><div style={{ fontSize: 22, fontWeight: 700 }}>2 passengers</div></div>
                        </div>
                    </div>
                </div>
            </div>
        );
    } else {
        // passenger-details (default)
        body = (
            <div style={{ flex: 1, display: 'flex', gap: 40, padding: '48px 56px' }}>
                <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 34, fontWeight: 700, marginBottom: 6, color: INK }}>Passenger details</div>
                    <div style={{ fontSize: 19, color: '#64748b', marginBottom: 36 }}>Lead passenger · who's travelling</div>
                    <div style={{ display: 'flex', gap: 24 }}>
                        {field('Title', 'Ms', false, 200)}
                        <div style={{ flex: 1 }}>{field('First name', 'Layla', true)}</div>
                    </div>
                    {field('Last name', 'Al-Rashid', false)}
                    <div style={{ display: 'flex', gap: 24 }}>
                        <div style={{ flex: 1 }}>{field('Date of birth', '12 Mar 1990', false)}</div>
                        <div style={{ flex: 1 }}>{field('Skywards number', '4471 9920 1183', false)}</div>
                    </div>
                </div>
                {flightSummary('Continue')}
            </div>
        );
    }
    return (
        <div style={{ width: 1280, height: 960, background: '#f1f5f9', color: '#0f172a', fontFamily: 'Arial, sans-serif', display: 'flex', flexFlow: 'column' }}>
            {/* top nav */}
            <div style={{ height: 72, background: RED, display: 'flex', alignItems: 'center', padding: '0 44px', gap: 18, flex: '0 0 auto' }}>
                <span style={{ color: '#fff', fontWeight: 800, fontSize: 26, letterSpacing: '-.01em' }}>Emirates</span>
                <div style={{ flex: 1 }} />
                {['Book', 'Manage', 'Check-in', 'Help'].map((t, i) => (
                    <span key={t} style={{ color: '#fff', fontSize: 18, fontWeight: i === 0 ? 700 : 400, opacity: i === 0 ? 1 : 0.8, borderBottom: i === 0 ? `3px solid ${GOLD}` : 'none', paddingBottom: 4 }}>{t}</span>
                ))}
            </div>
            {/* stepper */}
            <div style={{ height: 92, background: '#fff', borderBottom: '1px solid #e2e8f0', display: 'flex', alignItems: 'center', gap: 48, padding: '0 56px', flex: '0 0 auto' }}>
                {step(1, 'Search')}
                <div style={{ flex: 1, height: 2, background: '#e2e8f0' }} />
                {step(2, 'Fares')}
                <div style={{ flex: 1, height: 2, background: '#e2e8f0' }} />
                {step(3, 'Passenger')}
                <div style={{ flex: 1, height: 2, background: '#e2e8f0' }} />
                {step(4, 'Confirm')}
            </div>
            {body}
        </div>
    );
}

/* Scales the 1280×960 desktop page to whatever width the 4:3 frame gets. */
function BrowserViewport({ screen }) {
    const ref = React.useRef(null);
    const [scale, setScale] = React.useState(0.275);
    React.useEffect(() => {
        const el = ref.current;
        if (!el) return;
        const update = () => setScale(el.clientWidth / 1280);
        update();
        const ro = new ResizeObserver(update);
        ro.observe(el);
        return () => ro.disconnect();
    }, []);
    return (
        <div ref={ref} style={{ width: '100%', aspectRatio: '4 / 3', overflow: 'hidden', background: '#f1f5f9' }}>
            <div style={{ width: 1280, height: 960, transformOrigin: 'top left', transform: `scale(${scale})` }}>
                <MockSite screen={screen} />
            </div>
        </div>
    );
}

/* Lightweight syntax highlight for the file editor. */
function hlLine(line) {
    const re = /(\/\/.*$)|('[^']*')|\b(import|from|export|default|class|extends|async|await|const|let|return|new|this|true|false)\b/g;
    const out = []; let last = 0, m, k = 0;
    while ((m = re.exec(line))) {
        if (m.index > last) out.push(<span key={k++}>{line.slice(last, m.index)}</span>);
        const color = m[1] ? 'var(--p-text-muted-color)' : m[2] ? 'var(--p-green-600)' : 'var(--iso-primary-600)';
        out.push(<span key={k++} style={{ color }}>{m[0]}</span>);
        last = m.index + m[0].length;
    }
    if (last < line.length) out.push(<span key={k++}>{line.slice(last)}</span>);
    return out;
}

/* Inline markdown — **bold** and `code`. */
function mdInline(text) {
    const parts = text.split(/(\*\*[^*]+\*\*|`[^`]+`)/g);
    return parts.map((p, i) => {
        if (p.startsWith('**')) return <strong key={i}>{p.slice(2, -2)}</strong>;
        if (p.startsWith('`')) return <code key={i} style={{ fontFamily: 'var(--font-mono)', fontSize: '.92em', color: 'var(--iso-primary-600)', background: 'var(--iso-surface-100)', padding: '1px 5px', borderRadius: 4 }}>{p.slice(1, -1)}</code>;
        return <React.Fragment key={i}>{p}</React.Fragment>;
    });
}
function MarkdownLine({ ln }) {
    if (ln.trim() === '') return <div style={{ height: 10 }} />;
    if (ln.startsWith('## ')) return <div style={{ fontSize: 14, fontWeight: 700, margin: '14px 0 4px' }}>{mdInline(ln.slice(3))}</div>;
    if (ln.startsWith('# ')) return <div style={{ fontSize: 18, fontWeight: 700, margin: '2px 0 8px' }}>{mdInline(ln.slice(2))}</div>;
    if (ln.startsWith('> ')) return <div style={{ borderLeft: '3px solid var(--iso-primary-300)', paddingLeft: 12, color: 'var(--p-text-muted-color)', fontStyle: 'italic', margin: '4px 0' }}>{mdInline(ln.slice(2))}</div>;
    const li = ln.match(/^(\s*)(\d+\.|-)\s+(.*)$/);
    if (li) return (
        <div style={{ display: 'flex', gap: 8, paddingLeft: 8 + li[1].length * 6, margin: '2px 0' }}>
            <span style={{ color: 'var(--iso-primary-color)', flex: '0 0 auto', fontVariantNumeric: 'tabular-nums' }}>{li[2] === '-' ? '•' : li[2]}</span>
            <span>{mdInline(li[3])}</span>
        </div>
    );
    return <div style={{ margin: '3px 0' }}>{mdInline(ln)}</div>;
}

/* Interactive (no-diff) code/markdown editor for a config or stage file. */
function FileEditor({ name, lines }) {
    const [activeLine, setActiveLine] = React.useState(null);
    const isMd = /\.md$/.test(name);
    const [mdView, setMdView] = React.useState('preview');
    const lang = isMd ? 'Markdown' : /\.(ts|tsx)$/.test(name) ? 'TypeScript' : 'Text';
    const showRaw = !isMd || mdView === 'raw';
    const codeView = (
        <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: '10px 0', fontFamily: 'var(--font-mono)', fontSize: 12.5, lineHeight: '20px' }}>
            {lines.map((ln, i) => (
                <div key={i} onClick={() => setActiveLine(i)}
                    style={{ display: 'flex', minHeight: 20, background: activeLine === i ? 'var(--iso-primary-50)' : 'transparent', cursor: 'text' }}>
                    <span style={{ width: 44, flex: '0 0 auto', textAlign: 'right', paddingRight: 14, color: activeLine === i ? 'var(--iso-primary-color)' : 'var(--iso-surface-300)', userSelect: 'none' }}>{i + 1}</span>
                    <span style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>
                        {isMd ? ln : hlLine(ln)}
                        {activeLine === i && <span style={{ display: 'inline-block', width: 2, height: 15, background: 'var(--iso-primary-color)', verticalAlign: 'text-bottom', animation: 'a3caret 1s step-end infinite' }} />}
                    </span>
                </div>
            ))}
        </div>
    );
    const seg = (val, label, icon) => (
        <HGroup gap="0-5" onClick={() => setMdView(val)}
            style={{ padding: '3px 10px', borderRadius: 'var(--radius-md)', cursor: 'pointer', fontSize: 12,
                background: mdView === val ? 'var(--iso-surface-0)' : 'transparent',
                boxShadow: mdView === val ? 'var(--shadow-sm)' : 'none',
                color: mdView === val ? 'var(--p-text-color)' : 'var(--p-text-muted-color)', fontWeight: mdView === val ? 600 : 400 }}>
            <Icon name={icon} size={11} color={mdView === val ? 'var(--iso-primary-color)' : 'var(--p-text-muted-color)'} /> {label}
        </HGroup>
    );
    return (
        <div style={{ display: 'flex', flexFlow: 'column', height: '100%', minHeight: 0, background: 'var(--iso-surface-0)' }}>
            {isMd && (
                <HGroup gap="0-5" style={{ flex: '0 0 auto', padding: 'var(--sp1) var(--sp1-5)', borderBottom: '1px solid var(--iso-surface-200)' }}>
                    <Filler />
                    <HGroup gap="0" style={{ padding: 2, borderRadius: 'var(--radius-md)', background: 'var(--iso-surface-100)' }}>
                        {seg('preview', 'Preview', 'far fa-eye')}
                        {seg('raw', 'Raw', 'far fa-code')}
                    </HGroup>
                </HGroup>
            )}
            {showRaw ? codeView : (
                <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: '18px 22px', fontSize: 14, lineHeight: 1.6, color: 'var(--p-text-color)', maxWidth: 720 }}>
                    {lines.map((ln, i) => <MarkdownLine key={i} ln={ln} />)}
                </div>
            )}
            <div style={{ flex: '0 0 auto', padding: 'var(--sp1) var(--sp1-5)', borderTop: '1px solid var(--iso-surface-200)', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--p-text-muted-color)', display: 'flex', gap: 12 }}>
                <span>{name}</span><span>{lang}</span><span>{lines.length} lines</span>
            </div>
        </div>
    );
}

/* Inputs / Outputs / State viewer. */
/* ── JSON tree viewer ── color-coded, click a row to expand/collapse. */
function jsonValColor(v) {
    if (typeof v === 'string') return 'var(--p-green-600)';
    if (typeof v === 'number') return 'var(--p-yellow-700)';
    if (typeof v === 'boolean' || v === null) return 'var(--iso-primary-600)';
    return 'var(--p-text-color)';
}
function jsonFmt(v) {
    if (typeof v === 'string') return `"${v}"`;
    if (v === null) return 'null';
    return String(v);
}
function JsonNode({ keyName, value, depth }) {
    const isObj = value !== null && typeof value === 'object';
    const [open, setOpen] = React.useState(depth < 2);
    const pad = 8 + depth * 14;
    if (!isObj) {
        return (
            <div style={{ display: 'flex', paddingLeft: pad, lineHeight: '21px', whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>
                <span style={{ width: 14, flex: '0 0 auto' }} />
                {keyName != null && <span style={{ color: 'var(--iso-primary-color)' }}>{keyName}:&nbsp;</span>}
                <span style={{ color: jsonValColor(value) }}>{jsonFmt(value)}</span>
            </div>
        );
    }
    const arr = Array.isArray(value);
    const entries = arr ? value.map((v, i) => [i, v]) : Object.entries(value);
    const openCh = arr ? '[' : '{', closeCh = arr ? ']' : '}';
    return (
        <div>
            <div onClick={() => setOpen(o => !o)} style={{ display: 'flex', alignItems: 'center', paddingLeft: pad, lineHeight: '21px', cursor: 'pointer' }}>
                <span style={{ width: 14, flex: '0 0 auto', color: 'var(--p-text-muted-color)' }}>
                    <Icon name="fas fa-caret-right" size={11} style={{ transform: open ? 'rotate(90deg)' : 'none', transition: 'transform .12s' }} />
                </span>
                {keyName != null && <span style={{ color: 'var(--iso-primary-color)' }}>{keyName}:&nbsp;</span>}
                <span style={{ color: 'var(--p-text-muted-color)' }}>
                    {openCh}{!open && <span style={{ opacity: .75 }}> {arr ? `${entries.length} items` : `${entries.length} keys`} {closeCh}</span>}
                </span>
            </div>
            {open && <>
                {entries.map(([k, v]) => <JsonNode key={k} keyName={arr ? null : k} value={v} depth={depth + 1} />)}
                <div style={{ paddingLeft: pad + 14, color: 'var(--p-text-muted-color)', lineHeight: '21px' }}>{closeCh}</div>
            </>}
        </div>
    );
}

/* Inputs / Outputs / State viewer — full JSON tree. */
function DataView({ group, data }) {
    const obj = (data && data[group]) || {};
    const blurb = { inputs: 'Values passed into the workflow run.', outputs: 'Values the workflow produces.', context: 'Live session & browser state.' }[group];
    return (
        <div style={{ display: 'flex', flexFlow: 'column', height: '100%', minHeight: 0, background: 'var(--iso-surface-0)' }}>
            <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: 'var(--sp1-5)' }}>
                <div style={{ fontSize: 12, color: 'var(--p-text-muted-color)', marginBottom: 'var(--sp1-5)' }}>{blurb}</div>
                <div style={{ border: '1px solid var(--iso-surface-200)', borderRadius: 'var(--radius-md)', padding: '10px 6px', fontFamily: 'var(--font-mono)', fontSize: 12.5 }}>
                    <JsonNode keyName={null} value={obj} depth={0} />
                </div>
            </div>
        </div>
    );
}

/* Browser tab content — the scaled live frame + url. */
function BrowserView({ screen = 'blank' }) {
    const URL_OF = {
        'blank': 'about:blank',
        'search': 'emirates.com', 'results': 'emirates.com/book/select',
        'passenger-details': 'emirates.com/book/passengers', 'seat-map': 'emirates.com/book/seats',
        'payment': 'emirates.com/book/payment', 'confirmation': 'emirates.com/book/confirmation',
    };
    return (
        <div style={{ display: 'flex', flexFlow: 'column', height: '100%', minHeight: 0, background: 'var(--iso-surface-0)' }}>
            <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: 'var(--sp1-5)' }}>
                <div style={{ border: '2px solid var(--iso-primary-color)', borderRadius: 'var(--radius-md)', overflow: 'hidden', boxShadow: '0 0 8px color-mix(in srgb, var(--iso-primary-color) 35%, transparent)' }}>
                    <BrowserViewport screen={screen} />
                </div>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--p-text-muted-color)', padding: '6px 2px 0' }}>
                    {URL_OF[screen] || 'about:blank'}
                </div>
            </div>
        </div>
    );
}

/* Right dock — content only; its tabs live in the top bar. */
function RightDock({ activeTab, screen, openFile, openData, scopeData }) {
    return (
        <div style={{ display: 'flex', flexFlow: 'column', height: '100%', minHeight: 0, background: 'var(--iso-surface-0)', borderLeft: '1px solid var(--iso-surface-200)' }}>
            <div style={{ flex: 1, minHeight: 0 }}>
                {activeTab === 'browser' && <BrowserView screen={screen} />}
                {activeTab === 'file' && openFile && <FileEditor name={openFile.name} lines={openFile.lines} />}
                {activeTab === 'data' && openData && <DataView group={openData} data={scopeData} />}
            </div>
        </div>
    );
}

/* Project-config mode left pane — the project source tree. */
function ConfigNode({ node, depth, activeFile, onOpen }) {
    const [open, setOpen] = React.useState(true);
    if (node.type === 'folder') {
        return (
            <div>
                <HGroup gap="1" onClick={() => setOpen(o => !o)}
                    style={{ padding: '5px 8px', paddingLeft: 8 + depth * 12, borderRadius: 6, cursor: 'pointer' }}>
                    <Icon name="fas fa-chevron-right" size={9} color="var(--p-text-muted-color)" style={{ width: 10, transform: open ? 'rotate(90deg)' : 'none', transition: 'transform .12s' }} />
                    <Icon name={open ? 'far fa-folder-open' : 'far fa-folder'} size={12} color="var(--p-text-muted-color)" />
                    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--p-text-muted-color)' }}>{node.name}</span>
                </HGroup>
                {open && node.children.map(c => <ConfigNode key={c.name} node={c} depth={depth + 1} activeFile={activeFile} onOpen={onOpen} />)}
            </div>
        );
    }
    const active = activeFile === node.path;
    return (
        <HGroup gap="1" onClick={() => onOpen(node.path)}
            title={`Open ${node.name}`}
            style={{ padding: '5px 8px', paddingLeft: 8 + depth * 12 + 12, borderRadius: 6, cursor: 'pointer', background: active ? 'var(--iso-primary-50)' : 'transparent' }}
            onMouseEnter={e => { if (!active) e.currentTarget.style.background = 'var(--iso-surface-100)'; }}
            onMouseLeave={e => { if (!active) e.currentTarget.style.background = 'transparent'; }}>
            <Icon name="far fa-file-code" size={11} color={active ? 'var(--iso-primary-color)' : 'var(--iso-surface-400)'} style={{ width: 14 }} />
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: active ? 'var(--iso-primary-color)' : 'var(--p-text-color)', fontWeight: active ? 600 : 400, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{node.name}</span>
        </HGroup>
    );
}

function ConfigTree({ project, tree, activeFile, onOpen }) {
    return (
        <div style={{ display: 'flex', flexFlow: 'column', height: '100%', background: 'var(--iso-surface-50)', borderRight: '1px solid var(--iso-surface-200)' }}>
            <div style={{ padding: 'var(--sp2) var(--sp2) var(--sp1-5)' }}>
                <HGroup gap="1">
                    <svg width="15" height="15" viewBox="0 0 128 128" fill="none">
                        <path d="M 63.999985,63.999996 14.844273,35.653537 63.999989,7.3070782 113.15569,35.653537 V 92.346454 L 63.999989,120.69292 14.844273,92.346454 V 54.551177 l 49.155716,28.346457 16.38522,-9.448819 V 54.551177 L 47.61475,35.653537 63.999989,26.204718 96.770448,45.102357 V 82.897634 L 63.999989,101.79528 31.229511,82.897634" stroke="var(--iso-primary-color)" strokeWidth="7.2" strokeLinecap="round" strokeLinejoin="round" />
                    </svg>
                    <span style={{ fontWeight: 700 }}>{project.dataset ? 'flight-booking' : project.title}</span>
                </HGroup>
                <div style={{ fontSize: 12, color: 'var(--p-text-muted-color)', marginTop: 4 }}>project sources</div>
            </div>
            <h4 style={{ padding: '0 var(--sp2)', margin: '0 0 var(--sp1)' }}>Files</h4>
            <div style={{ flex: 1, minHeight: 0, overflow: 'auto', padding: '0 var(--sp1)' }}>
                {tree.length === 0
                    ? <VGroup align="center" gap="1" style={{ padding: 'var(--sp4) var(--sp2)', textAlign: 'center' }}>
                        <Icon name="far fa-folder-open" size={22} color="var(--iso-surface-400)" />
                        <span style={{ fontSize: 12.5, color: 'var(--p-text-muted-color)', lineHeight: 1.5 }}>No files yet — describe your project in the chat and A3 will write the missions, workflows and schemas here.</span>
                    </VGroup>
                    : tree.map(n => <ConfigNode key={n.name} node={n} depth={0} activeFile={activeFile} onOpen={onOpen} />)}
            </div>
        </div>
    );
}

window.A3Chat = Object.assign(window.A3Chat || {}, { PlanRail, RightDock, ConfigTree });
