// Control Room — proactive intelligence layer (additive, spec: proactive-intelligence-spec.md).
// One rule everywhere: no insight without an attached action, evidence stated inline
// and ⓘ-traceable. The spark glyph (lucide `sparkle`, single, consistent) is the only
// new mark this layer introduces — no new colors, no "AI" badges.
//
// Exports: CRIntelMark, CREvidence, CRBrixtonPanel (B1 hero evidence slide-over),
// CRIntelWatch + useCRWatch (A10 watchlist sync with Recruiting).
;(function(){
const DS = window.DoorpassDesignSystem_eaad52;
const { Button } = DS;
const D = window.CRData;
const { CRIcon, CRDef, CRChip, CRPhoto, CRLink, crMono } = window;

/* ---- CSS: slide-over motion + hover-revealed dismiss on attention items ---- */
const intelCSS = `
@keyframes crSlideIn { from { transform: translateX(40px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes crFadeIn { from { opacity: 0; } to { opacity: 1; } }
.cr-slideover { animation: crSlideIn 240ms var(--ease-out) both; }
.cr-scrim { animation: crFadeIn 180ms var(--ease-out) both; }
.cr-att .cr-att-x { opacity: 0; transition: opacity var(--dur-fast) var(--ease-out); }
.cr-att:hover .cr-att-x, .cr-att:focus-within .cr-att-x { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .cr-slideover, .cr-scrim { animation: none; } }
`;
if (!document.getElementById("cr-intel-css")) {
  const tag = document.createElement("style");
  tag.id = "cr-intel-css"; tag.textContent = intelCSS;
  document.head.appendChild(tag);
}

/* ---- The one glyph: a single spark marks intelligence apart from work. ---- */
function CRIntelMark({ size = 12, color = "var(--green-600)", style }) {
  return <CRIcon name="sparkle" size={size} color={color} style={style} />;
}

// Evidence stated inline, linked to its metric definition. Reads like a citation.
function CREvidence({ def, children, style }) {
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 5, fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 500, color: "var(--neutral-500)", ...style }}>
      <CRIntelMark />
      <span>{children}</span>
      {def && <CRDef k={def} align="left" />}
    </span>
  );
}

/* ---- A10 · shared watchlist state — the attention item and the Recruiting
       screen read and write the same store. ---- */
const CRIntelWatch = (() => {
  let v = {};
  const subs = new Set();
  return {
    get: () => v,
    set(name, on) { v = { ...v, [name]: on }; subs.forEach((fn) => fn()); },
    toggle(name) { this.set(name, !v[name]); },
    subscribe(fn) { subs.add(fn); return () => subs.delete(fn); },
  };
})();
function useCRWatch() {
  const [, force] = React.useReducer((n) => n + 1, 0);
  React.useEffect(() => CRIntelWatch.subscribe(force), []);
  return CRIntelWatch.get();
}

/* ---- B1 · Brixton evidence panel — data → cohort → recommendation. ----
   A slide-over, not a new page: the queue stays underneath. */

function CohortChart({ velo, signature, comp, w = 470, h = 180 }) {
  const padL = 26, padB = 22, padT = 12, padR = 10;
  const iw = w - padL - padR, ih = h - padT - padB;
  const max = Math.ceil(Math.max(...velo, ...signature, ...comp.map((c) => c * 1.3), 1));
  const n = Math.max(velo.length, signature.length);
  const x = (i) => padL + (i / (n - 1)) * iw;
  const y = (v) => padT + ih - (v / max) * ih;
  const bandTop = comp.map((c, i) => `${x(i)},${y(c * 1.3)}`).join(" ");
  const bandBot = comp.map((c, i) => `${x(i)},${y(c * 0.7)}`).reverse().join(" ");
  return (
    <svg width={w} height={h} style={{ display: "block", maxWidth: "100%" }} aria-hidden="true">
      {[0, Math.round(max / 2), max].map((v, i) => (
        <g key={i}>
          <line x1={padL} x2={w - padR} y1={y(v)} y2={y(v)} stroke="var(--line-200)" strokeWidth="1" />
          <text x={padL - 7} y={y(v) + 4} textAnchor="end" fontSize="12" fontFamily="var(--font-mono)" fill="var(--neutral-500)">{v}</text>
        </g>
      ))}
      <polygon points={`${bandTop} ${bandBot}`} fill="var(--mist-100)" opacity="0.9" />
      <polyline points={comp.map((c, i) => `${x(i)},${y(c)}`).join(" ")} fill="none" stroke="var(--neutral-300)" strokeWidth="1.2" strokeDasharray="2 4" />
      <polyline points={signature.map((v, i) => `${x(i)},${y(v)}`).join(" ")} fill="none" stroke="var(--neutral-500)" strokeWidth="1.6" strokeDasharray="5 4" />
      <polyline points={velo.map((v, i) => `${x(i)},${y(v)}`).join(" ")} fill="none" stroke="var(--red-600)" strokeWidth="2.2" strokeLinejoin="round" strokeLinecap="round" />
      {velo.map((v, i) => <circle key={i} cx={x(i)} cy={y(v)} r="3" fill="var(--red-600)" stroke="var(--surface-card)" strokeWidth="1.5" />)}
      {velo.map((v, i) => (
        <text key={"t" + i} x={x(i)} y={h - 6} textAnchor="middle" fontSize="12" fontFamily="var(--font-mono)" fill="var(--neutral-500)">W{i + 1}</text>
      ))}
    </svg>
  );
}

