// IVE Mobile — the instrument: interactive EB×SC plane, decay curve, mini plane
const { IVE_C: CH } = window;
const { useTh } = window;
const ACC2 = 'var(--ive-ochre)';

// ── Interactive EB × SC score plane ──────────────────────────────
// Controlled probe: parent owns {eb,sc}; drag/tap to scrub. The claim's
// scored point is fixed; the probe reads out any coordinate + names its zone.
function ScorePlaneLive({ claim, probe, onProbe, size = 300 }) {
  const th = useTh();
  const ref = React.useRef(null);
  const pad = 30;
  const inner = size - pad * 2;
  const toXY = (eb, sc) => [pad + eb * inner, pad + (1 - sc) * inner];
  const fromEvt = (e) => {
    const r = ref.current.getBoundingClientRect();
    const px = (e.touches ? e.touches[0].clientX : e.clientX) - r.left;
    const py = (e.touches ? e.touches[0].clientY : e.clientY) - r.top;
    const eb = Math.max(0, Math.min(1, (px / r.width * size - pad) / inner));
    const sc = Math.max(0, Math.min(1, 1 - (py / r.height * size - pad) / inner));
    return { eb: Math.round(eb * 100) / 100, sc: Math.round(sc * 100) / 100 };
  };
  const [drag, setDrag] = React.useState(false);
  const start = (e) => { e.preventDefault(); setDrag(true); onProbe(fromEvt(e)); };
  const move = (e) => { if (drag) { e.preventDefault(); onProbe(fromEvt(e)); } };
  const end = () => setDrag(false);

  const [cx, cy] = toXY(claim.eb, claim.sc);
  const [px, py] = toXY(probe.eb, probe.sc);
  const zx = pad + 0.66 * inner;
  const zy = pad + (1 - 0.66) * inner;
  const lab = th.dark ? 'rgba(244,239,227,0.5)' : CH.ink3;
  const gridc = th.dark ? 'rgba(244,239,227,0.55)' : CH.ink;

  return (
    <svg ref={ref} viewBox={`0 0 ${size} ${size}`} width="100%"
      style={{ display: 'block', touchAction: 'none', cursor: 'crosshair', userSelect: 'none' }}
      onMouseDown={start} onMouseMove={move} onMouseUp={end} onMouseLeave={end}
      onTouchStart={start} onTouchMove={move} onTouchEnd={end}>
      {/* canonical "verified" zone */}
      <rect x={zx} y={pad} width={(pad + inner) - zx} height={zy - pad} fill={CH.ochre} opacity="0.09" />
      <line x1={zx} y1={pad} x2={zx} y2={pad + inner} stroke={CH.ochre} strokeWidth="0.5" strokeDasharray="2 3" opacity="0.5" />
      <line x1={pad} y1={zy} x2={pad + inner} y2={zy} stroke={CH.ochre} strokeWidth="0.5" strokeDasharray="2 3" opacity="0.5" />
      {/* grid */}
      {Array.from({ length: 11 }).map((_, i) => (
        <g key={i}>
          <line x1={pad + (i / 10) * inner} y1={pad} x2={pad + (i / 10) * inner} y2={pad + inner}
            stroke={gridc} strokeWidth={i % 5 === 0 ? 0.5 : 0.3} opacity={i % 5 === 0 ? 0.28 : 0.12} />
          <line x1={pad} y1={pad + (i / 10) * inner} x2={pad + inner} y2={pad + (i / 10) * inner}
            stroke={gridc} strokeWidth={i % 5 === 0 ? 0.5 : 0.3} opacity={i % 5 === 0 ? 0.28 : 0.12} />
        </g>
      ))}
      {/* axes */}
      <line x1={pad} y1={pad + inner} x2={pad + inner} y2={pad + inner} stroke={gridc} strokeWidth="1" opacity="0.7" />
      <line x1={pad} y1={pad} x2={pad} y2={pad + inner} stroke={gridc} strokeWidth="1" opacity="0.7" />
      <text x={pad + inner / 2} y={size - 8} textAnchor="middle" fontFamily="var(--ive-mono)" fontSize="8" letterSpacing="1.4" fill={lab}>EVIDENCE BASIS →</text>
      <text x={11} y={pad + inner / 2} textAnchor="middle" fontFamily="var(--ive-mono)" fontSize="8" letterSpacing="1.4" fill={lab} transform={`rotate(-90 11 ${pad + inner / 2})`}>SOCIAL CONSENSUS →</text>

      {/* claim's scored point */}
      <circle cx={cx} cy={cy} r="5" fill={CH.ink} stroke={th.dark ? th.bg : CH.paper} strokeWidth="1.5" />
      {/* probe crosshair */}
      <line x1={px} y1={pad} x2={px} y2={pad + inner} stroke={CH.ochre} strokeWidth="0.7" opacity="0.6" />
      <line x1={pad} y1={py} x2={pad + inner} y2={py} stroke={CH.ochre} strokeWidth="0.7" opacity="0.6" />
      <circle cx={px} cy={py} r="7" fill="none" stroke={CH.ochre} strokeWidth="1.4" />
      <rect x={px - 1.5} y={py - 1.5} width="3" height="3" fill={CH.ochre} />
    </svg>
  );
}

