// Flow view — input → processing → output for any sub-workflow
const { DG: FDG, DG70: FDG70, DG60: FDG60, DG50: FDG50, DG10: FDG10, DG06: FDG06, MINT: FMINT, BGMINT: FBGMINT, BGLIGHT: FBGLIGHT, SPINE: FSPINE } = window;

// ─────────────────────── MARKDOWN RENDERER ───────────────────────
// Minimal markdown → React. Supports: # headings, **bold**, *italic*, lists, tables, ---
const InlineMD = ({ text }) => {
  // Render bold/italic/inline-code
  const parts = [];
  let rest = text;
  let key = 0;
  const regex = /(\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g;
  let last = 0;
  let m;
  while ((m = regex.exec(text)) !== null) {
    if (m.index > last) parts.push(text.slice(last, m.index));
    const tok = m[0];
    if (tok.startsWith('**')) parts.push(<strong key={key++} style={{color:FDG, fontWeight:600}}>{tok.slice(2,-2)}</strong>);
    else if (tok.startsWith('*')) parts.push(<em key={key++}>{tok.slice(1,-1)}</em>);
    else if (tok.startsWith('`')) parts.push(<code key={key++} style={{fontFamily:'ui-monospace, Menlo, monospace', fontSize:'0.9em', background:FBGLIGHT, padding:'1px 5px', borderRadius:4, color:FDG}}>{tok.slice(1,-1)}</code>);
    last = m.index + tok.length;
  }
  if (last < text.length) parts.push(text.slice(last));
  return <>{parts}</>;
};

const Markdown = ({ source }) => {
  const lines = source.split('\n');
  const blocks = [];
  let i = 0;
  let key = 0;
  while (i < lines.length) {
    const line = lines[i];
    // HR
    if (/^---+$/.test(line.trim())) {
      blocks.push(<hr key={key++} style={{border:'none', borderTop:`1px solid ${FDG10}`, margin:'18px 0'}}/>);
      i++; continue;
    }
    // Heading
    const h = line.match(/^(#{1,6})\s+(.+)$/);
    if (h) {
      const lvl = h[1].length;
      const size = [22, 18, 15.5, 14, 13, 12.5][lvl-1];
      const mt = lvl === 3 ? 18 : lvl === 4 ? 14 : 10;
      blocks.push(<div key={key++} style={{fontSize:size, fontWeight:600, color:FDG, marginTop:mt, marginBottom:8, letterSpacing: lvl<=2 ? '-0.01em' : 0}}><InlineMD text={h[2]}/></div>);
      i++; continue;
    }
    // Table
    if (line.includes('|') && i+1 < lines.length && /^\s*\|?[\s\-:|]+\|?\s*$/.test(lines[i+1])) {
      const header = line.split('|').map(s => s.trim()).filter(Boolean);
      i += 2;
      const rows = [];
      while (i < lines.length && lines[i].includes('|')) {
        rows.push(lines[i].split('|').map(s => s.trim()).filter((_,idx,arr) => !(idx===0 && arr[0]==='') && !(idx===arr.length-1 && arr[arr.length-1]==='')));
        i++;
      }
      blocks.push(
        <div key={key++} style={{margin:'12px 0', border:`1px solid ${FDG10}`, borderRadius:8, overflow:'hidden'}}>
          <table style={{width:'100%', borderCollapse:'collapse', fontSize:12.5}}>
            <thead><tr style={{background:FBGLIGHT}}>
              {header.map((h,j) => <th key={j} style={{textAlign:'left', padding:'9px 12px', fontWeight:600, color:FDG, borderBottom:`1px solid ${FDG10}`, fontSize:12}}>{h}</th>)}
            </tr></thead>
            <tbody>
              {rows.map((r, ri) => (
                <tr key={ri} style={{borderBottom: ri < rows.length-1 ? `1px solid ${FDG10}` : 'none'}}>
                  {r.map((c, ci) => <td key={ci} style={{padding:'9px 12px', color:FDG70, verticalAlign:'top', lineHeight:1.5}}><InlineMD text={c}/></td>)}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
      continue;
    }
    // Numbered list
    if (/^\d+\.\s/.test(line)) {
      const items = [];
      while (i < lines.length && /^\d+\.\s/.test(lines[i])) {
        items.push(lines[i].replace(/^\d+\.\s/, ''));
        i++;
      }
      blocks.push(
        <ol key={key++} style={{margin:'8px 0 8px 22px', padding:0, display:'flex', flexDirection:'column', gap:5, color:FDG70, fontSize:13.5, lineHeight:1.6}}>
          {items.map((it, j) => <li key={j}><InlineMD text={it}/></li>)}
        </ol>
      );
      continue;
    }
    // Bullet list
    if (/^[-•]\s/.test(line)) {
      const items = [];
      while (i < lines.length && /^[-•]\s/.test(lines[i])) {
        items.push(lines[i].replace(/^[-•]\s/, ''));
        i++;
      }
      blocks.push(
        <ul key={key++} style={{margin:'8px 0 8px 20px', padding:0, display:'flex', flexDirection:'column', gap:5, color:FDG70, fontSize:13.5, lineHeight:1.6, listStyle:'disc'}}>
          {items.map((it, j) => <li key={j}><InlineMD text={it}/></li>)}
        </ul>
      );
      continue;
    }
    // Blank
    if (line.trim() === '') { i++; continue; }
    // Paragraph
    const paraLines = [];
    while (i < lines.length && lines[i].trim() !== '' && !/^(#|---|\d+\.\s|[-•]\s)/.test(lines[i]) && !(lines[i].includes('|') && i+1<lines.length && /^\s*\|?[\s\-:|]+\|?\s*$/.test(lines[i+1]))) {
      paraLines.push(lines[i]);
      i++;
    }
    blocks.push(<p key={key++} style={{margin:'8px 0', color:FDG70, fontSize:13.5, lineHeight:1.65}}><InlineMD text={paraLines.join(' ')}/></p>);
  }
  return <>{blocks}</>;
};

// ─────────────────────── PROCESSING ANIMATION ───────────────────────
const ProcessingSteps = ({ steps, speedMs = 1 }) => {
  const [done, setDone] = React.useState(0);
  React.useEffect(() => {
    let cancelled = false;
    const run = async () => {
      for (let i = 0; i < steps.length; i++) {
        await new Promise(r => setTimeout(r, (steps[i].dur || 800) * speedMs));
        if (cancelled) return;
        setDone(i + 1);
      }
    };
    run();
    return () => { cancelled = true; };
  }, [steps]);

  return (
    <div style={{display:'flex', flexDirection:'column', gap:10}}>
      {steps.map((s, i) => {
        const isDone = i < done;
        const isActive = i === done;
        return (
          <div key={i} style={{display:'flex', alignItems:'center', gap:12, padding:'11px 14px', background: isActive ? 'rgba(3,168,120,0.06)' : isDone ? '#fff' : FBGLIGHT, border:`1px solid ${isActive ? FSPINE : FDG10}`, borderRadius:10, transition:'all 0.25s'}}>
            <div style={{width:22, height:22, borderRadius:9999, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0, background: isDone ? FSPINE : isActive ? '#fff' : 'transparent', border: isDone ? 'none' : `1.5px solid ${isActive ? FSPINE : FDG10}`}}>
              {isDone ? <span style={{color:'#fff'}}>{window.Ic.Check(13)}</span> : isActive ? <span className="hy-spin" style={{width:11, height:11, border:`1.5px solid rgba(3,168,120,0.3)`, borderTopColor:FSPINE, borderRadius:9999, display:'inline-block'}}/> : <span style={{width:5, height:5, borderRadius:9999, background:FDG50, display:'inline-block'}}/>}
            </div>
            <span style={{fontSize:13, color: isDone ? FDG70 : isActive ? FDG : FDG50, fontWeight: isActive ? 500 : 400, flex:1}}>{s.label}</span>
            {isDone && <span style={{fontSize:11, color:FSPINE, fontFamily:'ui-monospace, Menlo, monospace'}}>✓ {(s.dur/1000).toFixed(1)}s</span>}
          </div>
        );
      })}
    </div>
  );
};

// ─────────────────────── INPUT PANELS ───────────────────────

// Reusable CTA card for generate buttons — used by all assistants
const GenerateCTA = ({ title, description, buttonLabel, onGenerate, meta }) => (
  <div className="hy-cta" style={{position:'relative', overflow:'hidden', background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:12, padding:'14px 16px', boxShadow:'0 1px 2px rgba(3,61,46,0.04)'}}>
    <style>{`
      html.is-mobile .hy-cta-inner{flex-direction:column!important;align-items:stretch!important;gap:12px!important}
      html.is-mobile .hy-cta-icon{display:none!important}
      html.is-mobile .hy-cta-btn{width:100%!important;justify-content:center!important}
      html.is-mobile .hy-cta-text{flex:1 1 auto!important}
    `}</style>
    <div style={{position:'absolute', top:-60, right:-40, width:200, height:200, borderRadius:'50%', background:`radial-gradient(circle at 40% 40%, rgba(119,222,186,0.3) 0%, rgba(79,187,158,0.08) 55%, rgba(3,168,120,0) 75%)`, filter:'blur(20px)', pointerEvents:'none'}}/>
    <div className="hy-cta-inner" style={{position:'relative', display:'flex', alignItems:'center', gap:16, flexWrap:'wrap'}}>
      <div className="hy-cta-icon" style={{width:48, height:48, borderRadius:12, background:`linear-gradient(135deg, ${FMINT} 0%, ${FSPINE} 100%)`, color:'#fff', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0, boxShadow:'0 2px 8px rgba(3,168,120,0.2)'}}>
        {window.Ic.Sparkles(22)}
      </div>
      <div className="hy-cta-text" style={{flex:'1 1 200px', minWidth:0}}>
        <div style={{fontSize:15, fontWeight:600, color:FDG, letterSpacing:'-0.005em', marginBottom:3}}>{title}</div>
        <div style={{fontSize:12.5, color:FDG70, lineHeight:1.5}}>{description}</div>
        {meta && <div style={{fontSize:11.5, color:FDG60, marginTop:6, display:'flex', alignItems:'center', gap:8, flexWrap:'wrap'}}>{meta}</div>}
      </div>
      <button className="hy-cta-btn" onClick={onGenerate} style={{
        background:'linear-gradient(90deg,#4fbb9e 0%,#03a878 100%)', color:'#fff', border:'none',
        padding:'12px 18px', borderRadius:10, fontSize:13.5, fontWeight:600, cursor:'pointer',
        fontFamily:'inherit', display:'inline-flex', alignItems:'center', gap:8, minHeight:44,
        boxShadow:'0 2px 8px rgba(3,168,120,0.2)', flexShrink:0
      }}>
        {window.Ic.Sparkles(14)} {buttonLabel}
      </button>
    </div>
  </div>
);

// Scribe: preparation summary card on top, audio recorder full-width, manual notes full-width, CTA at bottom
const ScribeInputPanel = ({ input, onGenerate }) => {
  const [recording, setRecording] = React.useState(false);
  const [elapsed, setElapsed] = React.useState(0);
  const [showPrep, setShowPrep] = React.useState(true);
  React.useEffect(() => {
    if (!recording) return;
    const iv = setInterval(() => setElapsed(e => e + 1), 100);
    return () => clearInterval(iv);
  }, [recording]);

  return (
    <div style={{display:'flex', flexDirection:'column', gap:10}}>
      <window.PatientStrip patient={input.patient}/>

      {/* Preparation summary card — links Scribe to Preparation assistant */}
      <div style={{position:'relative', overflow:'hidden', background:`linear-gradient(135deg, #f0faf5 0%, #e8f4ed 100%)`, border:`1px solid rgba(119,222,186,0.32)`, borderRadius:12, padding:'12px 14px', boxShadow:'0 1px 2px rgba(3,61,46,0.04)'}}>
        <div style={{position:'relative', display:'flex', alignItems:'flex-start', gap:12}}>
          <div style={{width:40, height:40, borderRadius:10, background:'#fff', color:FDG, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0, boxShadow:'0 1px 4px rgba(3,61,46,0.06)'}}>
            {window.Ic.ClipboardList(20)}
          </div>
          <div style={{flex:1, minWidth:0}}>
            <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:4}}>
              <div style={{fontSize:10.5, color:FDG50, fontWeight:600, letterSpacing:'0.06em', textTransform:'uppercase'}}>Hysio Preparation · 02.02</div>
              <div style={{fontSize:10, padding:'2px 7px', borderRadius:9999, background:FSPINE, color:'#fff', fontWeight:600}}>KLAAR</div>
            </div>
            <div style={{fontSize:14, color:FDG, fontWeight:600, marginBottom:2, letterSpacing:'-0.005em'}}>Intake-voorbereiding beschikbaar</div>
            <div style={{fontSize:12.5, color:FDG70, lineHeight:1.55}}>
              Werkhypothese: <strong style={{color:FDG}}>chronische distale patellatendinopathie L</strong>. Kern-anamnese ingezet op keten-limiters (enkel-DF, glut med) en VISA-P baseline. 3 DD overwogen, 2 red flags negatief.
            </div>
            <button onClick={() => setShowPrep(s => !s)} style={{marginTop:8, background:'none', border:'none', color:FSPINE, cursor:'pointer', fontFamily:'inherit', fontSize:12, fontWeight:500, padding:0, display:'inline-flex', alignItems:'center', gap:4}}>
              {showPrep ? 'Verberg samenvatting' : 'Toon samenvatting'} {showPrep ? '↑' : '↓'}
            </button>
            {showPrep && (
              <div style={{marginTop:10, padding:'12px 14px', background:'rgba(255,255,255,0.7)', border:`1px solid ${FDG10}`, borderRadius:10, fontSize:12.5, color:FDG70, lineHeight:1.6}}>
                <div style={{marginBottom:6}}><strong style={{color:FDG}}>Focus vandaag:</strong> VISA-P hertest, SLS decline squat, ankle DF knee-to-wall, glut med Ekstrand.</div>
                <div><strong style={{color:FDG}}>Aandachtspunten:</strong> progressie naar HSR stage 3 · instep schieten nog 2 weken vermijden · verwachting managen (hersteltijd 3-6 mnd conform richtlijn).</div>
              </div>
            )}
          </div>
        </div>
      </div>

      {/* Audio recorder — full width */}
      <div style={{background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:12, padding:'14px 16px', boxShadow:'0 1px 2px rgba(3,61,46,0.04)'}}>
        <window.SectionLabel icon={window.Ic.Mic(12)}>Spraak-naar-Tekst</window.SectionLabel>
        <div style={{display:'flex', alignItems:'center', gap:12, padding:'10px 12px', background:FBGLIGHT, border:`1px solid ${FDG10}`, borderRadius:10}}>
          <button onClick={() => setRecording(r => !r)} style={{
            width:44, height:44, borderRadius:9999, border:'none', cursor:'pointer',
            background: recording ? '#dc2626' : 'linear-gradient(135deg,#4fbb9e 0%,#03a878 100%)',
            color:'#fff', display:'flex', alignItems:'center', justifyContent:'center',
            boxShadow: recording ? '0 0 0 5px rgba(220,38,38,0.15)' : '0 2px 8px rgba(3,168,120,0.25)',
            transition:'all 0.2s', flexShrink:0
          }}>
            {recording ? <span style={{width:14, height:14, background:'#fff', borderRadius:3}}/> : window.Ic.Mic(20)}
          </button>
          <div className="hy-wave" style={{display:'flex', alignItems:'center', gap:2, height:36, flex:1, minWidth:0, overflow:'hidden'}}>
            <style>{`html.is-mobile .hy-wave{display:none!important}`}</style>
            {Array.from({length:48}).map((_, i) => {
              const h = recording ? 4 + Math.abs(Math.sin((Date.now()/200 + i*0.4))) * 28 : 4 + (i%3)*2;
              return <div key={i} style={{width:2, height: h, borderRadius:2, background: recording ? FSPINE : FDG10, transition:'height 0.1s', flexShrink:0}}/>;
            })}
          </div>
          <div style={{fontSize:12, color: recording ? FDG : FDG70, minWidth:0, textAlign:'right', flexShrink:1, lineHeight:1.3}}>
            {recording ? <>
              <div style={{fontWeight:600, display:'flex', alignItems:'center', gap:6, justifyContent:'flex-end'}}>
                <span className="hy-pulse" style={{width:7, height:7, borderRadius:9999, background:'#dc2626', display:'inline-block'}}/>
                Hysio luistert mee…
              </div>
              <div style={{fontFamily:'ui-monospace, Menlo, monospace', color:FDG60, fontSize:11.5, marginTop:2}}>{Math.floor(elapsed/600)}:{String(Math.floor(elapsed/10)%60).padStart(2,'0')}</div>
            </> : <>{input.audioLabel}</>}
          </div>
        </div>
      </div>

      {/* Manual notes — full width */}
      <div style={{background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:12, padding:'14px 16px', boxShadow:'0 1px 2px rgba(3,61,46,0.04)'}}>
        <window.SectionLabel icon={window.Ic.Pencil(12)}>Handmatige notities (optioneel)</window.SectionLabel>
        <textarea defaultValue={input.manualNotes} style={{width:'100%', minHeight:110, fontSize:13, color:FDG, padding:'14px 16px', background:FBGLIGHT, border:`1px solid ${FDG10}`, borderRadius:10, fontFamily:'inherit', outline:'none', resize:'vertical', lineHeight:1.6, boxSizing:'border-box'}}/>
        <div style={{marginTop:8, fontSize:11.5, color:FDG60}}>Notities worden geïntegreerd in het eindverslag.</div>
      </div>

      {/* Generate CTA card */}
      <GenerateCTA
        title="Klaar om te genereren?"
        description="Hysio verwerkt je audio-opname, handmatige notities én de voorbereiding tot één gestructureerd SOEP-verslag. Je blijft eindverantwoordelijk — lees de output altijd na en pas aan waar nodig."
        buttonLabel="Genereer SOEP-verslag"
        onGenerate={onGenerate}
      />
    </div>
  );
};

// RawText: single big textarea (preparation, smartmail, mentor, edupack, intervention, diagnosecode)
const RawTextInputPanel = ({ input, onGenerate, ctaLabel = 'Genereer', ctaTitle, ctaDescription, ctaMeta }) => (
  <div style={{display:'flex', flexDirection:'column', gap:16}}>
    <window.PatientStrip patient={input.patient}/>
    <div style={{background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:12, padding:14}}>
      <window.SectionLabel icon={window.Ic.Pencil(12)}>Invoer</window.SectionLabel>
      <textarea defaultValue={input.rawText} placeholder={input.placeholder} style={{width:'100%', minHeight:140, fontSize:13, color:FDG, padding:'14px 16px', background:FBGLIGHT, border:`1px solid ${FDG10}`, borderRadius:10, fontFamily:'inherit', outline:'none', resize:'vertical', lineHeight:1.55, boxSizing:'border-box'}}/>
    </div>
    <GenerateCTA
      title={ctaTitle || 'Klaar om te genereren?'}
      description={ctaDescription || 'Hysio zet je invoer om in een gestructureerd document. Je blijft eindverantwoordelijk — lees de output altijd na en pas aan waar nodig.'}
      buttonLabel={ctaLabel}
      onGenerate={onGenerate}
      meta={ctaMeta}
    />
  </div>
);

// Document: preview a doc + generate
const DocumentInputPanel = ({ input, onGenerate, ctaLabel = 'Analyseer & vat samen', ctaTitle, ctaDescription }) => (
  <div style={{display:'flex', flexDirection:'column', gap:16}}>
    <window.PatientStrip patient={input.patient}/>
    <div style={{background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:12, padding:14}}>
      <window.SectionLabel icon={window.Ic.FileText(12)}>Aangeleverd document</window.SectionLabel>
      <div style={{border:`1px solid ${FDG10}`, borderRadius:10, overflow:'hidden'}}>
        <div style={{padding:'10px 14px', background:FBGLIGHT, borderBottom:`1px solid ${FDG10}`, display:'flex', justifyContent:'space-between', alignItems:'center'}}>
          <div style={{fontSize:12.5, color:FDG, fontWeight:500}}>{input.document.title}</div>
          <div style={{fontSize:11, color:FDG60}}>{input.document.date}</div>
        </div>
        <div style={{padding:'18px 22px', fontSize:12.5, color:FDG70, lineHeight:1.65, whiteSpace:'pre-wrap', maxHeight:320, overflow:'auto', fontFamily:'Georgia, serif'}}>{input.document.preview}</div>
      </div>
    </div>
    <GenerateCTA
      title={ctaTitle || 'Klaar om te analyseren?'}
      description={ctaDescription || 'Hysio leest het document en haalt het klinisch relevante eruit: diagnose, beleid, vraagstelling en red flags in een beknopte samenvatting.'}
      buttonLabel={ctaLabel}
      onGenerate={onGenerate}
    />
  </div>
);

// ─────────────────────── OUTPUT PANELS ───────────────────────

// Generic "document" shell wrapping markdown
const DocumentOutput = ({ output }) => (
  <div style={{background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:14, overflow:'hidden'}}>
    <div style={{padding:'12px 20px', background:FBGLIGHT, borderBottom:`1px solid ${FDG10}`, display:'flex', justifyContent:'space-between', alignItems:'center'}}>
      <div style={{fontSize:12, color:FDG60}}>{output.title}</div>
      <div style={{display:'flex', gap:6}}>
        <window.Chip>📋 Kopieer</window.Chip>
        <window.Chip>📄 Export</window.Chip>
        <window.Chip tone="active">💾 Opslaan in EPD</window.Chip>
      </div>
    </div>
    <div style={{padding:'16px 20px'}}>
      <Markdown source={output.markdown}/>
    </div>
  </div>
);

// Letter output
const LetterOutput = ({ output }) => {
  const l = output.letter;
  return (
    <div style={{background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:14, overflow:'hidden'}}>
      <div style={{padding:'12px 20px', background:FBGLIGHT, borderBottom:`1px solid ${FDG10}`, display:'flex', justifyContent:'space-between', alignItems:'center'}}>
        <div style={{fontSize:12, color:FDG60}}>Concept-brief</div>
        <div style={{display:'flex', gap:6}}>
          <window.Chip>📋 Kopieer</window.Chip><window.Chip>📄 Export PDF</window.Chip><window.Chip tone="active">✉ Verstuur</window.Chip>
        </div>
      </div>
      <div style={{padding:'20px 22px', fontFamily:'Georgia, "Times New Roman", serif', color:FDG, lineHeight:1.65, fontSize:13}}>
        <div style={{whiteSpace:'pre-wrap', color:FDG70, fontSize:12, marginBottom:16}}>{l.to}</div>
        <div style={{fontWeight:600, marginBottom:14}}>Betreft: {l.subject}</div>
        <div style={{marginBottom:12}}>{l.greeting}</div>
        <div style={{marginBottom:16}}>
          <Markdown source={l.body}/>
        </div>
        <div style={{whiteSpace:'pre-wrap', fontSize:12, borderTop:`1px solid ${FDG10}`, paddingTop:12}}>{l.closing}</div>
      </div>
    </div>
  );
};

// Mentor: markdown answer + sources block
const MentorOutput = ({ output }) => (
  <div style={{display:'flex', flexDirection:'column', gap:12}}>
    <div style={{display:'flex', gap:10, alignItems:'flex-start'}}>
      <div style={{width:38, height:38, borderRadius:10, background:`linear-gradient(135deg,${FMINT} 0%,${FSPINE} 100%)`, color:'#fff', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0}}>{window.Ic.GraduationCap(19)}</div>
      <div style={{flex:1, background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:'4px 12px 12px 12px', padding:'14px 16px'}}>
        <Markdown source={output.markdown}/>
      </div>
    </div>
    <div style={{padding:'16px 20px', background:'#fff', border:`1px dashed ${FMINT}`, borderRadius:12, marginLeft:48}}>
      <div style={{fontSize:11, fontWeight:600, color:FDG60, textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:10}}>Onderbouwd met</div>
      <div style={{display:'flex', flexDirection:'column', gap:7}}>
        {output.sources.map((s, i) => (
          <div key={i} style={{fontSize:12.5, color:FDG70, display:'flex', gap:8, alignItems:'baseline'}}>
            <span style={{fontFamily:'ui-monospace, Menlo, monospace', color:FSPINE, fontWeight:600, fontSize:11}}>[{i+1}]</span>
            <span><strong style={{color:FDG}}>{s.title}</strong> — {s.section}</span>
          </div>
        ))}
      </div>
    </div>
  </div>
);

// EduPack: patient info sheet with warm styling
const EduPackOutput = ({ output }) => (
  <div style={{background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:14, overflow:'hidden'}}>
    <div style={{padding:'14px 22px', background:FBGMINT, borderBottom:`1px solid ${FDG10}`, display:'flex', justifyContent:'space-between', alignItems:'center'}}>
      <div style={{display:'flex', alignItems:'center', gap:12}}>
        <img src="assets/hysio-logo-full-color.svg" style={{height:18}}/>
        <span style={{fontSize:12, color:FDG60}}>Patiënt-informatie · B1 leesniveau</span>
      </div>
      <div style={{display:'flex', gap:6}}>
        <window.Chip tone="active">✓ B1 gevalideerd</window.Chip>
        <window.Chip>📄 PDF</window.Chip>
      </div>
    </div>
    <div style={{padding:'18px 22px'}}>
      <h2 style={{fontSize:18, color:FDG, margin:'0 0 12px 0', fontWeight:600, letterSpacing:'-0.01em', lineHeight:1.2}}>{output.headline}</h2>
      <Markdown source={output.markdown}/>
    </div>
  </div>
);

// Codes: DCSPH ranked list + summary markdown
const CodesOutput = ({ output }) => (
  <div style={{display:'flex', flexDirection:'column', gap:14}}>
    <div style={{display:'flex', flexDirection:'column', gap:10}}>
      {output.codes.map((c, i) => (
        <div key={i} style={{background:'#fff', border:`${c.recommended ? 2 : 1}px solid ${c.recommended ? FDG : FDG10}`, borderRadius:12, padding:'16px 20px', position:'relative', overflow:'hidden'}}>
          {c.recommended && <div style={{position:'absolute', top:12, right:12, background:FSPINE, color:'#fff', fontSize:10, fontWeight:700, padding:'3px 10px', borderRadius:9999, textTransform:'uppercase', letterSpacing:'0.05em'}}>Aanbevolen</div>}
          <div style={{display:'flex', alignItems:'baseline', gap:14, marginBottom:10}}>
            <span style={{fontSize:24, fontWeight:700, color:FDG, fontFamily:'ui-monospace, Menlo, monospace'}}>{c.code}</span>
            <span style={{fontSize:14, color:FDG}}>{c.label}</span>
            <span style={{marginLeft:'auto', marginRight: c.recommended ? 110 : 0, fontSize:12, color:FDG60}}>Match <strong style={{color: c.match > 80 ? FSPINE : FDG, fontSize:13.5}}>{c.match}%</strong></span>
          </div>
          <div style={{width:'100%', height:5, background:FDG06, borderRadius:9999, marginBottom:12, overflow:'hidden'}}>
            <div style={{width:`${c.match}%`, height:'100%', background: c.match > 80 ? FSPINE : c.match > 50 ? FDG50 : FDG10, borderRadius:9999, transition:'width 0.8s'}}/>
          </div>
          <div style={{fontSize:12.5, color:FDG70, lineHeight:1.6}}>{c.reasoning}</div>
        </div>
      ))}
    </div>
    <div style={{background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:12, padding:'14px 16px'}}>
      <window.SectionLabel icon={window.Ic.Shield(12)}>Onderbouwing en advies</window.SectionLabel>
      <Markdown source={output.summary}/>
    </div>
  </div>
);

const OutputByFormat = ({ output }) => {
  if (output.format === 'markdown') return <DocumentOutput output={output}/>;
  if (output.format === 'letter') return <LetterOutput output={output}/>;
  if (output.format === 'mentor') return <MentorOutput output={output}/>;
  if (output.format === 'edupack') return <EduPackOutput output={output}/>;
  if (output.format === 'codes') return <CodesOutput output={output}/>;
  return <div>Output format niet herkend: {output.format}</div>;
};

// ─────────────────────── MAIN FLOW ───────────────────────

const AssistantFlow = ({ assistant, sub, speed = 1, onPickSub }) => {
  const [phase, setPhase] = React.useState('input');

  const start = () => {
    setPhase('processing');
    const total = sub.processing.reduce((s, p) => s + (p.dur || 800), 0) * speed;
    setTimeout(() => setPhase('output'), total + 300);
  };

  const reset = () => setPhase('input');

  React.useEffect(() => { setPhase('input'); }, [sub.id]);

  // Auto-scroll to sheet top when the user triggers a phase transition,
  // so long outputs don't leave them stranded at page bottom.
  React.useEffect(() => {
    if (phase === 'input') return;
    const el = document.querySelector('.hysio-demo-sheet');
    if (!el) return;
    const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    try { el.scrollIntoView({ behavior: reduce ? 'auto' : 'smooth', block: 'start' }); } catch {}
  }, [phase]);

  // CTA copy per assistant
  const ctaCopyFor = (aid) => ({
    preparation: { label: 'Genereer voorbereiding', title: 'Klaar om voor te bereiden?', description: 'Hysio analyseert je casus, raadpleegt de KNGF-richtlijn en maakt een gerichte intake-voorbereiding met werkhypothese, DD, kern-anamnese en aanbevolen tests.' },
    smartmail: { label: 'Genereer brief', title: 'Klaar om de brief te genereren?', description: 'Hysio bouwt een professionele, BIG-conforme brief met collegiale toon. Onderbouwing, privacy-check en ondertekening zijn automatisch meegenomen.' },
    summary: { label: 'Analyseer & vat samen', title: 'Klaar om te analyseren?', description: 'Hysio leest het document en haalt het klinisch relevante eruit: diagnose, beleid, vraagstelling en red flags in een beknopte samenvatting.' },
    mentor: { label: 'Vraag aan mentor', title: 'Klaar om te sparren?', description: 'Hysio redeneert mee op basis van de KNGF-richtlijn en de actuele evidence. Je krijgt onderbouwde adviezen met bronvermelding — geen gladgestreken antwoorden.' },
    edupack: { label: 'Genereer EduPack', title: 'Klaar om de uitleg te maken?', description: 'Hysio vertaalt jouw boodschap naar B1-taal, afgestemd op de patiënt. Medische termen worden uitgelegd, de toon blijft persoonlijk en concreet.' },
    intervention: { label: 'Genereer programma', title: 'Klaar om het programma te bouwen?', description: 'Hysio stelt een sessie samen op basis van fase, doelen en keten-limiters: oefenselectie, dosering, tempo en monitoring — direct klaar voor de oefenzaal.' },
    diagnosecode: { label: 'Zoek DCSPH-codes', title: 'Klaar om te coderen?', description: 'Hysio doorzoekt de DCSPH-database en stelt de top 3 meest passende codes voor, met onderbouwing en alternatieven. Jij blijft eindverantwoordelijk voor de definitieve keuze.' },
  })[aid] || { label: 'Genereer', title: 'Klaar om te genereren?', description: 'Hysio zet je invoer om in een gestructureerd document.' };

  const cta = ctaCopyFor(assistant.id);

  let InputPanel;
  if (sub.inputType === 'scribe') InputPanel = <ScribeInputPanel input={sub.input} onGenerate={start}/>;
  else if (sub.inputType === 'rawtext') InputPanel = <RawTextInputPanel input={sub.input} onGenerate={start} ctaLabel={cta.label} ctaTitle={cta.title} ctaDescription={cta.description}/>;
  else if (sub.inputType === 'document') InputPanel = <DocumentInputPanel input={sub.input} onGenerate={start} ctaLabel={cta.label} ctaTitle={cta.title} ctaDescription={cta.description}/>;
  else InputPanel = (
    <div style={{padding:'30px 20px', textAlign:'center', color:FDG60, background:'#fff', border:`1px dashed ${FDG10}`, borderRadius:12}}>
      Deze sub-workflow is nog niet uitgewerkt in deze demo. <br/>
      <a onClick={() => onPickSub(assistant.sub.find(s => s.processing).id)} style={{color:FSPINE, cursor:'pointer', fontWeight:500}}>Terug naar hoofd-workflow →</a>
    </div>
  );

  return (
    <div>
      {/* Assistant header — compact */}
      <div style={{display:'flex', alignItems:'center', gap:12, padding:'2px 4px 12px', borderBottom:'1px solid rgba(119,222,186,0.28)', marginBottom:12}}>
        {window.IllustrationFor
          ? <window.IllustrationFor slug={assistant.slug || assistant.id} size={40}/>
          : <div style={{width:40, height:40, borderRadius:10, background:FBGMINT, color:FDG, display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0}}>{window.Ic[assistant.icon](22)}</div>}
        <div style={{flex:1, minWidth:0}}>
          <div style={{display:'flex', alignItems:'baseline', gap:8}}>
            <span style={{fontSize:10, color:FDG50, fontWeight:600, letterSpacing:'0.06em', fontFamily:'ui-monospace, Menlo, monospace'}}>{assistant.num}</span>
            <h3 style={{fontSize:16, fontWeight:700, color:FDG, margin:0, letterSpacing:'-0.01em', lineHeight:1.2}}>{assistant.name}</h3>
          </div>
          <p style={{fontSize:12, color:FDG70, margin:'2px 0 0', lineHeight:1.3}}>{assistant.tagline}</p>
        </div>
      </div>

      {/* Sub-workflow chip-scroller — horizontal, handles SmartMail's 8 subs without overflow */}
      {assistant.sub.length > 1 && (
        <div style={{marginBottom:10}}>
          <style>{`.hy-sub-row::-webkit-scrollbar{display:none}.hy-sub-row{scrollbar-width:none}`}</style>
          <div className="hy-sub-row" style={{display:'flex', gap:6, padding:'2px 2px 4px', overflowX:'auto', scrollSnapType:'x mandatory', WebkitOverflowScrolling:'touch'}}>
            {assistant.sub.map(s => {
              const active = s.id === sub.id;
              const demo = !!s.processing;
              return (
                <button key={s.id} onClick={() => demo && onPickSub(s.id)} disabled={!demo} style={{
                  fontFamily:'inherit', fontSize:12, padding:'0 12px', height:32, borderRadius:9999,
                  border: `1px solid ${active ? FDG : 'rgba(119,222,186,0.32)'}`,
                  cursor: demo ? 'pointer' : 'not-allowed',
                  background: active ? FDG : '#fff', color: active ? '#fff' : demo ? FDG70 : FDG50,
                  fontWeight: active ? 600 : 500, display:'inline-flex', alignItems:'center', gap:6,
                  opacity: demo ? 1 : 0.7, scrollSnapAlign:'start', flexShrink:0, whiteSpace:'nowrap',
                  transition:'background-color 200ms ease, color 200ms ease, border-color 200ms ease'
                }}>
                  <span style={{fontSize:10, opacity:0.7, fontFamily:'ui-monospace, Menlo, monospace'}}>{s.code}</span>
                  <span>{s.name}</span>
                  {!demo && <span style={{fontSize:9, opacity:0.6, fontStyle:'italic'}}>· web-app</span>}
                </button>
              );
            })}
          </div>
        </div>
      )}

      {/* Phase stepper — slim inline row, no card */}
      <div style={{display:'flex', alignItems:'center', gap:6, padding:'4px 2px 12px', flexWrap:'wrap', marginBottom:4}}>
        {['input', 'processing', 'output'].map((p, i) => {
          const labels = { input: 'Invoer', processing: 'Verwerken', output: 'Resultaat' };
          const order = { input: 0, processing: 1, output: 2 };
          const pi = order[phase];
          const active = p === phase, done = i < pi;
          return (
            <React.Fragment key={p}>
              <div style={{display:'inline-flex', alignItems:'center', gap:6, padding:'4px 10px', borderRadius:9999, background: active ? FDG : done ? FBGMINT : 'transparent', color: active ? '#fff' : FDG70, border: active ? 'none' : `1px solid ${FDG10}`, fontSize:11.5, fontWeight: active ? 600 : 500}}>
                <span style={{width:16, height:16, borderRadius:9999, background: active ? FMINT : done ? FSPINE : FDG10, color: active || done ? '#fff' : FDG50, display:'flex', alignItems:'center', justifyContent:'center', fontSize:9.5, fontWeight:700}}>{done ? '✓' : i+1}</span>
                {labels[p]}
              </div>
              {i < 2 && <div style={{width:14, height:1, background:FDG10}}/>}
            </React.Fragment>
          );
        })}
        <div style={{flex:1}}/>
        {phase === 'output' && <window.GhostButton onClick={reset} icon={window.Ic.Refresh(13)}>Opnieuw</window.GhostButton>}
      </div>

      {/* Phase content — animated via .hy-phase keyframe for fluid transitions */}
      {phase === 'input' && <div key={`in-${sub.id}`} className="hy-phase">{InputPanel}</div>}
      {phase === 'processing' && sub.input && (
        <div key={`pr-${sub.id}`} className="hy-phase">
          <window.PatientStrip patient={sub.input.patient}/>
          <div style={{marginTop:10, background:'#fff', border:`1px solid rgba(119,222,186,0.32)`, borderRadius:12, padding:14, boxShadow:'0 1px 2px rgba(3,61,46,0.04)'}}>
            <window.SectionLabel icon={window.Ic.Sparkles(12)}>Hysio verwerkt je invoer</window.SectionLabel>
            <ProcessingSteps steps={sub.processing} speedMs={speed}/>
          </div>
        </div>
      )}
      {phase === 'output' && sub.output && (
        <div key={`ou-${sub.id}`} className="hy-phase">
          <window.PatientStrip patient={sub.input.patient}/>
          <div style={{marginTop:10, marginBottom:10, background:'#fff', border:`1px solid ${FDG10}`, borderRadius:10, padding:'8px 12px', display:'flex', alignItems:'center', gap:10, flexWrap:'wrap'}}>
            <span style={{display:'inline-flex', alignItems:'center', gap:6, fontSize:11.5, color:FSPINE, fontWeight:600, padding:'3px 9px', background:'rgba(3,168,120,0.08)', borderRadius:9999}}>
              {window.Ic.Check(12)} Gegenereerd
            </span>
            {sub.output.stats && Object.entries(sub.output.stats).map(([k,v]) => (
              <span key={k} style={{fontSize:11, color:FDG60}}>{k}: <strong style={{color:FDG, fontFamily:'ui-monospace, Menlo, monospace'}}>{v}</strong></span>
            ))}
            <div style={{flex:1}}/>
            <window.GhostButton icon={window.Ic.Copy(13)}>Kopieer</window.GhostButton>
            <window.GhostButton icon={window.Ic.Download(13)}>Export</window.GhostButton>
          </div>
          <OutputByFormat output={sub.output}/>
          <div style={{marginTop:12, padding:'10px 14px', background:'rgba(255,255,255,0.5)', border:`1px solid ${FDG10}`, borderRadius:10, display:'flex', alignItems:'center', gap:10, fontSize:11.5, color:FDG70, lineHeight:1.4}}>
            <span style={{color:FSPINE, flexShrink:0}}>{window.Ic.Shield(14)}</span>
            <span><strong style={{color:FDG}}>Jij bent eindverantwoordelijk.</strong> Lees de output altijd na en pas aan waar nodig.</span>
          </div>
        </div>
      )}
    </div>
  );
};

window.AssistantFlow = AssistantFlow;
