const { useState: useStateTD, useMemo: useMemoTD } = React;
const {
  IconArrowLeft, IconShare, IconChevDown, IconCopy, IconSearch,
  IconChevRight, IconChevsLeft, IconChevsRight, IconChevLeft,
  IconWaterfall, IconFire, IconGitGraph, IconJSON, IconTable, IconX,
  IconClock,
} = window.Icons;

const { TRACE_DETAIL } = window.Data;

// ─── Span color palette (mirrors OO span coloring)
const SPAN_COLOR = {
  blue:   "#3D6EF0",
  purple: "#7A52E0",
  green:  "#2E9D63",
  yellow: "#E0A53C",
  orange: "#E07B3C",
  red:    "#DC4040",
};

// ─── Header: back · trace name · timestamp · trace ID · spans · errors
function TraceHeader({ trace, onBack }) {
  return (
    <div style={{
      height: 64, flexShrink: 0,
      display: "flex", alignItems: "center", gap: 14,
      padding: "0 16px",
      borderBottom: "1px solid var(--border)",
      background: "var(--canvas)",
    }}>
      <button className="icon-btn" onClick={onBack} title="Back">
        <IconArrowLeft size={16}/>
      </button>
      <div style={{ display: "flex", alignItems: "baseline", gap: 12 }}>
        <span style={{ fontSize: 20, fontWeight: 700, color: "var(--ink)", letterSpacing: "-0.01em" }}>
          {trace.name}
        </span>
        <span style={{ fontSize: 12, color: "var(--muted)" }}>
          {trace.startedAt} <span style={{ color: "var(--muted-2)" }}>({trace.ago})</span>
        </span>
      </div>
      <span style={{ width: 1, height: 24, background: "var(--border)" }} />
      <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
        <span style={{ fontSize: 12, color: "var(--muted)" }}>Trace ID:</span>
        <span className="mono" style={{ fontSize: 13, color: "var(--ink)", fontWeight: 600 }}>
          {trace.traceId}
        </span>
        <button className="icon-btn" style={{ width: 22, height: 22, color: "var(--muted)" }} title="Copy trace ID">
          <IconCopy size={11}/>
        </button>
      </div>
      <span className="mono pill" style={{
        background: "var(--canvas)", border: "1px solid var(--border)",
        color: "var(--ink-2)", padding: "3px 9px", fontSize: 11,
      }}>{trace.spanCount} spans</span>
      <span className="mono pill" style={{
        background: trace.errors > 0 ? "var(--err-bg)" : "var(--err-bg)",
        color: "var(--err)", padding: "3px 9px", fontSize: 11,
        border: "1px solid rgba(220,64,64,.15)",
      }}>{trace.errors} errors</span>

      <div style={{ flex: 1 }} />
      <button className="icon-btn bordered" title="Share"><IconShare size={13}/></button>
      <button className="icon-btn" onClick={onBack} title="Close">
        <IconX size={14}/>
      </button>
    </div>
  );
}

// ─── Sub-view tabs (Waterfall / Flame Graph / Trace Graph)
function ViewTabs({ view, onView }) {
  const Tab = ({ k, Ico, label }) => {
    const active = view === k;
    return (
      <button onClick={() => onView(k)} style={{
        border: "none",
        background: active ? "var(--accent-bg)" : "transparent",
        color: active ? "var(--accent-fg)" : "var(--ink-2)",
        height: 32, padding: "0 16px", borderRadius: 999,
        fontSize: 13, fontWeight: active ? 600 : 500,
        cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 6,
      }}>
        <Ico size={14} sw={1.6}/>
        {label}
      </button>
    );
  };
  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 4,
      padding: "8px 12px",
    }}>
      <Tab k="waterfall"  Ico={IconWaterfall} label="Waterfall" />
      <Tab k="flame"      Ico={IconFire}      label="Flame Graph" />
      <Tab k="graph"      Ico={IconGitGraph}  label="Trace Graph" />
    </div>
  );
}

