// Shared primitives: Section, Badge, Pill, OriginBadge, StatusBadge, etc.
// Also: useReveal for scroll fade-in.

const Section = ({ id, eyebrow, title, sub, children, className = "", contentClassName = "" }) =>
<section id={id} className={`relative px-6 md:px-10 ${className}`}>
    <div className="mx-auto max-w-7xl py-20 md:py-28" style={{ padding: "22px 0px" }}>
      {(eyebrow || title || sub) &&
    <div className="max-w-3xl mb-12 md:mb-16 reveal">
          {eyebrow &&
      <div className="mb-4 inline-flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-primary">
              <span className="inline-block w-6 h-px bg-primary/60" />{eyebrow}
            </div>
      }
          {title && <h2 className="text-3xl md:text-[44px] font-semibold tracking-tight leading-[1.08] text-fg">{title}</h2>}
          {sub && <p className="mt-4 text-base md:text-lg text-mutedfg leading-relaxed max-w-2xl">{sub}</p>}
        </div>
    }
      <div className={contentClassName}>
        {children}
      </div>
    </div>
  </section>;


const Eyebrow = ({ children, className = "" }) =>
<div className={`inline-flex items-center gap-2 text-[10.5px] font-semibold uppercase tracking-[0.18em] text-primary ${className}`}>
    <span className="inline-block w-4 h-px bg-primary/60" />{children}
  </div>;


const Badge = ({ tone = "neutral", children, className = "", icon }) => {
  const tones = {
    neutral: "bg-card2 border-border1 text-mutedfg",
    primary: "bg-primary/15 border-primary/35 text-primary",
    positive: "bg-positive/12 border-positive/35 text-positive",
    negative: "bg-negative/12 border-negative/35 text-negative",
    warn: "bg-warn/15 border-warn/40 text-warn",
    info: "bg-info/12 border-info/35 text-info",
    open: "border-mutedfg/40 text-mutedfg",
    ghost: "border-border1 text-mutedfg"
  };
  return (
    <span className={`inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wider ${tones[tone]} ${className}`}>
      {icon}{children}
    </span>);

};

const Pill = ({ children, active = false, onClick, className = "" }) =>
<button
  type="button"
  onClick={onClick}
  className={
  "rounded-full px-3 py-1 text-xs font-medium font-mono tracking-wider transition-colors " + (
  active ?
  "bg-primary text-primaryFg shadow-[0_0_0_1px_hsl(var(--primary)/0.5)]" :
  "bg-card2 text-mutedfg border border-border1 hover:text-fg hover:border-mutedfg/40") +
  " " + className
  }>
  
    {children}
  </button>;


const OriginBadge = ({ origin }) => {
  const palette = {
    Sync: ["bg-info/12", "text-info", "border-info/35"],
    Man: ["bg-primary/15", "text-primary", "border-primary/35"],
    OC: ["bg-positive/12", "text-positive", "border-positive/35"],
    CSV: ["bg-warn/15", "text-warn", "border-warn/35"],
    XML: ["bg-card2", "text-mutedfg", "border-border1"]
  }[origin] || ["bg-card2", "text-mutedfg", "border-border1"];
  return (
    <span className={`inline-flex items-center rounded border px-1.5 py-px text-[9.5px] font-mono font-semibold tracking-wider ${palette.join(" ")}`}>
      {origin.toUpperCase()}
    </span>);

};

const SideBadge = ({ side }) => {
  const t = side === "BUY" || side === "COVER" ? "positive" :
  side === "SELL" || side === "SHORT" ? "negative" : "neutral";
  return <Badge tone={t} className="!text-[9.5px] !px-1.5 !py-0">{side}</Badge>;
};

// Numeric formatters
const fmtUsd = (n, { sign = false, decimals = 2 } = {}) => {
  const v = Math.abs(n).toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
  const s = n < 0 ? "-" : sign ? "+" : "";
  return `${s}$${v}`;
};
const fmtNum = (n, decimals = 2) => Math.abs(n).toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
const fmtPct = (n, { sign = true, decimals = 2 } = {}) => `${sign && n > 0 ? "+" : ""}${n.toFixed(decimals)}%`;
const fmtPctSpaced = (n, d = 2) => `${n >= 0 ? "+" : "−"}${Math.abs(n).toFixed(d)}%`;

// Money: monospace +- with color
const Money = ({ value, ccy = "USD", showCcy = false, sign = false, decimals = 2, className = "" }) => {
  const positive = value >= 0;
  return (
    <span className={`font-mono tabular-nums ${positive ? "text-fg" : "text-negative"} ${className}`}>
      {value < 0 ? "-" : sign ? "+" : ""}${fmtNum(value, decimals)}
      {showCcy && <span className="ml-1 text-[10px] text-subtlefg">{ccy}</span>}
    </span>);

};
const Signed = ({ value, decimals = 2, className = "", suffix }) => {
  const positive = value >= 0;
  return (
    <span className={`font-mono tabular-nums ${positive ? "text-positive" : "text-negative"} ${className}`}>
      {positive ? "+" : "-"}${fmtNum(value, decimals)}{suffix}
    </span>);

};
const SignedPct = ({ value, decimals = 2, className = "" }) => {
  const positive = value >= 0;
  return (
    <span className={`font-mono tabular-nums ${positive ? "text-positive" : "text-negative"} ${className}`}>
      {positive ? "+" : "-"}{Math.abs(value).toFixed(decimals)}%
    </span>);

};

// Reveal on scroll
function useReveal() {
  React.useEffect(() => {
    const els = document.querySelectorAll(".reveal");
    if (!("IntersectionObserver" in window)) {
      els.forEach((e) => e.classList.add("in"));
      return;
    }
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add("in");
          io.unobserve(e.target);
        }
      });
    }, { rootMargin: "-40px 0px -40px 0px", threshold: 0.04 });
    els.forEach((e) => io.observe(e));
    return () => io.disconnect();
  }, []);
}

// Animated number — counts from start to end over ms
function AnimatedNumber({ value, decimals = 2, prefix = "", suffix = "", duration = 1500, className = "" }) {
  const [n, setN] = React.useState(0);
  const startRef = React.useRef(null);
  React.useEffect(() => {
    let raf;
    const tick = (t) => {
      if (startRef.current === null) startRef.current = t;
      const k = Math.min(1, (t - startRef.current) / duration);
      // ease-out cubic
      const e = 1 - Math.pow(1 - k, 3);
      setN(value * e);
      if (k < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [value, duration]);
  const formatted = n.toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
  return <span className={className}>{prefix}{formatted}{suffix}</span>;
}

// Mini key/value row
const KV = ({ label, children, className = "" }) =>
<div className={`flex items-center justify-between gap-3 py-1.5 ${className}`}>
    <span className="text-[11px] font-semibold uppercase tracking-wider text-subtlefg">{label}</span>
    <span className="font-mono text-xs text-fg">{children}</span>
  </div>;


// Hairline divider
const HR = ({ className = "" }) => <div className={`h-px bg-border1 ${className}`} />;

Object.assign(window, {
  Section, Eyebrow, Badge, Pill, OriginBadge, SideBadge,
  fmtUsd, fmtNum, fmtPct, fmtPctSpaced,
  Money, Signed, SignedPct, KV, HR,
  useReveal, AnimatedNumber
});