// Small reusable UI bits.

function Stars({ rating = 5, size = 14 }) {
  const full = Math.floor(rating);
  const half = rating - full >= 0.5;
  return (
    <div className="inline-flex items-center gap-[2px]" style={{ color: '#ffc94a' }}>
      {Array.from({ length: 5 }).map((_, i) => {
        const isFull = i < full;
        const isHalf = !isFull && i === full && half;
        return (
          <svg key={i} width={size} height={size} viewBox="0 0 24 24" fill={isFull ? 'currentColor' : isHalf ? 'url(#half)' : 'none'} stroke="currentColor" strokeWidth={isFull ? 0 : 1.4}>
            {isHalf && (
              <defs>
                <linearGradient id="half">
                  <stop offset="50%" stopColor="currentColor" />
                  <stop offset="50%" stopColor="transparent" />
                </linearGradient>
              </defs>
            )}
            <polygon points="12,2.5 14.9,9 22,9.7 16.6,14.5 18.2,21.6 12,17.9 5.8,21.6 7.4,14.5 2,9.7 9.1,9" />
          </svg>
        );
      })}
    </div>
  );
}

function Dot({ color = 'var(--ok)', pulse = true, size = 8 }) {
  return (
    <span
      className={`inline-block rounded-full ${pulse ? 'dot-live' : ''}`}
      style={{ width: size, height: size, background: color }}
    />
  );
}

function Badge({ children, tone = 'accent' }) {
  const tones = {
    accent: { bg: 'rgba(168,123,255,0.12)', color: 'var(--accent)', border: 'rgba(168,123,255,0.25)' },
    ok: { bg: 'rgba(125,243,161,0.1)', color: 'var(--ok)', border: 'rgba(125,243,161,0.25)' },
    warn: { bg: 'rgba(255,211,90,0.1)', color: 'var(--warn)', border: 'rgba(255,211,90,0.25)' },
    mute: { bg: 'rgba(255,255,255,0.04)', color: 'var(--ink-dim)', border: 'rgba(255,255,255,0.1)' },
  };
  const t = tones[tone] || tones.accent;
  return (
    <span
      className="inline-flex items-center gap-1 text-[10px] mono uppercase tracking-widest px-2 py-[3px] rounded-full"
      style={{ background: t.bg, color: t.color, border: `1px solid ${t.border}` }}
    >
      {children}
    </span>
  );
}

function Icon({ name, size = 16, stroke = 1.6 }) {
  const p = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: stroke, strokeLinecap: 'round', strokeLinejoin: 'round' };
  const paths = {
    home: <><path d="M3 10.5 12 3l9 7.5" /><path d="M5 9v12h14V9" /></>,
    grid: <><rect x="3" y="3" width="7" height="7" /><rect x="14" y="3" width="7" height="7" /><rect x="3" y="14" width="7" height="7" /><rect x="14" y="14" width="7" height="7" /></>,
    search: <><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></>,
    cart: <><path d="M3 4h2l2.5 12h11L21 7H7" /><circle cx="9" cy="20" r="1.4" /><circle cx="18" cy="20" r="1.4" /></>,
    user: <><circle cx="12" cy="8" r="4" /><path d="M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8" /></>,
    star: <polygon points="12,2.5 14.9,9 22,9.7 16.6,14.5 18.2,21.6 12,17.9 5.8,21.6 7.4,14.5 2,9.7 9.1,9" />,
    bolt: <path d="M13 2 4 14h7l-1 8 9-12h-7z" />,
    shield: <><path d="M12 2 4 6v6c0 4.7 3.3 9 8 10 4.7-1 8-5.3 8-10V6z" /><path d="m9 12 2 2 4-4" /></>,
    clock: <><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></>,
    lock: <><rect x="4" y="10" width="16" height="10" rx="2" /><path d="M8 10V7a4 4 0 0 1 8 0v3" /></>,
    check: <polyline points="4,12 10,18 20,6" />,
    arrow: <><path d="M5 12h14" /><path d="m13 6 6 6-6 6" /></>,
    x: <><path d="m6 6 12 12" /><path d="m18 6-12 12" /></>,
    copy: <><rect x="9" y="9" width="12" height="12" rx="2" /><path d="M6 15H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1" /></>,
    chev: <path d="m6 9 6 6 6-6" />,
    filter: <><path d="M3 5h18" /><path d="M6 12h12" /><path d="M10 19h4" /></>,
    info: <><circle cx="12" cy="12" r="9" /><path d="M12 8h.01M11 12h1v4h1" /></>,
    menu: <><path d="M4 6h16" /><path d="M4 12h16" /><path d="M4 18h16" /></>,
    receipt: <><path d="M6 3h12v18l-3-2-3 2-3-2-3 2z" /><path d="M9 8h6M9 12h6M9 16h4" /></>,
    refresh: <><path d="M21 12a9 9 0 1 1-3-6.7" /><path d="M21 3v5h-5" /></>,
    support: <><circle cx="12" cy="12" r="9" /><path d="M12 17h.01" /><path d="M9.5 9.5a2.5 2.5 0 1 1 3.5 2.3c-.9.4-1 .9-1 1.7" /></>,
    flame: <path d="M12 3c3 4-2 5 0 9 1.5 3-1 5-1 5 6 0 8-4 8-8 0-5-4-6-7-6z" />,
    gift: <><rect x="3" y="9" width="18" height="12" rx="1" /><path d="M3 13h18" /><path d="M12 9v12" /><path d="M7 9a3 3 0 0 1 0-6c3 0 5 6 5 6s2-6 5-6a3 3 0 0 1 0 6" /></>,
    sparkle: <><path d="M12 3v18M3 12h18" strokeWidth="1" /><path d="M12 6v12M6 12h12" /></>,
    qr: <><rect x="3" y="3" width="7" height="7" /><rect x="14" y="3" width="7" height="7" /><rect x="3" y="14" width="7" height="7" /><path d="M14 14h3v3h-3zM20 14h1M14 20h1v1M17 17h4v4M17 17v1" strokeLinecap="butt" /></>,
    dollar: <><path d="M12 3v18" /><path d="M16 7a4 3 0 0 0-4-2c-2.5 0-4 1.3-4 3s1 2.5 4 3 4 1.3 4 3-1.5 3-4 3a4 3 0 0 1-4-2" /></>,
    wallet: <><path d="M3 7h15a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z" /><path d="M3 9V6a1 1 0 0 1 1-1h12" /><circle cx="16" cy="13" r="1.3" /></>,
    eye: <><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z" /><circle cx="12" cy="12" r="3" /></>,
    download: <><path d="M12 4v12" /><path d="m7 11 5 5 5-5" /><path d="M4 20h16" /></>,
  };
  return <svg {...p}>{paths[name]}</svg>;
}