// ─── Span row glyph (s/c/i/l badges from the screenshot)
function KindBadge({ k }) {
  const palette = {
    l: { bg: "#E2EAFF", fg: "#3D6EF0" }, // load-generator (link/load)
    s: { bg: "#DEF2E5", fg: "#2E9D63" }, // server
    c: { bg: "#E9DEF5", fg: "#7A52E0" }, // client
    i: { bg: "#FCEFC9", fg: "#A77622" }, // internal
  };
  const c = palette[k] || palette.s;
  return (
    <span className="mono" style={{
      display: "inline-flex", alignItems: "center", justifyContent: "center",
      width: 14, height: 14, borderRadius: 3,
      background: c.bg, color: c.fg,
      fontSize: 9, fontWeight: 700,
    }}>{k}</span>
  );
}

// ─── Waterfall view: span tree (left) + selected span detail (right)
function WaterfallView({ trace }) {
  const [activeTab, setActiveTab] = useStateTD("logs");
  const [bodyFormat, setBodyFormat] = useStateTD("json");
  return (
    <div style={{ flex: 1, display: "flex", minHeight: 0 }}>
      {/* Left: span tree */}
      <div style={{
        width: 480, flexShrink: 0,
        borderRight: "1px solid var(--border)",
        background: "var(--surface)",
        display: "flex", flexDirection: "column", minHeight: 0,
      }}>
        <div style={{
          padding: "8px 14px",
          fontSize: 12, fontWeight: 600, color: "var(--ink-2)",
          borderBottom: "1px solid var(--border)",
        }}>Operation Name</div>
        <div style={{ flex: 1, overflowY: "auto", padding: "4px 0" }}>
          {trace.spans.map((s, i) => {
            const isSelected = s.selected;
            return (
              <div key={s.id} style={{
                display: "flex", alignItems: "center",
                padding: "5px 12px 5px",
                paddingLeft: 12 + s.depth * 20,
                background: isSelected ? "var(--accent-bg)" : "transparent",
                borderLeft: isSelected ? "2px solid var(--accent)" : "2px solid transparent",
                fontSize: 12, cursor: "pointer",
                position: "relative",
              }}
              onMouseEnter={e => { if (!isSelected) e.currentTarget.style.background = "var(--rail)"; }}
              onMouseLeave={e => { if (!isSelected) e.currentTarget.style.background = "transparent"; }}>
                {/* depth bracket */}
                {s.depth > 0 && (
                  <span style={{
                    position: "absolute", left: 8 + (s.depth - 1) * 20,
                    top: 0, bottom: 0,
                    borderLeft: "1px dashed var(--border-2)",
                  }}/>
                )}
                <span className="mono" style={{
                  display: "inline-block",
                  fontSize: 9, color: "var(--muted)", fontWeight: 700,
                  background: "var(--canvas)", border: "1px solid var(--border)",
                  borderRadius: 3, padding: "0 4px", marginRight: 8,
                  minWidth: 16, textAlign: "center",
                }}>{i === 0 ? "2" : "1"}</span>
                <span style={{ color: "var(--accent-fg)", fontWeight: 500, marginRight: 6 }}>
                  {s.service}
                </span>
                <KindBadge k={s.kind}/>
                <span style={{ marginLeft: 6, color: "var(--ink-2)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                  {s.op}
                </span>
                {s.dot && <span style={{
                  width: 6, height: 6, borderRadius: "50%",
                  background: "var(--ok)", marginLeft: 4,
                }}/>}
                <span style={{ flex: 1 }} />
                <span className="mono" style={{ fontSize: 11, color: "var(--ok)", fontWeight: 600 }}>{s.status}</span>
              </div>
            );
          })}
        </div>
      </div>

      {/* Right: selected span detail */}
      <div style={{
        flex: 1, minWidth: 0, display: "flex", flexDirection: "column",
        background: "var(--surface)",
      }}>
        {/* Span name + stats */}
        <div style={{ padding: "10px 16px", borderBottom: "1px solid var(--border)" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
            <span style={{
              width: 14, height: 14, borderRadius: 3,
              background: "rgba(124,91,254,0.18)",
              border: "1px solid #C9C0EE",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
            }}>
              <span style={{ width: 5, height: 5, borderRadius: "50%", background: "#7A52E0" }}/>
            </span>
            <span style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)" }}>{trace.name}</span>
          </div>
          <div style={{ display: "flex", gap: 6, marginTop: 8, alignItems: "center" }}>
            <SpanChip icon={<span style={{ color: "var(--accent)" }}>◎</span>} label="Service" value={trace.selectedSpan.service} />
            <SpanChip icon={<IconClock size={11}/>} label="Duration" value={trace.selectedSpan.duration} />
            <SpanChip icon={<IconClock size={11}/>} label="Start" value={trace.selectedSpan.start} />
            <div style={{ flex: 1 }} />
            <span className="mono pill" style={{
              background: "var(--canvas)", border: "1px solid var(--border)",
              color: "var(--ink-2)", display: "flex", alignItems: "center", gap: 5,
            }}>
              <svg width="9" height="9" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="12" r="10"/></svg>
              {trace.selectedSpan.id}
              <button className="icon-btn" style={{ width: 14, height: 14, marginLeft: 2 }}><IconCopy size={9}/></button>
            </span>
            <button className="btn" style={{ height: 24, padding: "0 8px", fontSize: 11 }}>
              View Logs <IconChevRight size={10}/>
            </button>
          </div>
        </div>

        {/* Sub-tabs */}
        <div style={{
          display: "flex", gap: 22, padding: "10px 16px 0",
          borderBottom: "1px solid var(--border)",
        }}>
          {["attributes","error","events","links","logs","metrics"].map(t => (
            <button key={t} onClick={() => setActiveTab(t)}
              className={`tab-underline ${activeTab === t ? "active" : ""}`}
              style={{
                background: "none", border: "none", padding: "4px 0",
                cursor: "pointer", textTransform: "capitalize",
              }}>
              {t}
            </button>
          ))}
        </div>

        {/* Tab content */}
        <div style={{ flex: 1, overflowY: "auto", padding: 0 }}>
          {activeTab === "logs" && <LogsTab trace={trace}/>}
          {activeTab === "attributes" && (
            <AttributesTab attrs={trace.selectedSpan.attributes}
                           format={bodyFormat} onFormat={setBodyFormat} />
          )}
          {activeTab !== "logs" && activeTab !== "attributes" && (
            <div style={{ padding: 40, textAlign: "center", color: "var(--muted)", fontSize: 13 }}>
              No {activeTab} recorded for this span.
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function SpanChip({ icon, label, value }) {
  return (
    <span className="mono pill" style={{
      background: "var(--canvas)", border: "1px solid var(--border)",
      color: "var(--ink-2)", padding: "3px 8px",
      display: "inline-flex", alignItems: "center", gap: 5,
    }}>
      {icon}
      <span style={{ color: "var(--muted)" }}>{label}</span>
      <span style={{ color: "var(--ink)", fontWeight: 600 }}>{value}</span>
    </span>
  );
}

// ─── Logs tab: associated logs with stream_name + body + severity
function LogsTab({ trace }) {
  return (
    <div>
      <div style={{
        display: "grid",
        gridTemplateColumns: "180px 140px 1fr 80px",
        padding: "8px 16px",
        fontSize: 11, fontWeight: 600, color: "var(--ink-2)",
        borderBottom: "1px solid var(--border)",
        background: "var(--canvas)",
      }}>
        <div>timestamp <span style={{ color: "var(--muted)", fontWeight: 400 }}>(Asia/Calcutta)</span></div>
        <div>stream_name</div>
        <div>body</div>
        <div>severity</div>
      </div>
      {trace.associatedLogs.map((row, i) => (
        <div key={i} style={{
          display: "grid", gridTemplateColumns: "180px 140px 1fr 80px",
          padding: "5px 16px",
          fontSize: 11.5,
          borderBottom: "1px solid var(--border)",
          borderLeft: `3px solid ${row.sev === "ERROR" ? "var(--err)" : "var(--accent)"}`,
          marginLeft: -3,
          alignItems: "center",
        }}>
          <div className="mono" style={{ color: "var(--ink-2)", display: "flex", alignItems: "center", gap: 6 }}>
            <IconChevRight size={9} style={{ color: "var(--muted-2)" }}/>
            {row.time}
          </div>
          <div style={{ color: "var(--ink)" }}>{row.stream || "otel_demo"}</div>
          <div style={{ color: "var(--ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
            {row.body}
          </div>
          <div className="mono" style={{
            color: row.sev === "ERROR" ? "var(--err)" : "var(--accent-fg)",
            fontWeight: 600, fontSize: 11,
          }}>{row.sev}</div>
        </div>
      ))}
    </div>
  );
}

// ─── Attributes tab: JSON / Table viewer
function AttributesTab({ attrs, format, onFormat }) {
  return (
    <div>
      <div style={{
        display: "flex", gap: 4, padding: "10px 16px",
        background: "var(--canvas)",
        borderBottom: "1px solid var(--border)",
      }}>
        {["json","table"].map(f => (
          <button key={f} onClick={() => onFormat(f)}
            className="icon-btn bordered"
            style={{
              width: "auto", height: 26, padding: "0 10px",
              background: format === f ? "var(--accent-bg)" : "var(--surface)",
              color:      format === f ? "var(--accent-fg)" : "var(--ink-2)",
              borderColor:format === f ? "var(--accent-line)" : "var(--border)",
              gap: 5,
            }}>
            {f === "json" ? <IconJSON size={12}/> : <IconTable size={12}/>}
            <span style={{ fontSize: 11, textTransform: "capitalize" }}>{f.toUpperCase()}</span>
          </button>
        ))}
      </div>
      {format === "json" ? (
        <pre className="mono" style={{
          margin: 0, padding: "12px 16px",
          fontSize: 12, lineHeight: 1.7, color: "var(--ink-2)",
        }}>
          {"{\n"}
          {Object.entries(attrs).map(([k, v], i, arr) => (
            <span key={k}>
              {"  - "}<span className="lg-key">{k}</span>
              <span style={{ color: "var(--muted)" }}>: </span>
              <span style={{ color: "var(--ink)" }}>{v}</span>
              {i < arr.length - 1 ? "," : ""}
              {"\n"}
            </span>
          ))}
          {"}"}
        </pre>
      ) : (
        <div style={{ padding: "0 16px" }}>
          {Object.entries(attrs).map(([k, v]) => (
            <div key={k} style={{
              display: "grid", gridTemplateColumns: "240px 1fr", gap: 14,
              padding: "8px 0", borderBottom: "1px solid var(--border)",
              fontSize: 12,
            }}>
              <span className="mono lg-key">{k}</span>
              <span className="mono" style={{ color: "var(--ink)" }}>{v}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ─── Flame Graph view — depth-based rows, full-width, hover-interactive
function FlameGraphView({ trace }) {
  const [hoverId, setHoverId] = useStateTD(null);
  const [selectedId, setSelectedId] = useStateTD(() => {
    const sel = trace.spans.find(s => s.selected);
    return sel ? sel.id : trace.spans[0].id;
  });

  const maxStart = Math.max(...trace.spans.map(s => s.start + s.dur));
  const maxDepth = Math.max(...trace.spans.map(s => s.depth));
  const ROW_H = 24;
  const W = 1600;
  const padL = 24, padR = 24, padT = 28;
  const chartW = W - padL - padR;
  const chartH = (maxDepth + 1) * ROW_H;
  const H = padT + chartH + 8;

  // 7 evenly-spaced ticks in microseconds
  const TICKS = Array.from({ length: 7 }, (_, i) => (maxStart * i) / 6);

  function fmt(us) {
    if (us >= 1000) return (us / 1000).toFixed(2) + "ms";
    return Math.round(us) + "us";
  }

  const selected = trace.spans.find(s => s.id === selectedId);
  const hovered = hoverId ? trace.spans.find(s => s.id === hoverId) : null;

  return (
    <div style={{ flex: 1, display: "flex", flexDirection: "column", background: "var(--surface)", minHeight: 0 }}>
      {/* Header */}
      <div style={{ padding: "14px 20px 6px", flexShrink: 0 }}>
        <div style={{ display: "flex", alignItems: "baseline", gap: 14 }}>
          <span className="mono" style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)" }}>{trace.spanCount} spans</span>
          <span style={{ color: "var(--muted-2)" }}>•</span>
          <span className="mono" style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)" }}>{maxDepth + 1} depth</span>
        </div>
      </div>

      {/* Flame area + axis */}
      <div style={{ padding: "0 0 8px", overflow: "auto", flexGrow: 0 }}>
        <svg width="100%" height={H} viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ display: "block" }}>
          {/* Axis labels */}
          {TICKS.map((t, i) => {
            const x = padL + (t / maxStart) * chartW;
            return (
              <g key={i}>
                <text x={x} y={padT - 12} fontSize="10" fontFamily="JetBrains Mono"
                      fill="var(--muted)" textAnchor={i === 0 ? "start" : i === TICKS.length - 1 ? "end" : "middle"}>
                  {fmt(t)}
                </text>
                <line x1={x} y1={padT - 4} x2={x} y2={padT + chartH} stroke="var(--border)" strokeWidth="0.5" strokeDasharray="2 4" opacity=".6"/>
              </g>
            );
          })}
          {/* Spans */}
          {trace.spans.map(s => {
            const left = padL + (s.start / maxStart) * chartW;
            const width = Math.max(2, (s.dur / maxStart) * chartW);
            const y = padT + s.depth * ROW_H;
            const isSelected = s.id === selectedId;
            const isHovered = s.id === hoverId;
            const color = SPAN_COLOR[s.color] || SPAN_COLOR.yellow;
            const showLabel = width > 50;
            return (
              <g key={s.id}
                 onMouseEnter={() => setHoverId(s.id)}
                 onMouseLeave={() => setHoverId(null)}
                 onClick={() => setSelectedId(s.id)}
                 style={{ cursor: "pointer" }}>
                <rect x={left} y={y + 1} width={width} height={ROW_H - 3}
                      fill={color}
                      stroke={isSelected ? "#2A2D5C" : (isHovered ? "white" : "rgba(255,255,255,.45)")}
                      strokeWidth={isSelected ? 2 : (isHovered ? 1.2 : 0.8)}
                      rx="2"
                      opacity={hoverId && !isHovered && !isSelected ? 0.55 : 0.92}/>
                {showLabel && (
                  <text x={left + 6} y={y + ROW_H / 2 + 3.5}
                        fontSize="10.5" fill="white" fontWeight="500" pointerEvents="none"
                        clipPath={`inset(0 0 0 0)`}>
                    {truncateForWidth(s.op, width)}
                  </text>
                )}
              </g>
            );
          })}
        </svg>
      </div>

      {/* Selected span detail */}
      <div style={{
        flex: 1, minHeight: 0, padding: "12px 20px 16px",
        borderTop: "1px solid var(--border)",
        background: "var(--canvas)",
        overflow: "auto",
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 10 }}>
          <span style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)" }}>
            {selected.service}.{selected.op}
          </span>
          {hovered && hovered.id !== selected.id && (
            <span className="mono pill" style={{
              background: "var(--rail)", color: "var(--muted)",
              border: "1px solid var(--border)",
            }}>hovering: {hovered.service}.{hovered.op}</span>
          )}
        </div>
        <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 12 }}>
          <SpanChip icon={<span style={{ color: "var(--accent)" }}>◎</span>} label="Service" value={selected.service}/>
          <SpanChip icon={<IconClock size={11}/>} label="Duration" value={fmt(selected.dur)}/>
          <SpanChip icon={<IconClock size={11}/>} label="Start" value={fmt(selected.start)}/>
          <SpanChip icon={<span style={{ color: "var(--ok)" }}>●</span>} label="Status" value={selected.status}/>
          <SpanChip icon={<span style={{ color: "var(--muted)" }}>↧</span>} label="Depth" value={selected.depth}/>
          <SpanChip icon={<span style={{ color: "var(--muted)" }}>#</span>} label="Kind" value={kindLabel(selected.kind)}/>
        </div>
        <div className="mono" style={{
          padding: "10px 14px",
          background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 6,
          fontSize: 12, lineHeight: 1.8, color: "var(--ink-2)",
        }}>
          <div><span className="lg-key">span_id</span>: <span style={{ color: "var(--ink)" }}>{spanIdFor(selected.id)}</span></div>
          <div><span className="lg-key">trace_id</span>: <span style={{ color: "var(--ink)" }}>{trace.traceId}</span></div>
          <div><span className="lg-key">parent_span_id</span>: <span style={{ color: "var(--ink)" }}>{parentSpanId(selected, trace)}</span></div>
          <div><span className="lg-key">operation_name</span>: <span style={{ color: "var(--ink)" }}>{selected.op}</span></div>
          <div><span className="lg-key">service.name</span>: <span style={{ color: "var(--ink)" }}>{selected.service}</span></div>
          <div><span className="lg-key">span.kind</span>: <span style={{ color: "var(--ink)" }}>{kindLabel(selected.kind)}</span></div>
          <div><span className="lg-key">status_code</span>: <span style={{ color: "var(--ok)" }}>OK</span></div>
        </div>
      </div>
    </div>
  );
}

function truncateForWidth(text, widthPx) {
  // Roughly 7px per char
  const maxChars = Math.max(3, Math.floor(widthPx / 7) - 2);
  if (text.length <= maxChars) return text;
  return text.slice(0, maxChars - 1) + "…";
}

function kindLabel(k) {
  return ({ l: "load-generator", s: "server", c: "client", i: "internal" })[k] || k;
}

function spanIdFor(id) {
  // deterministic-looking hex
  let h = 0;
  for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) >>> 0;
  return ("00000000000000" + h.toString(16)).slice(-16);
}

function parentSpanId(s, trace) {
  if (s.depth === 0) return "—";
  // pick last span with depth = s.depth - 1 whose range covers s.start
  const candidates = trace.spans.filter(p => p.depth === s.depth - 1 && p.start <= s.start && (p.start + p.dur) >= (s.start + s.dur));
  const parent = candidates[candidates.length - 1] || trace.spans.find(p => p.depth === s.depth - 1);
  return parent ? spanIdFor(parent.id) : "—";
}

// ─── Trace Graph view: directed graph (vertical flow)
function TraceGraphView({ trace }) {
  // Build a simple service-call graph from spans (chain by depth pair)
  const W = 1100, H = 540;
  const nodes = [
    { id: "lg",  label: "load-generator", x: 80,  y: 240,  color: SPAN_COLOR.blue },
    { id: "fp",  label: "frontend-proxy", x: 260, y: 240,  color: SPAN_COLOR.green },
    { id: "fe",  label: "frontend",       x: 460, y: 240,  color: SPAN_COLOR.purple },
    { id: "pc",  label: "product-catalog",x: 720, y: 120,  color: SPAN_COLOR.green },
    { id: "ct",  label: "cart",           x: 720, y: 240,  color: SPAN_COLOR.green },
    { id: "ad",  label: "ad",             x: 720, y: 360,  color: SPAN_COLOR.green },
    { id: "rd",  label: "redis",          x: 920, y: 240,  color: SPAN_COLOR.red },
  ];
  const edges = [
    ["lg", "fp", 19],
    ["fp", "fe", 19],
    ["fe", "pc", 6],
    ["fe", "ct", 8],
    ["fe", "ad", 3],
    ["ct", "rd", 8],
  ];

  return (
    <div style={{
      flex: 1, display: "flex", flexDirection: "column",
      background: "var(--surface)", padding: 20, overflow: "auto",
    }}>
      <div style={{ fontSize: 12, color: "var(--ink-2)", marginBottom: 12 }}>
        <span className="mono" style={{ fontWeight: 600, color: "var(--ink)" }}>7 services</span>
        <span style={{ margin: "0 8px", color: "var(--muted-2)" }}>·</span>
        <span className="mono" style={{ fontWeight: 600, color: "var(--ink)" }}>{trace.spanCount} spans</span>
        <span style={{ margin: "0 8px", color: "var(--muted-2)" }}>·</span>
        <span style={{ color: "var(--muted)" }}>showing service call graph</span>
      </div>
      <div style={{ flex: 1, minHeight: 0, position: "relative" }}>
        <svg width="100%" height="100%" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet">
          <defs>
            <pattern id="tgd" width="22" height="22" patternUnits="userSpaceOnUse">
              <circle cx=".5" cy=".5" r=".5" fill="var(--border)" />
            </pattern>
            <marker id="tg-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
              <path d="M0 0L10 5L0 10z" fill="var(--border-strong)"/>
            </marker>
          </defs>
          <rect width={W} height={H} fill="url(#tgd)" opacity=".5"/>

          {/* Edges */}
          {edges.map(([a, b, cnt], i) => {
            const na = nodes.find(n => n.id === a);
            const nb = nodes.find(n => n.id === b);
            const mx = (na.x + nb.x) / 2;
            return (
              <g key={i}>
                <path d={`M${na.x + 60} ${na.y} C ${mx} ${na.y}, ${mx} ${nb.y}, ${nb.x - 60} ${nb.y}`}
                      stroke="var(--border-strong)" strokeWidth="1.6" fill="none"
                      markerEnd="url(#tg-arrow)" opacity=".85"/>
                <g transform={`translate(${mx} ${(na.y + nb.y) / 2})`}>
                  <rect x="-14" y="-9" width="28" height="18" rx="9"
                        fill="var(--surface)" stroke="var(--border)" strokeWidth="1"/>
                  <text textAnchor="middle" dominantBaseline="middle"
                        fontSize="10" fontFamily="JetBrains Mono" fill="var(--ink-2)">
                    {cnt}
                  </text>
                </g>
              </g>
            );
          })}

          {/* Nodes */}
          {nodes.map(n => (
            <g key={n.id}>
              <rect x={n.x - 60} y={n.y - 22} width="120" height="44" rx="6"
                    fill="var(--surface)" stroke={n.color} strokeWidth="2"/>
              <circle cx={n.x - 46} cy={n.y} r="5" fill={n.color}/>
              <text x={n.x - 36} y={n.y + 4} fontSize="12"
                    fill="var(--ink)" fontWeight="600">{n.label}</text>
            </g>
          ))}
        </svg>
      </div>
    </div>
  );
}

// ─── Trace Detail main
function TraceDetailScreen({ onBack }) {
  const trace = TRACE_DETAIL;
  const [view, setView] = useStateTD("waterfall");

  return (
    <div style={{
      flex: 1, display: "flex", flexDirection: "column", minHeight: 0,
      background: "var(--surface)",
    }}>
      <TraceHeader trace={trace} onBack={onBack}/>
      <ViewTabs view={view} onView={setView} />
      {view === "waterfall" && <WaterfallView trace={trace}/>}
      {view === "flame"     && <FlameGraphView trace={trace}/>}
      {view === "graph"     && <TraceGraphView trace={trace}/>}
    </div>
  );
}

window.TraceDetailScreen = TraceDetailScreen;
