// ----- Shared UI: icons, ring, charts, sheet, toggles -----
(() => {

function Icon({ name, size = 22 }) {
  const p = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case "home": return <svg {...p}><path d="M3 10.5 12 3l9 7.5"/><path d="M5 9.5V21h14V9.5"/></svg>;
    case "compass": return <svg {...p}><circle cx="12" cy="12" r="9"/><path d="m15.5 8.5-2 5-5 2 2-5z"/></svg>;
    case "plus": return <svg {...p}><path d="M12 5v14M5 12h14"/></svg>;
    case "user": return <svg {...p}><circle cx="12" cy="8" r="4"/><path d="M4 20c1.5-3.5 4.5-5 8-5s6.5 1.5 8 5"/></svg>;
    case "chev": return <svg {...p}><path d="m6 9 6 6 6-6"/></svg>;
    case "right": return <svg {...p}><path d="M5 12h14m-6-6 6 6-6 6"/></svg>;
    case "left": return <svg {...p}><path d="M19 12H5m6 6-6-6 6-6"/></svg>;
    case "spark": return <svg {...p} fill="currentColor" stroke="none"><path d="M12 2l2.1 6.1L20 10l-5.9 1.9L12 18l-2.1-6.1L4 10l5.9-1.9z"/></svg>;
    case "shuffle": return <svg {...p}><path d="M16 3h5v5M4 20 21 3M21 16v5h-5M15 15l6 6M4 4l5 5"/></svg>;
    case "check": return <svg {...p}><path d="m4 12.5 5 5L20 6.5"/></svg>;
    case "copy": return <svg {...p}><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>;
    case "save": return <svg {...p}><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><path d="M17 21v-8H7v8M7 3v5h8"/></svg>;
    case "watch": return <svg {...p}><circle cx="12" cy="12" r="6"/><path d="M12 9v3l2 1.5M9 3h6l.6 3M9 21h6l.6-3M8.4 6 9 3M8.4 18 9 21"/></svg>;
    case "menu": return <svg {...p}><path d="M4 7h16M4 12h16M4 17h16"/></svg>;
    case "x": return <svg {...p}><path d="M6 6l12 12M18 6 6 18"/></svg>;
    case "search": return <svg {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>;
    case "send": return <svg {...p}><path d="m5 12 14-7-4 7 4 7z"/></svg>;
    default: return null;
  }
}

function Ring({ value, max, label, sub, size = 84 }) {
  const r = (size - 10) / 2;
  const circ = 2 * Math.PI * r;
  const frac = Math.max(0, Math.min(1, value / max));
  return (
    <div className="ring-wrap" style={{ width: size, height: size }}>
      <svg width={size} height={size}>
        <circle cx={size / 2} cy={size / 2} r={r} stroke="var(--line-2)" strokeWidth="7" fill="none" />
        <circle cx={size / 2} cy={size / 2} r={r} stroke="var(--blue)" strokeWidth="7" fill="none"
          strokeDasharray={`${circ * frac} ${circ}`} strokeLinecap="round"
          transform={`rotate(-90 ${size / 2} ${size / 2})`} />
      </svg>
      <div className="c">
        <div className="n">{label}</div>
        <div className="d">{sub}</div>
      </div>
    </div>
  );
}

function Spark({ data, w = 84, h = 30, color = "var(--blue)" }) {
  const min = Math.min(...data), max = Math.max(...data);
  const span = max - min || 1;
  const pts = data.map((v, i) => `${(i / (data.length - 1)) * w},${h - 4 - ((v - min) / span) * (h - 8)}`).join(" ");
  return (
    <svg className="spark" width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

// Trend chart over trial days with A/B phase bands.
// cfg: { type: "bars" | "line" | "line-roll", yMin, yMax, yTicks, roll }
function TrendChart({ values, phases, cfg, h = 150 }) {
  const W = 340, padL = 28, padB = 24, padT = 14, padR = 4;
  const n = values.length;
  const iw = (W - padL - padR) / n;
  const yMin = cfg.yMin || 0, yMax = cfg.yMax;
  const y = (v) => padT + (h - padT - padB) * (1 - (v - yMin) / (yMax - yMin));
  const phaseOf = (day) => phases.find((p) => day >= p.s && day <= p.e);

  // rolling average over logged values (window cfg.roll)
  let rollPts = null;
  if (cfg.type === "line-roll") {
    const wdw = cfg.roll || 5;
    rollPts = values.map((v, i) => {
      const lo = Math.max(0, i - wdw + 1);
      const seg = values.slice(lo, i + 1).filter((x) => x != null);
      if (v == null || seg.length < 3) return null;
      return seg.reduce((a, b) => a + b, 0) / seg.length;
    });
  }

  const lineDays = values.map((v, i) => (v == null ? null : i));
  const linePath = (arr) => {
    let d = "", started = false;
    arr.forEach((v, i) => {
      if (v == null) return;
      const cmd = started ? "L" : "M";
      d += `${cmd}${padL + i * iw + iw / 2},${y(v)} `;
      started = true;
    });
    return d;
  };

  return (
    <svg viewBox={`0 0 ${W} ${h}`} style={{ width: "100%", height: "auto", display: "block" }}>
      {cfg.yTicks.map((t) => (
        <g key={t}>
          <line x1={padL} x2={W - padR} y1={y(t)} y2={y(t)} stroke="var(--line)" strokeWidth="0.6" strokeDasharray="2 3" />
          <text x={padL - 5} y={y(t) + 3.5} textAnchor="end" fill="var(--text-4)" fontFamily="var(--mono)" fontSize="8.5">{t}</text>
        </g>
      ))}
      {phases.map((p, i) => {
        const x1 = padL + (p.s - 1) * iw, x2 = padL + p.e * iw;
        return (
          <g key={i}>
            {p.type === "B" && <rect x={x1} y={padT} width={x2 - x1} height={h - padT - padB} fill="var(--blue-dim)" opacity="0.5" />}
            <text x={(x1 + x2) / 2} y={h - 7} textAnchor="middle" fill="var(--text-3)" fontFamily="var(--mono)" fontSize="8.5">{p.short || p.type}</text>
          </g>
        );
      })}
      {cfg.type === "bars" && values.map((v, i) => {
        if (v == null) return null;
        const ph = phaseOf(i + 1);
        const isB = ph && ph.type === "B";
        const wash = ph && ph.washUntil && i + 1 <= ph.washUntil;
        return (
          <rect key={i} x={padL + i * iw + 0.8} y={y(v)} width={iw - 1.6} height={h - padB - y(v)} rx="1.5"
            fill={isB ? "var(--blue)" : "#57554e"} opacity={wash ? 0.45 : 1} />
        );
      })}
      {(cfg.type === "line" || cfg.type === "line-roll") && (
        <g>
          {cfg.type === "line" && <path d={linePath(values)} fill="none" stroke="var(--blue)" strokeWidth="1.4" opacity="0.55" />}
          {values.map((v, i) => {
            if (v == null) return null;
            const ph = phaseOf(i + 1);
            const isB = ph && ph.type === "B";
            const dim = cfg.type === "line-roll";
            return <circle key={i} cx={padL + i * iw + iw / 2} cy={y(v)} r={dim ? 2 : 3}
              fill={isB ? "var(--blue)" : "#6a6860"} opacity={dim ? 0.45 : 1} />;
          })}
          {rollPts && <path d={linePath(rollPts)} fill="none" stroke="var(--blue)" strokeWidth="2.2" strokeLinecap="round" />}
        </g>
      )}
    </svg>
  );
}

function Sheet({ onClose, children }) {
  return (
    <React.Fragment>
      <div className="sheet-scrim" onClick={onClose} />
      <div className="sheet">
        <div className="grab" />
        {children}
      </div>
    </React.Fragment>
  );
}

function Toggle({ on, onTap }) {
  return (
    <button className={`tgl ${on ? "on" : ""}`} onClick={onTap} aria-pressed={on}><i /></button>
  );
}

function Avvy({ init, col, size }) {
  return <div className="avvy" style={{ background: col, color: "#e9ecef", width: size, height: size }}>{init}</div>;
}

window.UI = { Icon, Ring, Spark, TrendChart, Sheet, Toggle, Avvy };
})();
