// chat-extra-1.jsx — Chat components A–F
// A: Multimodal input, B: Thinking blocks, C: Tool cards,
// D: Multi-agent, E: Error recovery, F: Message actions

// ── Helper: chat layout wrapper ──
function ChatLayout({ dark, children, rightPanel, title = 'Refactor auth middleware', composerProps }) {
  const t = dark ? G.d : G.l;
  return (
    <AppShell dark={dark} active="chat" sidebar={chatSidebar(dark)}
      topBar={<AppTopBar dark={dark} breadcrumbs={['Chat', title]}
        right={<><Tag variant="outline"><Icon name="dot" size={11}/> Live</Tag><Button variant="ghost" size="sm" icon={<Icon name="moreH" size={14}/>} /></>} />}
    >
      <div style={{ height: '100%', display: 'flex' }}>
        <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column' }}>
          <div className="gh-scroll" style={{ flex: 1, overflow: 'auto', padding: '24px 0 16px' }}>
            {/* Edge-to-edge column. Assistant messages cap their inner width
                via maxWidth on the row, so long content stays readable while
                user bubbles flex-end to the actual right edge of the chat
                pane (not to a centered 760px column). */}
            <div style={{ padding: '0 32px', display: 'flex', flexDirection: 'column', gap: 22 }}>
              {children}
            </div>
          </div>
          {composerProps !== false && <Composer dark={dark} {...(composerProps || {})} />}
        </div>
        {rightPanel}
      </div>
    </AppShell>
  );
}

function UserMsg({ dark, children }) {
  const t = dark ? G.d : G.l;
  return (
    <div style={{ alignSelf: 'flex-end', maxWidth: '80%' }}>
      <div style={{ background: t.surface2, padding: '12px 16px', borderRadius: 18, fontSize: 14, lineHeight: 1.5 }}>{children}</div>
    </div>
  );
}