// Tiny "live counter" that ticks upward at a steady pace
function LiveCounter({ start = 100, increment = 1, interval = 3500, formatter = (n) => n.toLocaleString() }) {
  const [n, setN] = React.useState(start);
  React.useEffect(() => {
    const t = setInterval(() => setN((v) => v + increment), interval);
    return () => clearInterval(t);
  }, [increment, interval]);
  return <span>{formatter(n)}</span>;
}

// Fake QR code — deterministic pattern from string
function FakeQR({ value, size = 180 }) {
  const cells = 25;
  const cellSize = size / cells;
  let seed = 0;
  for (let i = 0; i < value.length; i++) seed = (seed * 31 + value.charCodeAt(i)) >>> 0;
  const rand = (i, j) => {
    const h = (seed ^ (i * 374761393) ^ (j * 668265263)) >>> 0;
    return (h % 100) / 100;
  };
  const isFinder = (i, j) => {
    const inBox = (ci, cj) => i >= ci && i < ci + 7 && j >= cj && j < cj + 7;
    return inBox(0, 0) || inBox(0, cells - 7) || inBox(cells - 7, 0);
  };
  const finderFill = (i, j) => {
    const box = [[0, 0], [0, cells - 7], [cells - 7, 0]].find(([ci, cj]) => i >= ci && i < ci + 7 && j >= cj && j < cj + 7);
    if (!box) return false;
    const [ci, cj] = box;
    const ri = i - ci, rj = j - cj;
    if (ri === 0 || ri === 6 || rj === 0 || rj === 6) return true;
    if (ri >= 2 && ri <= 4 && rj >= 2 && rj <= 4) return true;
    return false;
  };
  const rects = [];
  for (let i = 0; i < cells; i++) {
    for (let j = 0; j < cells; j++) {
      let fill = false;
      if (isFinder(i, j)) fill = finderFill(i, j);
      else fill = rand(i, j) > 0.55;
      if (fill) rects.push(<rect key={`${i}-${j}`} x={j * cellSize} y={i * cellSize} width={cellSize} height={cellSize} />);
    }
  }
  return (
    <div style={{ width: size, height: size, background: '#fff', padding: 8, borderRadius: 12 }}>
      <svg width={size - 16} height={size - 16} viewBox={`0 0 ${size} ${size}`} fill="#07070c">
        {rects}
      </svg>
    </div>
  );
}

function Copyable({ text, className = '' }) {
  const [copied, setCopied] = React.useState(false);
  const onCopy = () => {
    try {
      navigator.clipboard?.writeText(text);
    } catch (e) { /* noop */ }
    setCopied(true);
    setTimeout(() => setCopied(false), 1200);
  };
  return (
    <button onClick={onCopy} className={`inline-flex items-center gap-2 hairline rounded-lg px-3 py-2 mono text-xs hover:border-white/20 transition-colors ${className}`}>
      <span className="truncate">{text}</span>
      <span className="text-white/50 flex items-center gap-1">
        {copied ? <><Icon name="check" size={12} /> copied</> : <><Icon name="copy" size={12} /> copy</>}
      </span>
    </button>
  );
}

function formatUSD(n) {
  return '$' + n.toFixed(2);
}

function randomTxid() {
  const chars = 'abcdef0123456789';
  let s = '';
  for (let i = 0; i < 64; i++) s += chars[Math.floor(Math.random() * chars.length)];
  return s;
}

function randomOrderId() {
  const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
  let s = 'DS-';
  for (let i = 0; i < 4; i++) s += chars[Math.floor(Math.random() * chars.length)];
  s += '-';
  for (let i = 0; i < 4; i++) s += chars[Math.floor(Math.random() * chars.length)];
  return s;
}

function useCountdown(initialSec) {
  const [sec, setSec] = React.useState(initialSec);
  React.useEffect(() => {
    if (sec <= 0) return;
    const t = setInterval(() => setSec((s) => Math.max(0, s - 1)), 1000);
    return () => clearInterval(t);
  }, [sec]);
  const m = Math.floor(sec / 60);
  const s = sec % 60;
  return { sec, label: `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}` };
}

Object.assign(window, { Stars, Dot, Badge, Icon, LiveCounter, FakeQR, Copyable, formatUSD, randomTxid, randomOrderId, useCountdown });