function LegendSwatch({ kind, color, label }) {
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 11, fontWeight: 500, color: "var(--neutral-500)" }}>
      {kind === "band"
        ? <span style={{ width: 14, height: 9, borderRadius: 2, background: "var(--mist-100)", boxShadow: "inset 0 0 0 1px var(--line-200)" }}></span>
        : <svg width="18" height="8" aria-hidden="true"><line x1="0" x2="18" y1="4" y2="4" stroke={color} strokeWidth="2" strokeDasharray={kind === "dash" ? "4 3" : "none"} /></svg>}
      {label}
    </span>
  );
}

function PanelStat({ value, label, def }) {
  return (
    <div style={{ flex: 1, minWidth: 0, background: "var(--mist-100)", borderRadius: "var(--radius-sm)", padding: "10px 12px" }}>
      <div style={{ display: "flex", alignItems: "baseline", gap: 4 }}>
        <span style={crMono(19)}>{value}</span>
        {def && <CRDef k={def} align="left" />}
      </div>
      <div style={{ fontSize: 11, fontWeight: 600, color: "var(--neutral-500)", marginTop: 3, lineHeight: "14px" }}>{label}</div>
    </div>
  );
}

// One-shot entrance animation: the class is removed once it finishes so the
// visible end-state is the base style (capture-, print- and reduced-motion-safe).
function useEntrance(ms = 320) {
  const [on, setOn] = React.useState(true);
  React.useEffect(() => { const t = setTimeout(() => setOn(false), ms); return () => clearTimeout(t); }, []);
  return on;
}