function AssistantMsg({ dark, children }) {
  const t = dark ? G.d : G.l;
  return (
    <div style={{ display: 'flex', gap: 12, maxWidth: 780 }}>
      <GhastLogo size={26} color={t.fg} style={{ flexShrink: 0, marginTop: 2 }} />
      <div style={{ flex: 1, fontSize: 14, lineHeight: 1.6, minWidth: 0 }}>{children}</div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════
// A · MULTIMODAL INPUT
// ═════════════════════════════════════════════════════════════

// Composer with rich attachments
function ComposerMultimodal({ dark, variant = 'mixed' }) {
  const t = dark ? G.d : G.l;

  const attachments = {
    empty: [],
    image: [{ type: 'image', name: 'screenshot.png', preview: true }],
    mixed: [
      { type: 'image', name: 'mockup.png', preview: true },
      { type: 'pdf', name: 'PRD-v3.pdf', meta: '24 pages' },
      { type: 'code', name: 'auth.ts', meta: 'TypeScript · 412 lines' },
      { type: 'audio', name: 'meeting-notes.m4a', meta: '4:32' },
      { type: 'file', name: 'dataset.csv', meta: '2.1 MB' },
    ],
    dragging: [],
    uploading: [{ type: 'image', name: 'photo.jpg', progress: 70 }],
    recording: [],
    transcribing: [],
  };

  const atts = attachments[variant] || [];
  const isDrag = variant === 'dragging';
  const isRecording = variant === 'recording';
  const isTranscribing = variant === 'transcribing';

  const typeIcons = { image: 'image', pdf: 'file', code: 'code', audio: 'sound', video: 'play', file: 'paperclip' };

  return (
    <ChatLayout dark={dark} title="New thread" composerProps={false}>
      <div style={{ flex: 1 }} />
      {/* Full composer area */}
      <div style={{ padding: '0 24px 20px', position: 'relative' }}>
        {/* Drag overlay */}
        {isDrag && (
          <div style={{
            position: 'absolute', inset: 0, zIndex: 10,
            background: dark ? 'rgba(40,40,40,0.85)' : 'rgba(255,255,255,0.85)',
            border: `2px dashed ${t.fg3}`, borderRadius: 20,
            display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 8,
          }}>
            <Icon name="download" size={32} color={t.fg2} />
            <div style={{ fontSize: 15, fontWeight: 600 }}>Drop files here</div>
            <div style={{ fontSize: 12, color: t.fg3 }}>Images, PDFs, code, audio, video — anything.</div>
          </div>
        )}

        <Glass radius={20} dark={dark} style={{ background: 'transparent' }}>
          <div style={{ padding: '14px 14px 10px', display: 'flex', flexDirection: 'column', gap: 10 }}>
            {/* Attachment area */}
            {atts.length > 0 && (
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                {atts.map((a, i) => {
                  if (a.type === 'image') {
                    return (
                      <div key={i} style={{
                        width: 72, height: 72, borderRadius: 10, overflow: 'hidden', position: 'relative',
                        background: t.surface2, border: `1px solid ${t.border}`,
                      }}>
                        <ImgPlaceholder label="IMG" height={72} style={{ borderRadius: 0, border: 'none' }} />
                        {a.progress !== undefined && (
                          <div style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
                            <div style={{ fontSize: 14, fontWeight: 600, color: '#fff' }}>{a.progress}%</div>
                            <div style={{ width: 48, height: 3, background: 'rgba(255,255,255,0.3)', borderRadius: 2, marginTop: 4 }}>
                              <div style={{ width: `${a.progress}%`, height: '100%', background: '#fff', borderRadius: 2 }} />
                            </div>
                          </div>
                        )}
                        <button style={{ position: 'absolute', top: 4, right: 4, width: 18, height: 18, borderRadius: 9, background: 'rgba(0,0,0,0.6)', border: 'none', color: '#fff', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                          <Icon name="close" size={10} color="#fff" />
                        </button>
                      </div>
                    );
                  }
                  return (
                    <div key={i} style={{
                      padding: '8px 12px', borderRadius: 10, display: 'flex', alignItems: 'center', gap: 8,
                      background: t.surface, border: `1px solid ${t.border}`, maxWidth: 200,
                    }}>
                      <div style={{ width: 28, height: 28, borderRadius: 7, background: t.surface2, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                        <Icon name={typeIcons[a.type]} size={14} color={t.fg2} />
                      </div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 12, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{a.name}</div>
                        {a.meta && <div style={{ fontSize: 10, color: t.fg3 }}>{a.meta}</div>}
                      </div>
                      <button style={{ background: 'transparent', border: 'none', color: t.fg3, cursor: 'pointer', padding: 2 }}>
                        <Icon name="close" size={11} />
                      </button>
                    </div>
                  );
                })}
              </div>
            )}

            {/* Recording state */}
            {isRecording && (
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 4px' }}>
                <div style={{ width: 10, height: 10, borderRadius: 5, background: '#ff5f57', animation: 'gh-pulse 1s infinite' }} />
                <span style={{ fontSize: 14, fontWeight: 500 }}>Recording…</span>
                <span style={{ fontFamily: G.mono, fontSize: 13, color: t.fg2 }}>0:14</span>
                <div style={{ flex: 1 }} />
                {/* Waveform bars */}
                <div style={{ display: 'flex', gap: 2, alignItems: 'center', height: 24 }}>
                  {Array.from({ length: 20 }, (_, i) => (
                    <div key={i} style={{ width: 3, height: 4 + Math.sin(i * 0.8) * 10 + Math.random() * 8, background: t.fg, borderRadius: 1.5, opacity: 0.5 }} />
                  ))}
                </div>
              </div>
            )}

            {/* Transcribing state */}
            {isTranscribing && (
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 4px' }}>
                <div style={{ width: 14, height: 14, border: `2px solid ${t.fg3}`, borderTopColor: t.fg, borderRadius: 7, animation: 'gh-spin 0.8s linear infinite' }} />
                <span style={{ fontSize: 14, color: t.fg2 }}>Transcribing audio…</span>
                <span style={{ fontFamily: G.mono, fontSize: 12, color: t.fg3 }}>0:14 of audio</span>
              </div>
            )}

            {/* Text area */}
            {!isRecording && !isTranscribing && (
              <div style={{ minHeight: 28, fontSize: 14, color: variant !== 'empty' ? t.fg : t.fg3, lineHeight: 1.5, padding: '4px 4px' }}>
                {variant === 'mixed' ? 'Analyze the mockup, summarize the PRD, then audit the auth code. Use the audio for context.' : 'Ask, build, or run...'}
              </div>
            )}

            {/* Bottom toolbar */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <button style={{ width: 30, height: 30, borderRadius: 8, background: 'transparent', border: 'none', color: t.fg2, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="paperclip" size={15} /></button>
              <button style={{ width: 30, height: 30, borderRadius: 8, background: 'transparent', border: 'none', color: t.fg2, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="image" size={15} /></button>
              <button style={{ width: 30, height: 30, borderRadius: 8, background: isRecording ? '#ff5f57' : 'transparent', border: 'none', color: isRecording ? '#fff' : t.fg2, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', borderRadius: 15 }}><Icon name="mic" size={15} color={isRecording ? '#fff' : undefined} /></button>
              <Divider vertical style={{ height: 16, margin: '0 4px' }} />
              <Tag variant="outline" style={{ height: 24, gap: 4 }}><Icon name="sparkle" size={11} /> Ghast 2 Pro <Icon name="chevronDown" size={10} /></Tag>
              <div style={{ flex: 1 }} />
              {isRecording ? (
                <Button variant="primary" size="sm">Stop & Send</Button>
              ) : (
                <button style={{ width: 32, height: 32, borderRadius: 16, background: variant !== 'empty' ? t.fg : t.surface2, color: variant !== 'empty' ? t.bg : t.fg3, border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <Icon name="arrowUp" size={16} color={variant !== 'empty' ? t.bg : t.fg3} />
                </button>
              )}
            </div>
          </div>
        </Glass>
      </div>
    </ChatLayout>
  );
}


// ═════════════════════════════════════════════════════════════
// B · THINKING BLOCKS
// ═════════════════════════════════════════════════════════════

function ThinkingBlock({ dark, state = 'collapsed', thinkTime = '4.2s' }) {
  const t = dark ? G.d : G.l;
  const thinkingText = `The user wants me to audit auth middleware. Let me start by reading the directory structure to find all middleware files...

I see auth.ts, session.ts, errors.ts, and csrf.ts. The auth.ts file is the primary one — let me check for common bypass patterns:
1. Header-based trust without proxy verification
2. Cookie-based admin escalation
3. Missing CSRF on state-changing routes

Looking at line 142... there's a direct header check without any proxy chain validation. This is a critical bypass — any external client can set x-internal-trust: true and skip authentication entirely.

Now let me check session.ts for the admin cookie issue...`;

  return (
    <div style={{ marginBottom: 4 }}>
      {state === 'thinking' && (
        <div style={{ background: t.surface, border: `1px solid ${t.border}`, borderRadius: 12, padding: '12px 14px', marginBottom: 8 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
            <div style={{ width: 12, height: 12, border: `2px solid ${t.fg3}`, borderTopColor: t.fg, borderRadius: 6, animation: 'gh-spin 0.8s linear infinite' }} />
            <span style={{ fontSize: 12, fontWeight: 500, color: t.fg2 }}>Thinking…</span>
            <span style={{ fontSize: 11, fontFamily: G.mono, color: t.fg3 }}>2.1s</span>
          </div>
          <div style={{ fontSize: 13, color: t.fg3, fontStyle: 'italic', lineHeight: 1.55, maxHeight: 80, overflow: 'hidden', position: 'relative' }}>
            {thinkingText.slice(0, 180)}
            <span style={{ display: 'inline-block', width: 2, height: 14, background: t.fg3, marginLeft: 1, animation: 'gh-blink 1s infinite', verticalAlign: -2 }} />
            <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 30, background: `linear-gradient(transparent, ${t.surface})` }} />
          </div>
        </div>
      )}

      {state === 'collapsed' && (
        <div style={{
          display: 'inline-flex', alignItems: 'center', gap: 6, padding: '5px 10px',
          background: t.surface, border: `1px solid ${t.border}`, borderRadius: 8,
          fontSize: 12, color: t.fg3, cursor: 'pointer', marginBottom: 8,
        }}>
          <Icon name="chevronRight" size={11} color={t.fg3} />
          Thought for {thinkTime} · click to expand
        </div>
      )}

      {state === 'expanded' && (
        <div style={{ background: t.surface, border: `1px solid ${t.border}`, borderRadius: 12, padding: '12px 14px', marginBottom: 8 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10, cursor: 'pointer' }}>
            <Icon name="chevronDown" size={11} color={t.fg3} />
            <span style={{ fontSize: 12, fontWeight: 500, color: t.fg2 }}>Thought for {thinkTime}</span>
          </div>
          <div style={{ fontSize: 13, color: t.fg3, fontStyle: 'italic', lineHeight: 1.6, whiteSpace: 'pre-wrap' }}>{thinkingText}</div>
        </div>
      )}

      {state === 'nested' && (
        <div style={{ background: t.surface, border: `1px solid ${t.border}`, borderRadius: 12, padding: '12px 14px', marginBottom: 8 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10, cursor: 'pointer' }}>
            <Icon name="chevronDown" size={11} color={t.fg3} />
            <span style={{ fontSize: 12, fontWeight: 500, color: t.fg2 }}>Thought for 12.8s · 3 tool calls</span>
          </div>
          <div style={{ fontSize: 13, color: t.fg3, fontStyle: 'italic', lineHeight: 1.55, marginBottom: 10 }}>
            Let me read the auth middleware files first…
          </div>
          {/* Nested tool call */}
          <div style={{ padding: '8px 10px', background: t.surface2, border: `1px solid ${t.border2}`, borderRadius: 8, marginBottom: 8, display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
            <Icon name="check" size={11} color={t.fg2} />
            <span style={{ fontFamily: G.mono, fontWeight: 500 }}>read_file</span>
            <span style={{ color: t.fg3, fontFamily: G.mono }}>auth.ts</span>
            <span style={{ flex: 1 }} />
            <span style={{ color: t.fg3, fontFamily: G.mono, fontSize: 10 }}>12ms</span>
          </div>
          <div style={{ fontSize: 13, color: t.fg3, fontStyle: 'italic', lineHeight: 1.55, marginBottom: 10 }}>
            Found the bypass on line 142. Let me also check session.ts…
          </div>
          <div style={{ padding: '8px 10px', background: t.surface2, border: `1px solid ${t.border2}`, borderRadius: 8, marginBottom: 8, display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
            <Icon name="check" size={11} color={t.fg2} />
            <span style={{ fontFamily: G.mono, fontWeight: 500 }}>read_file</span>
            <span style={{ color: t.fg3, fontFamily: G.mono }}>session.ts</span>
            <span style={{ flex: 1 }} />
            <span style={{ color: t.fg3, fontFamily: G.mono, fontSize: 10 }}>8ms</span>
          </div>
          <div style={{ fontSize: 13, color: t.fg3, fontStyle: 'italic', lineHeight: 1.55, marginBottom: 10 }}>
            Confirmed: admin=true cookie bypass on line 88. Let me grep for other issues…
          </div>
          <div style={{ padding: '8px 10px', background: t.surface2, border: `1px solid ${t.border2}`, borderRadius: 8, display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
            <Icon name="check" size={11} color={t.fg2} />
            <span style={{ fontFamily: G.mono, fontWeight: 500 }}>grep</span>
            <span style={{ color: t.fg3, fontFamily: G.mono }}>bypass|skipAuth</span>
            <span style={{ flex: 1 }} />
            <span style={{ color: t.fg3, fontFamily: G.mono, fontSize: 10 }}>88ms</span>
          </div>
        </div>
      )}
    </div>
  );
}

function ChatThinkingBlocks({ dark, variant = 'collapsed' }) {
  return (
    <ChatLayout dark={dark}>
      <UserMsg dark={dark}>Audit the auth middleware — flag any session bypasses.</UserMsg>
      <AssistantMsg dark={dark}>
        <ThinkingBlock dark={dark} state={variant} />
        {(variant === 'collapsed' || variant === 'expanded' || variant === 'nested') && (
          <p style={{ margin: '4px 0 0' }}>I found <strong>two high-severity bypasses</strong> and one low-severity leak in the auth middleware.</p>
        )}
      </AssistantMsg>
    </ChatLayout>
  );
}


// ═════════════════════════════════════════════════════════════
// C · TOOL EXECUTION INLINE CARDS
// ═════════════════════════════════════════════════════════════

function ToolCard({ dark, name, arg, status = 'success', time, input, output, stderr, truncated }) {
  const t = dark ? G.d : G.l;
  const statusColors = { pending: t.fg3, running: t.fg2, success: t.fg2, error: '#ff5f57' };
  const statusIcons = {
    pending: <div style={{ width: 11, height: 11, borderRadius: 6, border: `1.5px solid ${t.fg3}` }} />,
    running: <div style={{ width: 11, height: 11, border: `1.5px solid ${t.fg2}`, borderTopColor: 'transparent', borderRadius: 6, animation: 'gh-spin 0.8s linear infinite' }} />,
    success: <Icon name="check" size={12} color={t.fg2} />,
    error: <Icon name="warn" size={12} color="#ff5f57" />,
  };
  const isExpanded = !!input;

  return (
    <div style={{
      background: t.surface, border: `1px solid ${status === 'error' ? '#ff5f57' : t.border}`,
      borderRadius: 10, overflow: 'hidden', marginBottom: 6,
    }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 12px', cursor: 'pointer' }}>
        {statusIcons[status]}
        <span style={{ fontFamily: G.mono, fontSize: 12, fontWeight: 500 }}>{name}</span>
        <span style={{ fontSize: 12, color: t.fg3, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{arg}</span>
        {time && <span style={{ fontSize: 10, fontFamily: G.mono, color: t.fg3, flexShrink: 0 }}>{time}</span>}
        <Icon name={isExpanded ? 'chevronDown' : 'chevronRight'} size={11} color={t.fg4} />
      </div>

      {/* Expanded content */}
      {isExpanded && (
        <div style={{ borderTop: `1px solid ${status === 'error' ? 'rgba(255,95,87,0.2)' : t.border2}`, padding: '10px 12px' }}>
          {input && (
            <>
              <div style={{ fontSize: 10, fontWeight: 600, color: t.fg3, letterSpacing: 0.6, marginBottom: 4 }}>INPUT</div>
              <pre style={{ fontFamily: G.mono, fontSize: 11, color: t.fg2, background: t.surface2, padding: 8, borderRadius: 6, margin: '0 0 10px', lineHeight: 1.5, overflow: 'auto', maxHeight: 80 }}>{input}</pre>
            </>
          )}
          {output && (
            <>
              <div style={{ fontSize: 10, fontWeight: 600, color: t.fg3, letterSpacing: 0.6, marginBottom: 4 }}>OUTPUT</div>
              <pre style={{ fontFamily: G.mono, fontSize: 11, color: t.fg, background: t.surface2, padding: 8, borderRadius: 6, margin: 0, lineHeight: 1.5, overflow: 'auto', maxHeight: 100, position: 'relative' }}>
                {output}
                {truncated && <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: 28, background: `linear-gradient(transparent, ${t.surface2})`, display: 'flex', alignItems: 'flex-end', justifyContent: 'center', paddingBottom: 4 }}>
                  <span style={{ fontSize: 10, color: t.fg3, cursor: 'pointer' }}>Show all (2.4 KB) ↓</span>
                </div>}
              </pre>
            </>
          )}
          {stderr && (
            <>
              <div style={{ fontSize: 10, fontWeight: 600, color: '#ff5f57', letterSpacing: 0.6, marginBottom: 4, marginTop: 10 }}>STDERR</div>
              <pre style={{ fontFamily: G.mono, fontSize: 11, color: '#ff5f57', background: dark ? 'rgba(255,95,87,0.08)' : 'rgba(255,95,87,0.05)', padding: 8, borderRadius: 6, margin: 0, lineHeight: 1.5 }}>{stderr}</pre>
            </>
          )}
          {status === 'error' && (
            <div style={{ display: 'flex', gap: 8, marginTop: 10 }}>
              <Button variant="primary" size="sm" icon={<Icon name="refresh" size={11} color={dark ? G.d.bg : G.l.bg} />}>Retry</Button>
              <Button variant="ghost" size="sm">Skip and continue</Button>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function ChatToolCards({ dark, variant = 'mixed' }) {
  return (
    <ChatLayout dark={dark}>
      <UserMsg dark={dark}>Audit and fix the auth middleware.</UserMsg>
      <AssistantMsg dark={dark}>
        <ThinkingBlock dark={dark} state="collapsed" thinkTime="3.1s" />
        <p style={{ margin: '0 0 10px' }}>Let me read the files and run the audit.</p>

        {variant === 'pending' && <ToolCard dark={dark} name="read_file" arg="auth.ts" status="pending" />}
        {variant === 'running' && <ToolCard dark={dark} name="shell" arg="pnpm test:auth" status="running" time="2.4s" />}

        {(variant === 'collapsed' || variant === 'mixed') && (
          <>
            <ToolCard dark={dark} name="read_file" arg="auth.ts" status="success" time="12ms" />
            <ToolCard dark={dark} name="grep" arg='"bypass|skipAuth" in /apps/web' status="success" time="88ms" />
          </>
        )}

        {variant === 'expanded' && (
          <ToolCard dark={dark} name="read_file" arg="auth.ts" status="success" time="12ms"
            input={'{\n  "path": "apps/web/middleware/auth.ts"\n}'}
            output={'import type { NextFunction, Request, Response } from \'express\';\nimport { verifyJwt } from \'../lib/jwt\';\n\nexport async function auth(req, res, next) {\n  if (req.headers[\'x-internal-trust\'] === \'true\') {\n    return next();\n  }\n  ...'} />
        )}

        {variant === 'error' && (
          <ToolCard dark={dark} name="shell" arg="pnpm test:auth" status="error" time="12.4s"
            input={'{\n  "command": "pnpm test:auth"\n}'}
            stderr={'Error: Cannot find module \'@testing-library/jest-dom\'\n    at Module._resolveFilename (node:internal/modules/cjs/loader:1075:15)\n    at Module._load (node:internal/modules/cjs/loader:920:27)\n\nTest Suites: 3 failed, 11 passed, 14 total'} />
        )}

        {variant === 'truncated' && (
          <ToolCard dark={dark} name="shell" arg="pnpm build" status="success" time="34s"
            input={'{\n  "command": "pnpm build"\n}'}
            output={'> ghast-web@2.4.0 build\n> turbo run build --filter=apps/web\n\n• Packages in scope: @ghast/web\n• Running build in 1 packages\n• Remote caching disabled\napps/web:build: $ next build\napps/web:build: ▲ Next.js 15.2.0\napps/web:build: Creating optimized production build...'}
            truncated />
        )}

        {(variant === 'collapsed' || variant === 'mixed') && (
          <p style={{ margin: '6px 0 0' }}>Found 2 critical issues in auth.ts. Fixing now…</p>
        )}
      </AssistantMsg>
    </ChatLayout>
  );
}


// ═════════════════════════════════════════════════════════════
// D · MULTI-AGENT COLLABORATION
// ═════════════════════════════════════════════════════════════

function SubAgentThread({ dark, name, avatar, status = 'running', messages = [], collapsed = false }) {
  const t = dark ? G.d : G.l;
  const statusColors = { spawned: t.fg3, running: '#febc2e', completed: '#28c840', failed: '#ff5f57' };
  const statusLabels = { spawned: 'Spawned', running: 'Running', completed: 'Completed', failed: 'Failed' };

  return (
    <div style={{
      marginLeft: 38, borderLeft: `2px solid ${t.border}`, paddingLeft: 16, paddingBottom: 8, position: 'relative',
    }}>
      {/* Connector dot */}
      <div style={{ position: 'absolute', left: -5, top: 14, width: 8, height: 8, borderRadius: 4, background: statusColors[status], border: `2px solid ${t.bg}` }} />

      {/* Agent card */}
      <div style={{
        background: t.surface, border: `1px solid ${status === 'failed' ? '#ff5f57' : t.border}`,
        borderRadius: 12, overflow: 'hidden',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', cursor: 'pointer' }}>
          <div style={{ width: 24, height: 24, borderRadius: 12, background: t.surface2, border: `1px solid ${t.border}`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <GhastLogo size={14} color={t.fg2} />
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 12, fontWeight: 600, display: 'flex', alignItems: 'center', gap: 6 }}>
              {name}
              <StatusDot status={status === 'completed' ? 'on' : status === 'failed' ? 'off' : 'pending'} size={6} />
              <span style={{ fontSize: 10, color: t.fg3, fontWeight: 400 }}>{statusLabels[status]}</span>
            </div>
          </div>
          {status === 'running' && <div style={{ width: 12, height: 12, border: `1.5px solid ${t.fg3}`, borderTopColor: '#febc2e', borderRadius: 6, animation: 'gh-spin 0.8s linear infinite' }} />}
          <Icon name={collapsed ? 'chevronRight' : 'chevronDown'} size={12} color={t.fg3} />
        </div>

        {!collapsed && messages.length > 0 && (
          <div style={{ borderTop: `1px solid ${t.border2}`, padding: '10px 14px', display: 'flex', flexDirection: 'column', gap: 8 }}>
            {messages.map((m, i) => (
              <div key={i} style={{ fontSize: 12, color: t.fg2, lineHeight: 1.5 }}>
                {m}
              </div>
            ))}
          </div>
        )}

        {status === 'failed' && (
          <div style={{ borderTop: `1px solid rgba(255,95,87,0.2)`, padding: '8px 14px', display: 'flex', gap: 8, alignItems: 'center' }}>
            <span style={{ fontSize: 11, color: '#ff5f57', flex: 1 }}>Partial result available</span>
            <Button variant="ghost" size="sm">View result</Button>
            <Button variant="secondary" size="sm" icon={<Icon name="refresh" size={11} />}>Retry</Button>
          </div>
        )}
      </div>
    </div>
  );
}

function ChatMultiAgent({ dark, variant = 'single' }) {
  return (
    <ChatLayout dark={dark} title="Audit & fix auth">
      <UserMsg dark={dark}>Audit auth, fix issues, and write a summary — do it all in parallel.</UserMsg>
      <AssistantMsg dark={dark}>
        <p style={{ margin: '0 0 10px' }}>
          {variant === 'fanout' ? 'Spawning 3 sub-agents to work in parallel:' :
           variant === 'completed' ? 'All sub-agents completed. Here\'s the summary:' :
           variant === 'failed' ? 'Two sub-agents completed, one failed:' :
           'Delegating the audit to a specialized sub-agent:'}
        </p>
      </AssistantMsg>

      {(variant === 'single') && (
        <SubAgentThread dark={dark} name="ghast-auditor" status="running"
          messages={['Reading auth.ts… found bypass on line 142.', 'Checking session.ts for admin cookie logic…']} />
      )}

      {(variant === 'fanout' || variant === 'completed' || variant === 'failed') && (
        <>
          <SubAgentThread dark={dark} name="ghast-auditor" status={variant === 'fanout' ? 'running' : 'completed'}
            messages={variant === 'fanout' ? ['Scanning middleware files…'] : ['Found 2 high-severity issues. Patches ready.']}
            collapsed={variant === 'completed'} />
          <SubAgentThread dark={dark} name="ghast-fixer" status={variant === 'failed' ? 'failed' : variant === 'fanout' ? 'running' : 'completed'}
            messages={variant === 'fanout' ? ['Waiting for audit results…'] : variant === 'failed' ? ['Applied fix for auth.ts, but tests failed.'] : ['Applied 2 patches. All 14 tests pass.']}
            collapsed={variant === 'completed'} />
          <SubAgentThread dark={dark} name="ghast-writer" status={variant === 'fanout' ? 'spawned' : 'completed'}
            messages={variant === 'fanout' ? [] : ['Generated audit-report.md (2.8 KB)']}
            collapsed={variant === 'completed' || variant === 'fanout'} />
        </>
      )}

      {variant === 'completed' && (
        <AssistantMsg dark={dark}>
          <p style={{ margin: '4px 0 0' }}>All done. 2 patches applied, tests pass, and the report is ready. Want me to open a PR?</p>
        </AssistantMsg>
      )}
    </ChatLayout>
  );
}


// ═════════════════════════════════════════════════════════════
// E · ERROR RECOVERY
// ═════════════════════════════════════════════════════════════

function ChatErrors({ dark, variant = 'timeout' }) {
  const t = dark ? G.d : G.l;

  const errorBanners = {
    timeout: (
      <div style={{ margin: '0 24px', padding: '12px 16px', background: dark ? 'rgba(255,95,87,0.08)' : 'rgba(255,95,87,0.05)', border: `1px solid rgba(255,95,87,0.2)`, borderRadius: 12, display: 'flex', alignItems: 'center', gap: 12 }}>
        <Icon name="warn" size={16} color="#ff5f57" />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 500 }}>Model timed out</div>
          <div style={{ fontSize: 12, color: t.fg3, marginTop: 1 }}>claude-4-sonnet didn't respond within 60s.</div>
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          <Button variant="primary" size="sm" icon={<Icon name="refresh" size={11} color={t.bg} />}>Retry</Button>
          <Button variant="secondary" size="sm">Switch model</Button>
          <Button variant="ghost" size="sm">Cancel</Button>
        </div>
      </div>
    ),
    network: (
      <div style={{ margin: '0 24px', padding: '12px 16px', background: dark ? 'rgba(254,188,46,0.08)' : 'rgba(254,188,46,0.05)', border: `1px solid rgba(254,188,46,0.2)`, borderRadius: 12, display: 'flex', alignItems: 'center', gap: 12 }}>
        <Icon name="warn" size={16} color="#febc2e" />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 500 }}>Network disconnected</div>
          <div style={{ fontSize: 12, color: t.fg3, marginTop: 1 }}>Reconnecting in <span style={{ fontFamily: G.mono }}>8s</span>… Messages will resume automatically.</div>
        </div>
        <Button variant="secondary" size="sm" icon={<Icon name="refresh" size={11} />}>Retry now</Button>
      </div>
    ),
    apikey: (
      <div style={{ margin: '0 24px', padding: '12px 16px', background: dark ? 'rgba(255,95,87,0.08)' : 'rgba(255,95,87,0.05)', border: `1px solid rgba(255,95,87,0.2)`, borderRadius: 12, display: 'flex', alignItems: 'center', gap: 12 }}>
        <Icon name="lock" size={16} color="#ff5f57" />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 500 }}>Anthropic API key invalid</div>
          <div style={{ fontSize: 12, color: t.fg3, marginTop: 1 }}>Your key was rejected. Update it in Settings → Providers.</div>
        </div>
        <Button variant="primary" size="sm">Go to Providers →</Button>
      </div>
    ),
    ratelimit: (
      <div style={{ margin: '0 24px', padding: '12px 16px', background: dark ? 'rgba(254,188,46,0.08)' : 'rgba(254,188,46,0.05)', border: `1px solid rgba(254,188,46,0.2)`, borderRadius: 12, display: 'flex', alignItems: 'center', gap: 12 }}>
        <Icon name="history" size={16} color="#febc2e" />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 500 }}>Rate limited by Anthropic</div>
          <div style={{ fontSize: 12, color: t.fg3, marginTop: 1 }}>Wait <span style={{ fontFamily: G.mono }}>42s</span> or switch to another provider.</div>
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          <Button variant="secondary" size="sm">Use OpenAI</Button>
          <Button variant="ghost" size="sm">Use Ollama</Button>
        </div>
      </div>
    ),
  };

  return (
    <ChatLayout dark={dark}>
      <UserMsg dark={dark}>Audit the auth middleware and write a report.</UserMsg>
      {variant === 'network' && (
        <div style={{ maxWidth: 760, margin: '0 auto', width: '100%' }}>{errorBanners.network}</div>
      )}
      <AssistantMsg dark={dark}>
        {variant === 'timeout' && (
          <>
            <ThinkingBlock dark={dark} state="collapsed" thinkTime="58.2s" />
            <div style={{ marginTop: 4 }}>{errorBanners.timeout}</div>
          </>
        )}
        {variant === 'network' && (
          <p style={{ margin: '4px 0', color: t.fg3 }}>I was reading auth.ts when the connection dropped…</p>
        )}
        {variant === 'apikey' && (
          <div>{errorBanners.apikey}</div>
        )}
        {variant === 'ratelimit' && (
          <div>{errorBanners.ratelimit}</div>
        )}
      </AssistantMsg>
    </ChatLayout>
  );
}


// ═════════════════════════════════════════════════════════════
// F · MESSAGE ACTIONS (hover toolbar, branch, edit, reactions)
// ═════════════════════════════════════════════════════════════

function ChatMessageActions({ dark, variant = 'hover' }) {
  const t = dark ? G.d : G.l;

  return (
    <ChatLayout dark={dark}>
      <UserMsg dark={dark}>Audit the auth middleware.</UserMsg>

      {/* Assistant message with hover toolbar */}
      <div style={{ display: 'flex', gap: 12, position: 'relative' }}>
        <GhastLogo size={26} color={t.fg} style={{ flexShrink: 0, marginTop: 2 }} />
        <div style={{ flex: 1, fontSize: 14, lineHeight: 1.6 }}>
          {/* Branch indicator */}
          {variant === 'branched' && (
            <div style={{
              display: 'inline-flex', alignItems: 'center', gap: 8, padding: '4px 10px',
              background: t.surface, border: `1px solid ${t.border}`, borderRadius: 8,
              fontSize: 12, color: t.fg2, marginBottom: 8,
            }}>
              <Icon name="arrowLeft" size={11} color={t.fg3} style={{ cursor: 'pointer' }} />
              <span>Branch <strong>2</strong> of <strong>3</strong></span>
              <Icon name="arrowRight" size={11} color={t.fg3} style={{ cursor: 'pointer' }} />
            </div>
          )}

          {variant !== 'editing' ? (
            <>
              <p style={{ margin: '4px 0 8px' }}>I found <strong>two high-severity bypasses</strong>. The X-Internal-Trust header on line 142 can be set by any external client, and the admin cookie on line 88 skips the session check entirely.</p>

              {/* Hover toolbar */}
              {variant === 'hover' && (
                <div style={{
                  position: 'absolute', top: -16, right: 0, display: 'flex', gap: 1,
                  background: t.surface, border: `1px solid ${t.border}`, borderRadius: 10,
                  padding: 3, boxShadow: t.shadow,
                }}>
                  {[
                    { icon: 'copy', tip: 'Copy' },
                    { icon: 'edit', tip: 'Edit' },
                    { icon: 'refresh', tip: 'Re-roll' },
                    { icon: 'git', tip: 'Branch' },
                    { icon: 'trash', tip: 'Delete' },
                    { icon: 'chat', tip: 'Quote' },
                    { icon: 'box', tip: 'Add to memory' },
                    { icon: 'star', tip: 'React' },
                  ].map((a, i) => (
                    <button key={i} title={a.tip} style={{
                      width: 28, height: 28, borderRadius: 7, background: 'transparent',
                      border: 'none', color: t.fg2, cursor: 'pointer',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                    }}>
                      <Icon name={a.icon} size={13} />
                    </button>
                  ))}
                </div>
              )}

              {/* Reaction chips */}
              {variant === 'reacted' && (
                <div style={{ display: 'flex', gap: 6, marginTop: 8 }}>
                  <div style={{
                    padding: '3px 8px', borderRadius: 12, fontSize: 13,
                    background: t.surface2, border: `1px solid ${t.fg}`,
                    display: 'flex', alignItems: 'center', gap: 4,
                  }}>👍 <span style={{ fontSize: 11, fontWeight: 500 }}>1</span></div>
                  <div style={{
                    padding: '3px 8px', borderRadius: 12, fontSize: 13,
                    background: t.surface2, border: `1px solid ${t.border}`,
                    display: 'flex', alignItems: 'center', gap: 4,
                  }}>🎯</div>
                  <button style={{ width: 24, height: 24, borderRadius: 12, background: t.surface2, border: `1px solid ${t.border}`, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, color: t.fg3 }}>+</button>
                </div>
              )}
            </>
          ) : (
            /* Editing mode */
            <>
              <div style={{
                border: `2px solid ${t.fg}`, borderRadius: 12, padding: '10px 14px',
                background: t.surface, fontSize: 14, lineHeight: 1.6,
                fontFamily: G.font, minHeight: 80,
              }}>
                I found two high-severity bypasses. The X-Internal-Trust header on line 142 can be set by any external client, and the admin cookie on line 88 skips the session check entirely.
                <span style={{ display: 'inline-block', width: 2, height: 16, background: t.fg, animation: 'gh-blink 1s infinite', verticalAlign: -3, marginLeft: 1 }} />
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 10 }}>
                <Button variant="primary" size="sm">Save & resubmit</Button>
                <Button variant="ghost" size="sm">Cancel</Button>
              </div>
            </>
          )}
        </div>
      </div>
    </ChatLayout>
  );
}

// Spin keyframes (reuse)
if (typeof document !== 'undefined' && !document.getElementById('gh-spin-style')) {
  const s = document.createElement('style');
  s.id = 'gh-spin-style';
  s.textContent = '@keyframes gh-spin{to{transform:rotate(360deg)}}';
  document.head.appendChild(s);
}

Object.assign(window, {
  ChatLayout, UserMsg, AssistantMsg,
  ComposerMultimodal,
  ThinkingBlock, ChatThinkingBlocks,
  ToolCard, ChatToolCards,
  SubAgentThread, ChatMultiAgent,
  ChatErrors,
  ChatMessageActions,
});
