import { useMemo, useState } from 'react';
import type { RunEvent } from '../../lib/orchestratorApi';

/**
 * Rich, grouped renderer for an agent run's event log.
 *
 * Turns the flat event stream into a readable "agent activity" view:
 *   - assistant `text` becomes wide chat bubbles (the agent "talking"),
 *   - tool calls are paired (start→end) into compact timeline entries with
 *     status markers — a spinner while running, ✓ / ✗ when done — and an
 *     expandable result block,
 *   - bevy `start`/`end` are milestones; bevy `output` is collapsed into a
 *     console block that streams live while the playtest runs,
 *   - logs, errors, and the `done` milestone get their own treatments,
 *   - every entry carries a relative `+Ns` timestamp.
 *
 * Pure presentation: inline styles + the project's CSS-var design tokens only.
 * State is limited to which tool/result blocks the user has expanded.
 */

interface RunEventListProps {
  events: RunEvent[];
  /** ISO string of run start, used for relative timestamps. */
  startedAtIso?: string | null;
  /** True while the agent itself is working (drives the trailing live cursor). */
  active: boolean;
  /** True while a Bevy playtest is running (keeps its console live). */
  bevyRunning: boolean;
}

// ---- timeline model -------------------------------------------------------

interface ToolItem {
  kind: 'tool';
  key: string;
  tool: string;
  startPreview: string;
  endPreview?: string;
  ok?: boolean;
  open: boolean;
  startEv: RunEvent;
  endEv?: RunEvent;
}
interface LogItem {
  kind: 'log';
  key: string;
  ev: RunEvent;
}
interface BevyMarkerItem {
  kind: 'bevy_marker';
  key: string;
  phase: 'start' | 'end';
  text: string;
  exitCode?: number;
  ev: RunEvent;
}
interface BevyOutputItem {
  kind: 'bevy_output';
  key: string;
  lines: string[];
  startEv: RunEvent;
}
interface DoneItem {
  kind: 'done';
  key: string;
  ev: RunEvent;
}
interface ErrorItem {
  kind: 'error';
  key: string;
  ev: RunEvent;
}

type ActivityItem =
  | ToolItem
  | LogItem
  | BevyMarkerItem
  | BevyOutputItem
  | DoneItem
  | ErrorItem;

/** Activity items rendered by the simple dispatcher (tool/bevy_output are
 * handled by their own components). Each variant exposes an `ev`. */
type SimpleActivityItem = LogItem | BevyMarkerItem | DoneItem | ErrorItem;

type Block =
  | { kind: 'message'; key: string; ev: RunEvent }
  | { kind: 'activity'; key: string; items: ActivityItem[] };

/** Pair tool_start/tool_end, group bevy output, and split text into chat blocks. */
function buildTimeline(events: RunEvent[]): Block[] {
  const blocks: Block[] = [];
  const openTools: ToolItem[] = [];
  let n = 0;

  const key = (prefix: string, ev: RunEvent) => `${prefix}-${ev.seq ?? n++}`;

  // Append to the trailing activity block, creating one if the last block is a
  // chat message (so consecutive tool/log/bevy work shares a single rail).
  const activityItems = (): ActivityItem[] => {
    const last = blocks[blocks.length - 1];
    if (last && last.kind === 'activity') return last.items;
    const block: Block = { kind: 'activity', key: `act-${blocks.length}`, items: [] };
    blocks.push(block);
    return block.items;
  };

  for (const ev of events) {
    switch (ev.type) {
      case 'status':
        continue; // reflected by the header/banner; skip in the timeline
      case 'text':
        blocks.push({ kind: 'message', key: key('msg', ev), ev });
        break;
      case 'tool_start': {
        const item: ToolItem = {
          kind: 'tool',
          key: key('tool', ev),
          tool: String(ev.data.tool ?? 'tool'),
          startPreview: String(ev.data.preview ?? ''),
          open: true,
          startEv: ev,
        };
        activityItems().push(item);
        openTools.push(item);
        break;
      }
      case 'tool_end': {
        const item = openTools.pop();
        if (item) {
          item.open = false;
          item.ok = ev.data.ok !== false;
          item.endPreview = String(ev.data.preview ?? '');
          item.endEv = ev;
        } else {
          // Orphan end (history truncated before its start) → standalone result.
          activityItems().push({
            kind: 'tool',
            key: key('tool', ev),
            tool: String(ev.data.tool ?? 'tool'),
            startPreview: '',
            endPreview: String(ev.data.preview ?? ''),
            ok: ev.data.ok !== false,
            open: false,
            startEv: ev,
            endEv: ev,
          });
        }
        break;
      }
      case 'log':
        activityItems().push({ kind: 'log', key: key('log', ev), ev });
        break;
      case 'bevy': {
        const phase = String(ev.data.phase ?? 'output');
        const text = String(ev.data.text ?? '');
        if (phase === 'start' || phase === 'end') {
          activityItems().push({
            kind: 'bevy_marker',
            key: key('bevym', ev),
            phase,
            text,
            exitCode: typeof ev.data.exitCode === 'number' ? ev.data.exitCode : undefined,
            ev,
          });
        } else {
          const items = activityItems();
          const last = items[items.length - 1];
          if (last && last.kind === 'bevy_output') {
            if (text) last.lines.push(text);
          } else {
            items.push({ kind: 'bevy_output', key: key('bevyo', ev), lines: text ? [text] : [], startEv: ev });
          }
        }
        break;
      }
      case 'done':
        activityItems().push({ kind: 'done', key: key('done', ev), ev });
        break;
      case 'error':
        activityItems().push({ kind: 'error', key: key('err', ev), ev });
        break;
      default:
        break;
    }
  }
  return blocks;
}