function CRBrixtonPanel({ onClose, go }) {
  const l = D.listing("brixton");
  const c = D.cohort;
  const entering = useEntrance();
  const [prep, setPrep] = React.useState("idle");   // idle · working · done
  const [watch, setWatch] = React.useState(false);  // watch-one-more-week logged
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);
  const prepare = () => {
    setPrep("working");
    setTimeout(() => {
      setPrep("done");
      D.logIntel("intelligence.card acted · price-cut warning → seller conversation pack generated", "brixton");
    }, 900);
  };
  const watchWeek = () => {
    setWatch(true);
    D.logIntel("intelligence.card acted · price-cut warning → watch one more week (re-checks Mon Jun 15)", "brixton");
  };
  return (
    <div className={entering ? "cr-scrim" : undefined} onClick={onClose} style={{ position: "fixed", inset: 0, zIndex: 60, background: "rgba(5,31,17,0.42)", display: "flex", justifyContent: "flex-end" }}>
      <div className={entering ? "cr-slideover" : undefined} onClick={(e) => e.stopPropagation()} role="dialog" aria-label="Price-cut evidence — 104 Brixton Ln" style={{
        width: 560, height: "100%", background: "var(--surface-app)", boxShadow: "var(--shadow-float)",
        display: "flex", flexDirection: "column", overflow: "hidden",
      }}>
        {/* Header */}
        <div style={{ flex: "none", display: "flex", alignItems: "center", gap: 12, padding: "16px 22px", borderBottom: "1px solid var(--line-200)", background: "var(--surface-card)" }}>
          <CRPhoto listing={l} w={40} h={32} radius={8} />
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 15.5, fontWeight: 800, color: "var(--green-950)" }}>{l.addr}</div>
            <div style={{ fontSize: 11.5, fontWeight: 500, color: "var(--neutral-500)", marginTop: 1 }}>{l.hood} · {l.price} · day {l.days}</div>
          </div>
          <CRChip tone="bad">Price-cut signal</CRChip>
          <button className="cr-ia cr-def-btn" onClick={onClose} aria-label="Close evidence panel" style={{ padding: 8 }}><CRIcon name="x" size={16} color="currentColor" /></button>
        </div>

        <div style={{ flex: 1, minHeight: 0, overflowY: "auto", padding: "18px 22px 22px" }}>
          <CREvidence def="cohortmatch" style={{ marginBottom: 14 }}>
            Matched to the price-cut cohort — {c.matchPct}% curve similarity · from {c.n} metro listings, anonymized
          </CREvidence>

          {/* 1 · The data */}
          <section style={{ background: "var(--surface-card)", borderRadius: "var(--radius-md)", boxShadow: "var(--shadow-card)", padding: 16, marginBottom: 12 }}>
            <div style={{ display: "flex", alignItems: "baseline", gap: 10, marginBottom: 10 }}>
              <h3 style={{ margin: 0, fontSize: 13.5, fontWeight: 800, color: "var(--green-950)", display: "inline-flex", alignItems: "center", gap: 6 }}>Velocity vs the cohort signature <CRDef k="velocity" align="left" /></h3>
              <span style={{ flex: 1 }}></span>
              <span style={{ fontSize: 11.5, fontWeight: 500, color: "var(--neutral-500)" }}>verified showings/wk</span>
            </div>
            <span className="sr-only">Brixton's verified showings fell from 5 per week to 2 over eight weeks, tracking the price-cut cohort signature and running 60% below the comp-set band.</span>
            <CohortChart velo={l.velo} signature={c.signature} comp={l.comp} />
            <div style={{ display: "flex", gap: 14, marginTop: 8, flexWrap: "wrap" }}>
              <LegendSwatch kind="solid" color="var(--red-600)" label="104 Brixton — verified" />
              <LegendSwatch kind="dash" color="var(--neutral-500)" label="cohort signature (median)" />
              <LegendSwatch kind="band" label="comp-set band" />
            </div>
          </section>

          {/* 2 · The cohort */}
          <div style={{ display: "flex", gap: 10, marginBottom: 12 }}>
            <PanelStat value={`${c.cutPct}%`} label={`cut price within ${c.cutDays} days of matching`} def="cohort" />
            <PanelStat value={c.n} label="listings in the cohort · trailing 12 mo" def="cohort" />
            <PanelStat value={`${l.vsComp}%`} label="vs comp-set median, week 8" def="velocity" />
          </div>

          {/* 3 · What waiting costs */}
          <section style={{ background: "var(--cream-100)", borderRadius: "var(--radius-md)", boxShadow: "var(--shadow-card)", padding: "13px 16px", marginBottom: 16 }}>
            <div style={{ display: "flex", gap: 11, alignItems: "flex-start" }}>
              <CRIcon name="hourglass" size={15} color="var(--amber-700)" style={{ marginTop: 2 }} />
              <span style={{ fontSize: 12.5, fontWeight: 500, color: "var(--neutral-700)", lineHeight: "18px" }}>
                Median cut in this cohort: <strong style={{ color: "var(--amber-700)" }}>−{c.medianCut} ≈ {c.medianCutDollars}</strong> at this list price.
                Repricing by week 8 historically settles <strong style={{ color: "var(--amber-700)" }}>{c.waitCost} shallower</strong> than waiting past week 10. <CRDef k="cutcost" align="left" />
              </span>
            </div>
          </section>

          {/* 4 · The recommendation — two actions, both logged */}
          {prep === "done" ? (
            <section style={{ background: "var(--surface-tint)", borderRadius: "var(--radius-md)", boxShadow: "inset 0 0 0 1px var(--green-300)", padding: 16, marginBottom: 10 }}>
              <div style={{ display: "flex", gap: 10, alignItems: "center", marginBottom: 10 }}>
                <CRIcon name="file-check" size={16} color="var(--green-800)" />
                <span style={{ fontSize: 13, fontWeight: 800, color: "var(--green-900)" }}>Seller conversation pack ready</span>
                <span style={{ flex: 1 }}></span>
                <span style={{ fontSize: 11.5, fontWeight: 500, color: "var(--neutral-500)" }}>saved to Brixton · logged</span>
              </div>
              <ul style={{ margin: 0, padding: "0 0 0 18px", fontSize: 12.5, fontWeight: 500, color: "var(--green-900)", lineHeight: "19px" }}>
                <li>Velocity vs comps chart, weeks 1–8 (this panel's data)</li>
                <li>The {c.cutPct}% / {c.cutDays}-day cohort stat, with derivation</li>
                <li>Reprice scenarios at −3% and −{c.medianCut}, with carry costs</li>
              </ul>
            </section>
          ) : (
            <div style={{ display: "flex", gap: 10, marginBottom: 10 }}>
              <Button variant="primary" size="md" fullWidth onClick={prepare} disabled={prep === "working"}>
                {prep === "working" ? "Preparing…" : "Prepare seller conversation"}
              </Button>
              <Button variant="secondary" size="md" fullWidth onClick={watchWeek} disabled={watch}>Watch one more week</Button>
            </div>
          )}
          {watch && (
            <div style={{ display: "flex", gap: 9, alignItems: "center", padding: "10px 13px", borderRadius: "var(--radius-sm)", background: "var(--mist-100)", marginBottom: 10 }}>
              <CRIcon name="check" size={14} color="var(--green-800)" />
              <span style={{ fontSize: 12.5, fontWeight: 600, color: "var(--green-900)" }}>Decision logged — Brixton re-checks against the cohort Mon Jun 15.</span>
              <span style={{ flex: 1 }}></span>
              <CRLink onClick={() => { onClose(); go("activity", { filter: "intelligence" }); }} size={11.5} weight={700} color="var(--green-800)">View in ledger →</CRLink>
            </div>
          )}

          <div style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 11.5, fontWeight: 500, color: "var(--neutral-500)" }}>
            <CRIcon name="badge-check" size={13} color="var(--neutral-500)" />
            Every stat above derives from verified entry/exit events — nothing is modeled from feedback forms.
            <span style={{ flex: 1 }}></span>
            <CRLink onClick={() => { onClose(); go("listing", "brixton"); }} size={11.5} weight={700} color="var(--green-800)">Open listing detail →</CRLink>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { CRIntelMark, CREvidence, CRBrixtonPanel, CRIntelWatch, useCRWatch });
})();
