// OKRDeck.jsx — Tinder-style stacked OKR card deck

const { useState, useRef, useEffect, useCallback } = React;

// ─────────────────────────────────────────────────────────────
// Swipe-deck physics
// ─────────────────────────────────────────────────────────────
function useSwipe({ onSwipe, onRelease, threshold = 110 }) {
  const [drag, setDrag] = useState({ x: 0, y: 0, active: false });
  // Track the pending gesture before we commit to a horizontal drag. We don't
  // capture the pointer (or mark drag.active) until we're sure the user is
  // swiping horizontally, otherwise vertical native scroll inside the card
  // body is impossible.
  const start = useRef(null);

  const onPointerDown = (e) => {
    start.current = { x: e.clientX, y: e.clientY, pointerId: e.pointerId, captured: false };
    setDrag({ x: 0, y: 0, active: false });
  };
  const onPointerMove = (e) => {
    if (!start.current) return;
    if (!e.buttons && e.pointerType === "mouse") return;
    const dx = e.clientX - start.current.x;
    const dy = e.clientY - start.current.y;
    if (!drag.active) {
      if (Math.abs(dx) > 8 && Math.abs(dx) > Math.abs(dy)) {
        if (!start.current.captured) {
          e.currentTarget.setPointerCapture?.(e.pointerId);
          start.current.captured = true;
        }
        setDrag({ x: dx, y: dy, active: true });
      } else if (Math.abs(dy) > 8) {
        // Vertical dominance — let the inner content scroll, abort the gesture.
        start.current = null;
      }
      return;
    }
    setDrag({ x: dx, y: dy, active: true });
  };
  const onPointerUp = () => {
    const wasActive = drag.active;
    start.current = null;
    if (!wasActive) {
      setDrag({ x: 0, y: 0, active: false });
      return;
    }
    const { x } = drag;
    if (Math.abs(x) > threshold) {
      onSwipe?.(x > 0 ? "right" : "left");
    } else {
      onRelease?.();
    }
    setDrag({ x: 0, y: 0, active: false });
  };

  return {
    drag,
    setDrag,
    handlers: {
      onPointerDown,
      onPointerMove,
      onPointerUp,
      onPointerCancel: onPointerUp,
    },
  };
}

// ─────────────────────────────────────────────────────────────
// Direction pill — shows the orderflow-derived BULLISH / BEARISH bias
// for the cell. When `vetoed` is true the badge gets a subtle outline,
// signaling that orderflow overrode the rule-based regime call.
// ─────────────────────────────────────────────────────────────
function DirectionBadge({ direction, vetoed }) {
  const isBull = direction === "BULLISH";
  const color = isBull ? "var(--color-success, #0b6b3a)" : "var(--color-danger, #b03a2e)";
  const bg = isBull ? "rgba(11,107,58,0.10)" : "rgba(176,58,46,0.10)";
  const arrow = isBull ? "▲" : "▼";
  return (
    <span style={{
      display: "inline-flex",
      alignItems: "center",
      gap: 4,
      padding: "2px 8px",
      borderRadius: 999,
      background: bg,
      border: vetoed ? `1px dashed ${color}` : `1px solid transparent`,
      color,
      fontFamily: "var(--font-family-sans)",
      fontWeight: 600,
      fontSize: 10,
      letterSpacing: "0.06em",
      textTransform: "uppercase",
      lineHeight: 1,
      whiteSpace: "nowrap",
    }}>
      <span style={{ fontSize: 9 }}>{arrow}</span>
      {direction}
      {vetoed && <span style={{ opacity: 0.7, fontSize: 8 }}>· vetoed</span>}
    </span>
  );
}

// ─────────────────────────────────────────────────────────────
// Chart skeleton — animated "candle bars" that read as a chart loading,
// not generic shimmer. Theme-aware via CSS vars; the bar heights are fixed
// so the pattern doesn't reshuffle on each render.
// ─────────────────────────────────────────────────────────────
const CHART_SKELETON_BARS = [
  0.42, 0.58, 0.36, 0.71, 0.49, 0.83, 0.55,
  0.68, 0.40, 0.75, 0.52, 0.88, 0.61, 0.45,
  0.70, 0.38, 0.66, 0.79,
];