// ---- component ------------------------------------------------------------

export function RunEventList({ events, startedAtIso, active, bevyRunning }: RunEventListProps) {
  // Keep the rendered log bounded; grouping compresses bevy/log noise first, so
  // each tool/chat item stays intact even at the slice boundary.
  const blocks = useMemo(() => buildTimeline(events).slice(-80), [events]);
  const [expandedTools, setExpandedTools] = useState<Record<string, boolean>>({});
  const [openConsoles, setOpenConsoles] = useState<Record<string, boolean>>({});

  const startMs = parseMs(startedAtIso);

  if (events.length === 0) {
    return (
      <div style={emptyStyle}>
        {active ? (
          <>
            <TypingDots color="var(--accent)" />
            <span style={{ color: 'var(--fg-dim)' }}>
              {bevyRunning ? 'Bevy is compiling / running…' : 'Waiting for the agent to respond…'}
            </span>
          </>
        ) : (
          <span style={{ color: 'var(--muted)' }}>No activity recorded yet.</span>
        )}
      </div>
    );
  }

  // The trailing bevy_output stays "live" (open + pulsing) while Bevy runs.
  let liveConsoleKey: string | null = null;
  if (bevyRunning) {
    const lastBlock = blocks[blocks.length - 1];
    if (lastBlock && lastBlock.kind === 'activity') {
      const lastItem = lastBlock.items[lastBlock.items.length - 1];
      if (lastItem && lastItem.kind === 'bevy_output') liveConsoleKey = lastItem.key;
    }
  }

  return (
    <div style={listStyle}>
      {blocks.map((block) =>
        block.kind === 'message' ? (
          <ChatBubble key={block.key} text={String(block.ev.data.text ?? '')} timeMs={parseMs(block.ev.createdAt)} startMs={startMs} />
        ) : (
          <ActivityBlock key={block.key}>
            {block.items.map((item) => {
              if (item.kind === 'tool') {
                const open = item.open || !!expandedTools[item.key];
                return (
                  <ToolEntry
                    key={item.key}
                    item={item}
                    expanded={open}
                    startMs={startMs}
                    onToggle={() => setExpandedTools((p) => ({ ...p, [item.key]: !p[item.key] }))}
                  />
                );
              }
              if (item.kind === 'bevy_output') {
                const live = item.key === liveConsoleKey;
                const open = live || !!openConsoles[item.key];
                return (
                  <BevyConsole
                    key={item.key}
                    item={item}
                    open={open}
                    live={live}
                    startMs={startMs}
                    onToggle={() => setOpenConsoles((p) => ({ ...p, [item.key]: !p[item.key] }))}
                  />
                );
              }
              return <ActivityEntry key={item.key} item={item} startMs={startMs} />;
            })}
          </ActivityBlock>
        ),
      )}
      {active && <WorkingRow />}
    </div>
  );
}

// ---- shared bits ----------------------------------------------------------