// Names the quadrant/zone a coordinate falls in.
function zoneName(eb, sc) {
  if (eb >= 0.66 && sc >= 0.66) return 'Verified zone — evidence and consensus agree';
  if (eb >= 0.66 && sc < 0.45) return 'Suppressed — strong evidence, low consensus';
  if (eb < 0.45 && sc >= 0.66) return 'Received wisdom — high consensus, thin evidence';
  if (eb < 0.45 && sc < 0.45) return 'Open ground — neither established';
  return 'Contested middle — partial on both axes';
}

// ── Sub-weight bars ──────────────────────────────────────────────
function WeightBars({ title, parts }) {
  const th = useTh();
  return (
    <div>
      <div className="ive-mono" style={{ fontSize: 9, letterSpacing: '0.14em', textTransform: 'uppercase', color: th.ink3, marginBottom: 10 }}>{title}</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 9 }}>
        {parts.map(([label, v]) => (
          <div key={label} style={{ display: 'grid', gridTemplateColumns: '108px 1fr 32px', gap: 10, alignItems: 'center' }}>
            <span className="ive-serif" style={{ fontSize: 12, color: th.ink2, fontWeight: 300 }}>{label}</span>
            <div style={{ height: 3, background: th.ruleSoft, position: 'relative' }}>
              <div style={{ position: 'absolute', inset: 0, width: `${v * 100}%`, background: v >= 0.66 ? CH.ochre : th.ink3 }} />
            </div>
            <span className="ive-mono" style={{ fontSize: 11, color: th.ink2, textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}>{v.toFixed(2)}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Decay curve ──────────────────────────────────────────────────
function DecayCurve({ halfLife, ageDays, decay, height = 120 }) {
  const th = useTh();
  const W = 320, H = height, pad = 8;
  const infinite = halfLife >= 36500;
  // window: 3 half-lives or 1.4× current age, whichever is larger
  const span = infinite ? Math.max(ageDays * 2, 365) : Math.max(halfLife * 3, ageDays * 1.3);
  const val = (d) => infinite ? 1 : Math.pow(2, -d / halfLife);
  const x = (d) => pad + (d / span) * (W - pad * 2);
  const y = (v) => pad + (1 - v) * (H - pad * 2 - 14);
  const pts = Array.from({ length: 60 }).map((_, i) => {
    const d = (i / 59) * span; return `${x(d)},${y(val(d))}`;
  }).join(' ');
  const threshold = 0.7; // recheck flag
  const gridc = th.dark ? 'rgba(244,239,227,0.5)' : CH.ink;
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: 'block' }}>
      {/* recheck threshold */}
      {!infinite && (
        <>
          <line x1={pad} y1={y(threshold)} x2={W - pad} y2={y(threshold)} stroke={CH.disputed} strokeWidth="0.6" strokeDasharray="3 3" opacity="0.6" />
          <text x={W - pad} y={y(threshold) - 4} textAnchor="end" fontFamily="var(--ive-mono)" fontSize="7.5" letterSpacing="0.8" fill={CH.disputed} opacity="0.85">RECHECK · 0.70</text>
        </>
      )}
      {/* axis */}
      <line x1={pad} y1={H - pad - 14} x2={W - pad} y2={H - pad - 14} stroke={gridc} strokeWidth="0.7" opacity="0.6" />
      {/* curve */}
      <polyline points={pts} fill="none" stroke={th.ink2} strokeWidth="1.4" />
      {/* current position */}
      <line x1={x(ageDays)} y1={pad} x2={x(ageDays)} y2={H - pad - 14} stroke={CH.ochre} strokeWidth="0.8" />
      <circle cx={x(ageDays)} cy={y(val(ageDays))} r="4" fill={CH.ochre} />
      <text x={x(ageDays)} y={H - 4} textAnchor="middle" fontFamily="var(--ive-mono)" fontSize="7.5" letterSpacing="0.6" fill={th.ink3}>NOW · {ageDays}d</text>
      <text x={pad} y={H - 4} fontFamily="var(--ive-mono)" fontSize="7.5" letterSpacing="0.6" fill={th.ink3}>VERIFIED</text>
    </svg>
  );
}

// ── Mini plane (feed thumbnail) ──────────────────────────────────
function MiniPlane({ eb, sc, size = 60 }) {
  const th = useTh();
  const pad = 6, inner = size - pad * 2;
  const x = pad + eb * inner, y = pad + (1 - sc) * inner;
  const zx = pad + 0.66 * inner, zy = pad + (1 - 0.66) * inner;
  const gridc = th.dark ? 'rgba(244,239,227,0.5)' : CH.ink;
  return (
    <svg viewBox={`0 0 ${size} ${size}`} width={size} height={size} style={{ display: 'block' }}>
      <rect x={pad} y={pad} width={inner} height={inner} fill="none" stroke={gridc} strokeWidth="0.5" opacity="0.4" />
      <rect x={zx} y={pad} width={(pad + inner) - zx} height={zy - pad} fill={CH.ochre} opacity="0.12" />
      <line x1={x} y1={pad} x2={x} y2={pad + inner} stroke={gridc} strokeWidth="0.3" opacity="0.25" />
      <line x1={pad} y1={y} x2={pad + inner} y2={y} stroke={gridc} strokeWidth="0.3" opacity="0.25" />
      <circle cx={x} cy={y} r="3" fill={CH.ink} stroke={th.dark ? th.bg : CH.paper} strokeWidth="1" />
    </svg>
  );
}

Object.assign(window, { ScorePlaneLive, zoneName, WeightBars, DecayCurve, MiniPlane });