function ChartSkeleton() {
  return (
    <div
      aria-hidden
      style={{
        position: "absolute", inset: 0,
        display: "flex",
        alignItems: "flex-end",
        justifyContent: "space-between",
        padding: "14% 6% 18%",
        gap: 4,
        // Subtle baseline so the bars feel rooted to a chart axis
        background:
          "linear-gradient(180deg, transparent 0%, transparent 82%, var(--color-border-subtle) 82%, var(--color-border-subtle) 82.5%, transparent 82.5%)",
      }}
    >
      {CHART_SKELETON_BARS.map((h, i) => (
        <span
          key={i}
          style={{
            display: "block",
            flex: 1,
            minWidth: 0,
            height: `${Math.round(h * 100)}%`,
            background: "var(--color-text-muted, #8a8a8a)",
            borderRadius: 2,
            opacity: 0.18,
            transformOrigin: "bottom",
            animation: `tw-chart-pulse 1600ms ease-in-out ${i * 70}ms infinite`,
          }}
        />
      ))}
      <style>{`
        @keyframes tw-chart-pulse {
          0%, 100% { opacity: 0.12; transform: scaleY(0.85); }
          50%      { opacity: 0.34; transform: scaleY(1.04); }
        }
      `}</style>
    </div>
  );
}

// Chart slot — animated skeleton until loaded, fade-in on first paint. Only
// the top card (`active`) requests the image; cards behind the top card hold
// the layout slot with a static skeleton so the swap-in is seamless.
function ChartSlot({ okr, active }) {
  const [loaded, setLoaded] = useState(false);
  const [errored, setErrored] = useState(false);

  // Reset state when the chart URL changes (e.g. theme toggle replaces all charts).
  useEffect(() => {
    setLoaded(false);
    setErrored(false);
  }, [okr.chart_url]);

  if (errored) return null;

  return (
    <div
      style={{
        position: "relative",
        width: "100%",
        aspectRatio: "360 / 220",
        background: "var(--color-surface-subtle)",
        border: "1px solid var(--color-border-subtle)",
        borderRadius: 6,
        overflow: "hidden",
      }}
    >
      {!loaded && <ChartSkeleton />}
      {active && (
        <img
          src={okr.chart_url}
          alt={`${okr.tag} chart`}
          decoding="async"
          draggable={false}
          onLoad={() => setLoaded(true)}
          onError={() => setErrored(true)}
          style={{
            position: "absolute", inset: 0,
            display: "block",
            width: "100%", height: "100%",
            objectFit: "cover",
            opacity: loaded ? 1 : 0,
            transition: "opacity 320ms var(--ease-standard, ease-out)",
          }}
        />
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Single OKR card (front of stack)
// ─────────────────────────────────────────────────────────────
function OKRCard({ okr, drag, onSwipe, onRelease, swipeHandlers, exiting, depth = 0 }) {
  // Depth = 0 is top card; higher numbers are behind
  const isTop = depth === 0;

  // Apply drag-driven transform OR exit transform OR rest transform
  let tx = 0, ty = 0, rot = 0, scale = 1 - depth * 0.04, opacity = 1;

  if (depth > 0) {
    ty = depth * 14;
    opacity = depth > 2 ? 0 : 1 - depth * 0.18;
  }

  if (exiting) {
    tx = exiting === "right" ? 800 : -800;
    rot = exiting === "right" ? 24 : -24;
    opacity = 0;
  } else if (isTop && drag.active) {
    tx = drag.x;
    ty = drag.y * 0.3;
    rot = drag.x / 18;
  }

  const transition = drag.active && isTop
    ? "none"
    : `transform 380ms var(--ease-standard, cubic-bezier(.2,0,0,1)), opacity 280ms var(--ease-standard, cubic-bezier(.2,0,0,1))`;

  // Direction badge intensity
  const likeOpacity = isTop && drag.active ? Math.min(1, Math.max(0, drag.x / 120)) : 0;
  const passOpacity = isTop && drag.active ? Math.min(1, Math.max(0, -drag.x / 120)) : 0;

  return (
    <div
      {...(isTop ? swipeHandlers : {})}
      style={{
        position: "absolute",
        inset: 0,
        transform: `translate3d(${tx}px, ${ty}px, 0) rotate(${rot}deg) scale(${scale})`,
        opacity,
        transition,
        // pan-y lets the browser scroll the card body vertically while the
        // swipe gesture handles horizontal drags.
        touchAction: "pan-y",
        zIndex: 100 - depth,
        cursor: isTop ? (drag.active ? "grabbing" : "grab") : "default",
        pointerEvents: isTop ? "auto" : "none",
      }}
    >
      <div
        style={{
          height: "100%",
          width: "100%",
          background: "var(--color-surface-default)",
          border: "1px solid var(--color-border-subtle)",
          borderRadius: "var(--radius-md)",
          boxShadow: depth === 0 ? "var(--shadow-3)" : "var(--shadow-1)",
          boxSizing: "border-box",
          position: "relative",
          overflow: "hidden",
        }}
      >
        {/* Top accent stripe */}
        <div
          aria-hidden
          style={{
            position: "absolute",
            top: 0, left: 0, right: 0,
            height: 4,
            background: "var(--color-brand-primary)",
            zIndex: 2,
          }}
        />

        {/* Decision stamps */}
        <Stamp label="TRADE THIS" tone="success" opacity={likeOpacity} rotate={-12} />
        <Stamp label="SKIP" tone="muted" opacity={passOpacity} rotate={12} side="right" />

        {/* Scrollable body — accent stripe and stamps stay outside, anchored
            to the card frame, so they don't scroll with the content. */}
        <div style={{
          position: "absolute",
          inset: 0,
          padding: "22px 22px 20px",
          boxSizing: "border-box",
          display: "flex",
          flexDirection: "column",
          gap: 18,
          overflowY: "auto",
          WebkitOverflowScrolling: "touch",
        }}>
          {/* Eyebrow */}
          <div style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
            gap: 8,
            paddingTop: 6,
          }}>
            <div style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}>
              <span className="ds-overline" style={{
                color: "var(--color-brand-primary)",
                whiteSpace: "nowrap",
                overflow: "hidden",
                textOverflow: "ellipsis",
              }}>
                {okr.tag}
              </span>
              {okr.direction && okr.direction !== "NEUTRAL" && (
                <DirectionBadge direction={okr.direction} vetoed={okr.orderflow_veto} />
              )}
            </div>
            <span className="ds-caption" style={{ whiteSpace: "nowrap" }}>Scan · Today</span>
          </div>

          {/* Objective — big display type */}
          <h2 style={{
            margin: 0,
            fontFamily: "var(--font-family-sans)",
            fontWeight: 600,
            fontSize: 28,
            lineHeight: "34px",
            letterSpacing: "-0.01em",
            color: "var(--color-text-primary)",
            textWrap: "balance",
          }}>
            {okr.objective}
          </h2>

          <p className="ds-body-sm" style={{ margin: 0, color: "var(--color-text-secondary)" }}>
            {okr.summary}
          </p>

          {/* Chart thumbnail with skeleton; only the top card fetches. */}
          {okr.chart_url && <ChartSlot okr={okr} active={isTop} />}

          {/* Key results */}
          <div style={{
            marginTop: "auto",
            display: "flex",
            flexDirection: "column",
            gap: 10,
            borderTop: "1px solid var(--color-border-subtle)",
            paddingTop: 16,
          }}>
            <div className="ds-overline" style={{ color: "var(--color-text-muted)", fontSize: 11, letterSpacing: ".14em" }}>
              Scan signals
            </div>
            {okr.krs.map((kr, i) => (
              <div key={kr.id} style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
                <span style={{
                  fontFamily: "var(--font-family-sans)",
                  fontWeight: 600,
                  fontSize: 13,
                  color: "var(--color-brand-primary)",
                  fontVariantNumeric: "tabular-nums",
                  minWidth: 18,
                  paddingTop: 2,
                }}>
                  S{i + 1}
                </span>
                <span className="ds-body-sm" style={{ color: "var(--color-text-primary)", flex: 1 }}>
                  {kr.label}
                </span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function Stamp({ label, tone, opacity, rotate, side = "left" }) {
  const colors = {
    success: { fg: "var(--color-success)", bg: "rgba(11,107,58,0.06)" },
    muted: { fg: "var(--color-text-secondary)", bg: "rgba(89,89,89,0.06)" },
  }[tone] || {};
  return (
    <div
      aria-hidden
      style={{
        position: "absolute",
        top: 36,
        [side]: 22,
        padding: "8px 14px",
        border: `2px solid ${colors.fg}`,
        color: colors.fg,
        background: colors.bg,
        borderRadius: 6,
        fontFamily: "var(--font-family-sans)",
        fontWeight: 700,
        fontSize: 13,
        letterSpacing: "0.14em",
        transform: `rotate(${rotate}deg)`,
        opacity,
        transition: "opacity 80ms linear",
        pointerEvents: "none",
        zIndex: 5,
      }}
    >
      {label}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Main deck
// ─────────────────────────────────────────────────────────────
function formatScanAge(isoStr) {
  if (!isoStr) return "";
  const ms = Date.now() - new Date(isoStr).getTime();
  if (!isFinite(ms) || ms < 0) return "";
  const min = Math.floor(ms / 60000);
  if (min < 1) return "just now";
  if (min < 60) return `${min}m ago`;
  const hr = Math.floor(min / 60);
  if (hr < 24) return `${hr}h ago`;
  return `${Math.floor(hr / 24)}d ago`;
}

function RefreshButton({ refreshStatus, onRefresh }) {
  const status = refreshStatus?.status || "idle";
  const busy = status === "dispatching" || status === "waiting";
  const label = busy ? "Refreshing…" : "Refresh";
  return (
    <button
      onClick={() => onRefresh?.("full")}
      disabled={busy}
      title="Re-run scan + TA + visual"
      style={{
        display: "inline-flex",
        alignItems: "center",
        gap: 6,
        padding: "4px 10px",
        borderRadius: "var(--radius-pill)",
        border: "1px solid var(--color-border-subtle)",
        background: "var(--color-surface-subtle, transparent)",
        color: busy ? "var(--color-text-muted)" : "var(--color-text-secondary)",
        fontFamily: "var(--font-family-sans)",
        fontSize: 11,
        fontWeight: 600,
        letterSpacing: "0.02em",
        cursor: busy ? "wait" : "pointer",
        transition: "background var(--motion-base) var(--ease-standard)",
      }}
    >
      <svg
        width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
        strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"
        style={busy ? { animation: "tw-spin 1.1s linear infinite" } : undefined}
      >
        <polyline points="23 4 23 10 17 10" />
        <polyline points="1 20 1 14 7 14" />
        <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" />
      </svg>
      {label}
    </button>
  );
}

function OKRDeck({ okrs, onContinue, scanAsOf, scanSource, refreshStatus, onRefresh }) {
  const [index, setIndex] = useState(0);
  const [exiting, setExiting] = useState(null); // 'left'|'right'|null
  const [passed, setPassed] = useState([]); // ids passed
  const [picks, setPicks] = useState([]);   // OKRs the user wants to validate

  const visible = okrs.slice(index, index + 3);
  const current = visible[0];

  // Reset local pick state when the underlying scan changes — a fresh deck
  // shouldn't carry over picks from the previous as_of.
  useEffect(() => {
    setIndex(0); setExiting(null); setPassed([]); setPicks([]);
  }, [scanAsOf]);

  const advance = useCallback((direction, okr) => {
    setExiting(direction);
    setTimeout(() => {
      if (direction === "right") {
        setPicks((p) => (p.find((x) => x.id === okr.id) ? p : [...p, okr]));
      } else {
        setPassed((p) => [...p, okr.id]);
      }
      setIndex((i) => i + 1);
      setExiting(null);
    }, 320);
  }, []);

  const { drag, setDrag, handlers } = useSwipe({
    threshold: 110,
    onSwipe: (dir) => current && advance(dir, current),
    onRelease: () => setDrag({ x: 0, y: 0, active: false }),
  });

  const handleAction = (dir) => {
    if (!current || exiting) return;
    // Animate from rest to target before advancing
    setDrag({ x: dir === "right" ? 240 : -240, y: 0, active: false });
    setTimeout(() => {
      setDrag({ x: 0, y: 0, active: false });
      advance(dir, current);
    }, 200);
  };

  const allDone = index >= okrs.length;

  return (
    <div style={{
      display: "flex",
      flexDirection: "column",
      height: "100%",
      padding: "0 20px 20px",
      gap: 16,
      boxSizing: "border-box",
    }}>
      {/* Header */}
      <header style={{ paddingTop: 6 }}>
        <div style={{
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          gap: 8,
          marginBottom: 4,
        }}>
          <span className="ds-overline" style={{ color: "var(--color-text-muted)" }}>
            {scanSource === "live" ? "Regime scan · Live" : "Regime scan · Demo"}
            {scanAsOf ? ` · ${formatScanAge(scanAsOf)}` : ""}
          </span>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            {onRefresh && (
              <RefreshButton refreshStatus={refreshStatus} onRefresh={onRefresh} />
            )}
            <span className="ds-caption ds-numeric" style={{ color: "var(--color-text-muted)" }}>
              {Math.min(index + 1, okrs.length)} / {okrs.length}
              {picks.length > 0 ? ` · ${picks.length} picked` : ""}
            </span>
          </div>
        </div>
        <h1 style={{
          margin: 0,
          fontFamily: "var(--font-family-sans)",
          fontWeight: 600,
          fontSize: 22,
          lineHeight: "28px",
          letterSpacing: "-0.005em",
          color: "var(--color-text-primary)",
          textWrap: "balance",
        }}>
          Which market regime are you trading today?
        </h1>
        {refreshStatus?.status === "waiting" && (
          <div className="ds-caption" style={{ color: "var(--color-text-muted)", marginTop: 4 }}>
            Refreshing scan + TA + visual… (~{refreshStatus.eta_seconds}s)
          </div>
        )}
        {refreshStatus?.status === "error" && (
          <div style={{ marginTop: 4 }}>
            <div className="ds-caption" style={{ color: "var(--color-danger, #b03a2e)" }}>
              Refresh failed: {refreshStatus.error}
              {refreshStatus.retry_after ? ` · retry in ${refreshStatus.retry_after}s` : ""}
            </div>
            {refreshStatus.detail && (
              <div className="ds-caption" style={{
                color: "var(--color-text-muted)",
                fontSize: 10,
                marginTop: 2,
                fontFamily: "var(--font-family-mono, monospace)",
                wordBreak: "break-word",
              }}>
                {String(refreshStatus.detail).slice(0, 200)}
              </div>
            )}
          </div>
        )}
      </header>

      {/* Stack arena */}
      <div style={{ flex: 1, position: "relative", minHeight: 0 }}>
        {allDone ? (
          <DeckSummary
            pickCount={picks.length}
            passedCount={passed.length}
            onScanMore={onRefresh ? () => { onRefresh?.("full"); } : null}
            onContinue={picks.length > 0 ? () => onContinue?.(picks) : null}
            refreshStatus={refreshStatus}
          />
        ) : (
          [...visible].reverse().map((okr) => {
            const depth = visible.indexOf(okr);
            return (
              <OKRCard
                key={okr.id}
                okr={okr}
                depth={depth}
                drag={depth === 0 ? drag : { x: 0, y: 0, active: false }}
                swipeHandlers={handlers}
                exiting={depth === 0 ? exiting : null}
              />
            );
          })
        )}
      </div>

      {/* Action bar */}
      {!allDone && (
        <div style={{
          display: "flex",
          gap: 12,
          alignItems: "center",
          justifyContent: "center",
          paddingTop: 4,
        }}>
          <ActionButton
            kind="pass"
            disabled={!current}
            onClick={() => handleAction("left")}
            ariaLabel="Skip this opportunity"
          />
          <ActionHint />
          <ActionButton
            kind="pick"
            disabled={!current}
            onClick={() => handleAction("right")}
            ariaLabel="Trade this opportunity"
          />
        </div>
      )}
    </div>
  );
}

function ActionButton({ kind, onClick, disabled, ariaLabel }) {
  const isPick = kind === "pick";
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      aria-label={ariaLabel}
      style={{
        width: 64,
        height: 64,
        borderRadius: "50%",
        border: "1.5px solid",
        borderColor: isPick ? "var(--color-brand-primary)" : "var(--color-border-subtle)",
        background: isPick ? "var(--color-brand-primary)" : "var(--color-surface-default)",
        color: isPick ? "var(--color-text-on-brand)" : "var(--color-text-secondary)",
        cursor: disabled ? "not-allowed" : "pointer",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        boxShadow: isPick ? "var(--shadow-2)" : "none",
        transition: "transform var(--motion-fast) var(--ease-standard), background var(--motion-base) var(--ease-standard)",
      }}
      onMouseDown={(e) => (e.currentTarget.style.transform = "scale(0.92)")}
      onMouseUp={(e) => (e.currentTarget.style.transform = "scale(1)")}
      onMouseLeave={(e) => (e.currentTarget.style.transform = "scale(1)")}
    >
      {isPick ? (
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
          <polyline points="20 6 9 17 4 12" />
        </svg>
      ) : (
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
          <line x1="18" y1="6" x2="6" y2="18" />
          <line x1="6" y1="6" x2="18" y2="18" />
        </svg>
      )}
    </button>
  );
}

function ActionHint() {
  return (
    <div style={{
      flex: "0 0 auto",
      display: "flex",
      flexDirection: "column",
      alignItems: "center",
      gap: 2,
      padding: "0 12px",
    }}>
      <span className="ds-caption" style={{ color: "var(--color-text-muted)" }}>
        Swipe or tap
      </span>
      <div style={{ display: "flex", gap: 4, alignItems: "center" }}>
        <span style={{ fontSize: 11, color: "var(--color-text-muted)" }}>←&nbsp;skip</span>
        <span style={{ fontSize: 11, color: "var(--color-text-muted)" }}>·</span>
        <span style={{ fontSize: 11, color: "var(--color-brand-primary)", fontWeight: 600 }}>trade&nbsp;→</span>
      </div>
    </div>
  );
}

function DeckSummary({ pickCount, passedCount, onScanMore, onContinue, refreshStatus }) {
  const busy = refreshStatus?.status === "dispatching" || refreshStatus?.status === "waiting";
  const noPicks = pickCount === 0;
  return (
    <div style={{
      position: "absolute",
      inset: 0,
      display: "flex",
      flexDirection: "column",
      alignItems: "center",
      justifyContent: "center",
      textAlign: "center",
      padding: 32,
      gap: 14,
      background: "var(--color-surface-subtle)",
      border: "1px dashed var(--color-border-subtle)",
      borderRadius: "var(--radius-md)",
    }}>
      <div className="ds-h3" style={{ color: "var(--color-text-primary)" }}>
        {noPicks ? "Nothing picked yet" : `${pickCount} opportunit${pickCount === 1 ? "y" : "ies"} picked`}
      </div>
      <p className="ds-body-sm" style={{ color: "var(--color-text-secondary)", margin: 0, maxWidth: 280 }}>
        {noPicks
          ? "You skipped every card. Run a fresh scan or sit this one out — flat is a position too."
          : `Skipped ${passedCount}. Continue to validate your picks against Hyperliquid, or scan again for a fresh deck.`}
      </p>
      <div style={{ display: "flex", gap: 10, marginTop: 4, flexWrap: "wrap", justifyContent: "center" }}>
        {onScanMore && (
          <button
            onClick={onScanMore}
            disabled={busy}
            style={{
              padding: "10px 18px",
              background: noPicks ? "var(--color-brand-primary)" : "var(--color-surface-default)",
              color: noPicks ? "var(--color-text-on-brand)" : "var(--color-text-primary)",
              border: noPicks ? "none" : "1px solid var(--color-border-subtle)",
              borderRadius: "var(--radius-sm)",
              fontFamily: "var(--font-family-sans)",
              fontWeight: 600,
              fontSize: 14,
              cursor: busy ? "wait" : "pointer",
              opacity: busy ? 0.6 : 1,
            }}
          >
            {busy ? "Scanning…" : "Scan more"}
          </button>
        )}
        {onContinue && (
          <button
            onClick={onContinue}
            style={{
              padding: "10px 18px",
              background: "var(--color-brand-primary)",
              color: "var(--color-text-on-brand)",
              border: "none",
              borderRadius: "var(--radius-sm)",
              fontFamily: "var(--font-family-sans)",
              fontWeight: 600,
              fontSize: 14,
              cursor: "pointer",
              display: "inline-flex",
              alignItems: "center",
              gap: 8,
            }}
          >
            Continue
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <polyline points="9 18 15 12 9 6" />
            </svg>
          </button>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { OKRDeck });