/** A vertical-rail activity block holding tool/log/bevy work. */
function ActivityBlock({ children }: { children: React.ReactNode }) {
  return (
    <div style={activityBlockStyle}>
      <span style={railStyle} aria-hidden />
      {children}
    </div>
  );
}

/** One row on the rail: absolutely-positioned marker + flexible content + time. */
function Row({ marker, children, time = null }: { marker: React.ReactNode; children: React.ReactNode; time?: string | null }) {
  return (
    <div style={rowStyle}>
      <span style={markerSlotStyle}>{marker}</span>
      <div style={{ flex: 1, minWidth: 0 }}>{children}</div>
      {time && <span style={timeStyle}>{time}</span>}
    </div>
  );
}

function ChatBubble({ text, timeMs, startMs }: { text: string; timeMs: number | null; startMs: number | null }) {
  const [expanded, setExpanded] = useState(false);
  const long = text.length > 360 || text.split('\n').length > 8;
  const shown = expanded || !long ? text : truncateText(text);
  return (
    <div style={bubbleWrapStyle}>
      <span style={avatarStyle} title="Agent">
        🤖
      </span>
      <div style={bubbleStyle}>
        <div style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{shown}</div>
        {long && (
          <button
            type="button"
            style={moreBtnStyle}
            onClick={(e) => {
              e.stopPropagation();
              setExpanded((x) => !x);
            }}
          >
            {expanded ? 'show less' : `show more (${text.length} chars)`}
          </button>
        )}
        {timeMs && (
          <div style={bubbleTimeStyle}>{relTime(timeMs, startMs) ?? absShort(timeMs)}</div>
        )}
      </div>
    </div>
  );
}

function ToolEntry({
  item,
  expanded,
  startMs,
  onToggle,
}: {
  item: ToolItem;
  expanded: boolean;
  startMs: number | null;
  onToggle: () => void;
}) {
  const running = item.open;
  const ok = item.ok !== false;
  const color = running ? 'var(--accent)' : item.ok === false ? 'var(--red)' : 'var(--green)';
  const hasDetail = Boolean(item.endPreview);

  return (
    <Row marker={<ToolMarker state={running ? 'running' : ok ? 'ok' : 'fail'} />} time={relTime(parseMs(item.endEv?.createdAt ?? item.startEv.createdAt), startMs)}>
      <div
        style={{ ...toolCardStyle, borderColor: running ? color : 'var(--border)', cursor: hasDetail ? 'pointer' : 'default' }}
        onClick={(e) => {
          e.stopPropagation();
          if (hasDetail) onToggle();
        }}
        role={hasDetail ? 'button' : undefined}
      >
        <div style={{ display: 'flex', alignItems: 'center', gap: '6px', minWidth: 0 }}>
          <span style={{ ...toolTagStyle(color) }}>{toolIcon(item.tool)} {item.tool}</span>
          <span style={previewStyle}>{item.startPreview || (running ? '…' : '')}</span>
          {hasDetail && (
            <span style={{ marginLeft: 'auto', fontSize: '0.6rem', color: 'var(--muted)', flexShrink: 0 }}>
              {expanded ? '▲' : '▼'}
            </span>
          )}
        </div>
        {expanded && (item.startPreview || item.endPreview) && (
          <div style={resultBlockStyle}>
            {item.startPreview && (
              <>
                <span style={resultLabelStyle}>{item.tool === 'bash' ? 'command' : 'input'}</span>
                <pre style={resultPreStyle}>{item.startPreview}</pre>
              </>
            )}
            {item.endPreview && (
              <>
                <span style={resultLabelStyle}>result</span>
                <pre style={resultPreStyle}>{item.endPreview}</pre>
              </>
            )}
          </div>
        )}
      </div>
    </Row>
  );
}

function BevyConsole({
  item,
  open,
  live,
  startMs,
  onToggle,
}: {
  item: BevyOutputItem;
  open: boolean;
  live: boolean;
  startMs: number | null;
  onToggle: () => void;
}) {
  const color = live ? 'var(--purple)' : 'var(--fg-dim)';
  const lineCount = item.lines.length;
  return (
    <Row marker={<Dot color={color} pulsing={live} />} time={relTime(parseMs(item.startEv.createdAt), startMs)}>
      <div
        style={{ ...consoleHeadStyle(color), cursor: 'pointer' }}
        onClick={(e) => {
          e.stopPropagation();
          onToggle();
        }}
        role="button"
      >
        <span style={{ fontWeight: 600 }}>🎮 Bevy output</span>
        <span style={{ color: 'var(--muted)' }}> · {lineCount} line{lineCount === 1 ? '' : 's'}</span>
        {live && <span style={liveTagStyle}>live</span>}
        <span style={{ marginLeft: 'auto', color: 'var(--muted)' }}>{open ? '▲' : '▼'}</span>
      </div>
      {open && (
        <pre style={consolePreStyle}>{item.lines.join('').trimEnd() || '(no output)'}</pre>
      )}
    </Row>
  );
}

/** A single non-tool activity item (log, bevy milestone, done, error). */
function ActivityEntry({ item, startMs }: { item: SimpleActivityItem; startMs: number | null }) {
  const time = relTime(parseMs(item.ev.createdAt), startMs);
  if (item.kind === 'log') {
    const level = String(item.ev.data.level ?? 'info');
    const text = String(item.ev.data.text ?? '');
    const color = level === 'error' ? 'var(--red)' : level === 'warn' ? 'var(--accent)' : 'var(--muted)';
    return (
      <Row marker={<Dot color={color} size={5} />}>
        <span style={{ ...logLineStyle(color) }}>
          <span style={{ opacity: 0.7 }}>{level}</span> {text}
        </span>
      </Row>
    );
  }
  if (item.kind === 'bevy_marker') {
    const isStart = item.phase === 'start';
    const color = isStart ? 'var(--purple)' : item.exitCode === 0 ? 'var(--green)' : 'var(--fg-dim)';
    return (
      <Row marker={<Glyph color={color}>{isStart ? '▶' : '■'}</Glyph>} time={time}>
        <span style={{ ...milestoneLineStyle(color) }}>
          {item.text}
          {typeof item.exitCode === 'number' && item.exitCode !== 0 && (
            <span style={{ color: 'var(--accent)' }}> · exit {item.exitCode}</span>
          )}
        </span>
      </Row>
    );
  }
  if (item.kind === 'done') {
    const summary = String(item.ev.data.summary ?? '');
    return (
      <Row marker={<Glyph color="var(--green)" solid>✓</Glyph>} time={time}>
        <span style={doneLineStyle}>
          <strong style={{ color: 'var(--green)' }}>Run complete</strong>
          {summary && <span style={{ color: 'var(--fg-dim)' }}> · {summary}</span>}
        </span>
      </Row>
    );
  }
  // error
  const message = String(item.ev.data.message ?? '');
  return (
    <Row marker={<Glyph color="var(--red)" solid>!</Glyph>} time={time}>
      <div style={errorLineStyle}>
        <strong style={{ color: 'var(--red)' }}>Error</strong>
        <div style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', color: 'var(--fg-dim)' }}>{message}</div>
      </div>
    </Row>
  );
}

function WorkingRow() {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '6px 2px', color: 'var(--accent)' }}>
      <TypingDots color="var(--accent)" />
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.7rem' }}>working…</span>
    </div>
  );
}

function TypingDots({ color }: { color: string }) {
  return (
    <span style={{ display: 'inline-flex', gap: '3px', alignItems: 'center' }}>
      {[0, 1, 2].map((i) => (
        <span
          key={i}
          style={{
            width: '4px',
            height: '4px',
            borderRadius: '50%',
            background: color,
            animation: 'vn-dots 1.1s ease-in-out infinite',
            animationDelay: `${i * 0.16}s`,
          }}
        />
      ))}
    </span>
  );
}

// ---- markers --------------------------------------------------------------

function ToolMarker({ state }: { state: 'running' | 'ok' | 'fail' }) {
  if (state === 'running') {
    return (
      <span
        style={{
          width: '13px',
          height: '13px',
          borderRadius: '50%',
          border: '2px solid var(--accent)',
          borderTopColor: 'transparent',
          animation: 'vn-spin 0.7s linear infinite',
          display: 'inline-block',
        }}
        aria-label="running"
      />
    );
  }
  const color = state === 'ok' ? 'var(--green)' : 'var(--red)';
  const ch = state === 'ok' ? '✓' : '✗';
  return <Glyph color={color} solid>{ch}</Glyph>;
}

function Dot({ color, size = 9, pulsing = false }: { color: string; size?: number; pulsing?: boolean }) {
  return (
    <span
      style={{
        width: `${size}px`,
        height: `${size}px`,
        borderRadius: '50%',
        background: color,
        boxShadow: pulsing ? `0 0 6px ${color}` : 'none',
        animation: pulsing ? 'vn-pulse 1.1s ease-in-out infinite' : undefined,
        display: 'inline-block',
      }}
    />
  );
}

function Glyph({ color, solid = false, children }: { color: string; solid?: boolean; children: React.ReactNode }) {
  return (
    <span
      style={{
        width: '15px',
        height: '15px',
        borderRadius: '50%',
        display: 'inline-flex',
        alignItems: 'center',
        justifyContent: 'center',
        fontSize: '0.6rem',
        fontWeight: 700,
        lineHeight: 1,
        color: solid ? 'var(--bg)' : color,
        background: solid ? color : `${color}22`,
        border: `1px solid ${color}`,
      }}
    >
      {children}
    </span>
  );
}

// ---- helpers --------------------------------------------------------------

function parseMs(iso?: string | null): number | null {
  if (!iso) return null;
  const t = Date.parse(iso);
  return Number.isFinite(t) ? t : null;
}

/** Relative time from run start, e.g. "+12s" / "+1m05s". */
function relTime(t: number | null, startMs: number | null): string | null {
  if (t == null || startMs == null) return null;
  const s = Math.max(0, Math.floor((t - startMs) / 1000));
  if (s < 60) return `+${s}s`;
  const m = Math.floor(s / 60);
  return `+${m}m${String(s % 60).padStart(2, '0')}s`;
}

function absShort(t: number): string {
  const d = new Date(t);
  return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
}

/** Collapse a long assistant message to a few lines/characters for skimming. */
function truncateText(text: string, maxChars = 360, maxLines = 8): string {
  const lines = text.split('\n');
  if (lines.length > maxLines) return `${lines.slice(0, maxLines).join('\n')}…`;
  if (text.length > maxChars) return `${text.slice(0, maxChars).replace(/\s+\S*$/, '')}…`;
  return text;
}

function toolIcon(tool: string): string {
  switch (tool) {
    case 'bash':
      return '⌘';
    case 'read':
      return '▤';
    case 'edit':
    case 'write':
      return '✎';
    case 'grep':
      return '⌕';
    case 'glob':
      return '◇';
    default:
      return '⚒';
  }
}

// ---- styles ---------------------------------------------------------------

const listStyle: React.CSSProperties = {
  display: 'flex',
  flexDirection: 'column',
  gap: '2px',
  fontFamily: 'var(--font-mono)',
  fontSize: '0.72rem',
  lineHeight: 1.5,
};

const emptyStyle: React.CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: '8px',
  padding: '14px 4px',
  fontFamily: 'var(--font-mono)',
  fontSize: '0.72rem',
};

const activityBlockStyle: React.CSSProperties = {
  position: 'relative',
  paddingLeft: '22px',
  margin: '6px 0',
};

const railStyle: React.CSSProperties = {
  position: 'absolute',
  left: '7px',
  top: '4px',
  bottom: '4px',
  width: '2px',
  background: 'var(--border)',
  borderRadius: '1px',
};

const rowStyle: React.CSSProperties = {
  position: 'relative',
  display: 'flex',
  alignItems: 'flex-start',
  gap: '8px',
  padding: '3px 0',
};

const markerSlotStyle: React.CSSProperties = {
  position: 'absolute',
  left: '-20px',
  top: '4px',
  width: '15px',
  display: 'flex',
  justifyContent: 'center',
};

const timeStyle: React.CSSProperties = {
  fontFamily: 'var(--font-mono)',
  fontSize: '0.6rem',
  color: 'var(--muted)',
  flexShrink: 0,
  paddingTop: '1px',
};

const previewStyle: React.CSSProperties = {
  color: 'var(--fg-dim)',
  opacity: 0.9,
  overflow: 'hidden',
  textOverflow: 'ellipsis',
  whiteSpace: 'nowrap',
  minWidth: 0,
  flex: 1,
};

const toolCardStyle: React.CSSProperties = {
  border: '1px solid var(--border)',
  borderRadius: 'var(--radius-sm)',
  background: 'var(--surface)',
  padding: '3px 7px',
  transition: 'border-color 0.15s ease',
};

function toolTagStyle(color: string): React.CSSProperties {
  return {
    fontFamily: 'var(--font-mono)',
    fontSize: '0.66rem',
    fontWeight: 600,
    color,
    background: `${color}1a`,
    border: `1px solid ${color}33`,
    borderRadius: 'var(--radius-sm)',
    padding: '1px 5px',
    whiteSpace: 'nowrap',
    flexShrink: 0,
  };
}

const resultBlockStyle: React.CSSProperties = {
  marginTop: '5px',
};

const resultLabelStyle: React.CSSProperties = {
  display: 'block',
  fontSize: '0.58rem',
  textTransform: 'uppercase',
  letterSpacing: '0.06em',
  color: 'var(--muted)',
  marginBottom: '2px',
};

const resultPreStyle: React.CSSProperties = {
  margin: 0,
  background: 'var(--bg)',
  border: '1px solid var(--border)',
  borderRadius: 'var(--radius-sm)',
  padding: '5px 7px',
  fontSize: '0.66rem',
  lineHeight: 1.45,
  color: 'var(--fg-dim)',
  whiteSpace: 'pre-wrap',
  wordBreak: 'break-word',
  maxHeight: '180px',
  overflow: 'auto',
};

function consoleHeadStyle(color: string): React.CSSProperties {
  return {
    display: 'flex',
    alignItems: 'center',
    gap: '4px',
    padding: '3px 7px',
    borderRadius: 'var(--radius-sm)',
    background: `${color}14`,
    border: `1px solid ${color}33`,
    color: 'var(--fg-dim)',
    fontSize: '0.68rem',
  };
}

const liveTagStyle: React.CSSProperties = {
  marginLeft: '4px',
  fontSize: '0.56rem',
  fontWeight: 700,
  letterSpacing: '0.08em',
  textTransform: 'uppercase',
  color: 'var(--purple)',
};

const consolePreStyle: React.CSSProperties = {
  margin: '4px 0 0 0',
  background: 'var(--bg)',
  border: '1px solid var(--border)',
  borderLeft: '2px solid var(--purple)',
  borderRadius: 'var(--radius-sm)',
  padding: '6px 8px',
  fontSize: '0.66rem',
  lineHeight: 1.45,
  color: 'var(--fg-dim)',
  whiteSpace: 'pre-wrap',
  wordBreak: 'break-word',
  maxHeight: '220px',
  overflow: 'auto',
};

function logLineStyle(color: string): React.CSSProperties {
  return { color, opacity: 0.9, wordBreak: 'break-word' };
}

function milestoneLineStyle(color: string): React.CSSProperties {
  return { color, wordBreak: 'break-word' };
}

const doneLineStyle: React.CSSProperties = {
  wordBreak: 'break-word',
};

const errorLineStyle: React.CSSProperties = {
  wordBreak: 'break-word',
};

// --- chat bubble -----------------------------------------------------------

const bubbleWrapStyle: React.CSSProperties = {
  display: 'flex',
  gap: '8px',
  alignItems: 'flex-start',
  margin: '8px 0',
};

const avatarStyle: React.CSSProperties = {
  flexShrink: 0,
  width: '24px',
  height: '24px',
  borderRadius: '50%',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  fontSize: '0.8rem',
  background: 'radial-gradient(circle at 30% 30%, rgba(34,211,238,0.35), rgba(167,139,250,0.25))',
  border: '1px solid var(--border-light)',
};

const bubbleStyle: React.CSSProperties = {
  flex: 1,
  minWidth: 0,
  background: 'var(--surface-raised)',
  border: '1px solid var(--border-light)',
  borderLeft: '2px solid var(--cyan)',
  borderRadius: '2px var(--radius-md) var(--radius-md) var(--radius-md)',
  padding: '7px 10px',
  color: 'var(--fg)',
  fontFamily: 'var(--font-body)',
  fontSize: '0.8rem',
  lineHeight: 1.55,
};

const bubbleTimeStyle: React.CSSProperties = {
  marginTop: '4px',
  fontFamily: 'var(--font-mono)',
  fontSize: '0.58rem',
  color: 'var(--muted)',
};

const moreBtnStyle: React.CSSProperties = {
  marginTop: '5px',
  background: 'transparent',
  border: 'none',
  padding: 0,
  cursor: 'pointer',
  fontFamily: 'var(--font-mono)',
  fontSize: '0.6rem',
  color: 'var(--cyan)',
};
