/* ProTGen StoryLab — interactive workbench app */

function SlIcon({ name, size = 18 }) {
  const p = {
    arrow: <><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></>,
    back: <><path d="M19 12H5"/><path d="m12 19-7-7 7-7"/></>,
    check: <path d="M20 6 9 17l-5-5"/>,
    chair: <><path d="M5 11V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v6"/><path d="M4 11h16l-1 5H5z"/><path d="M6 16v5"/><path d="M18 16v5"/></>,
    flag: <><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></>,
    list: <><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></>,
    target: <><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></>,
    alert: <><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></>,
    book: <><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></>,
    headphones: <><path d="M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5a9 9 0 0 1 18 0v5a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3"/></>,
    play: <polygon points="6 3 20 12 6 21 6 3"/>,
    toc: <><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></>,
  }[name];
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">{p}</svg>;
}

function SlMark({ size = 26 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 48 48" fill="none">
      <path d="M 39.9 15.6 A 18 18 0 1 0 39.9 32.4" stroke="#46CAD3" strokeWidth="3" strokeLinecap="round"/>
      <circle cx="24" cy="15" r="2.2" fill="#2A9498"/><circle cx="24" cy="33" r="2.2" fill="#2A9498"/>
      <circle cx="16.5" cy="19.5" r="2.2" fill="#2A9498"/><circle cx="16.5" cy="28.5" r="2.2" fill="#2A9498"/>
      <circle cx="32" cy="24" r="2.4" fill="#2A9498"/><circle cx="24" cy="24" r="3.4" fill="#F7F2E8"/>
    </svg>
  );
}

/* ---------- Decision bar ---------- */
function DecisionBar({ section, value, onSet }) {
  const states = [["accept", "Accept"], ["edit", "Edit"], ["challenge", "Challenge"], ["park", "Park"]];
  return (
    <div className="sl-decisionbar">
      <span className="dlbl">Decision</span>
      {states.map(([k, l]) => (
        <button key={k} className={"dbtn" + (value === k ? " sel-" + k : "")} onClick={() => onSet(section, k, value === k)}>
          {value === k && <SlIcon name="check" size={15} />} {l}
        </button>
      ))}
    </div>
  );
}

/* ---------- Section heading ---------- */
function SlHead({ kicker, h, sub }) {
  return (
    <div>
      <div className="sl-kicker">{kicker}</div>
      <h2 className="sl-h">{h}</h2>
      {sub && <p className="sl-sub">{sub}</p>}
    </div>
  );
}

/* ============================ SECTIONS ============================ */

function OpeningSection({ onWalk }) {
  return (
    <div>
      <div className="banner">
        <SlIcon name="chair" size={20} />
        <p><b>The empty chair.</b> The ProTGen story works when Carter explains it. The next phase requires it to work when Carter is <b>not</b> in the room. This workbench is how we make the few decisions that determine whether it travels.</p>
      </div>
      <SlHead kicker="The story travel problem" h="Let's walk through the five decisions that determine whether the ProTGen story travels."
        sub="This is an internal strategy appendix for the review with Carter and Amritha — not a public page. It shows the thinking behind the website, one‑pager, and investor briefing: audience logic, belief sequence, narrative spine, and how the design supports investor and partner conversion." />
      <div className="lens-panel" style={{ gridTemplateColumns: "1fr 1fr 1fr" }}>
        {[
          ["Walk me through the strategy", "Guided mode — one decision at a time.", "context"],
          ["Show the top decisions", "Jump to the assumption ranker.", "assume"],
          ["Open the full appendix", "Explore everything, in any order.", "heard"],
        ].map(([h, p, go], i) => (
          <div key={i} className="lens-left" style={{ borderRight: i < 2 ? "1px solid var(--bone-200)" : "none", cursor: "pointer" }} onClick={() => onWalk(go)}>
            <div className="lens-word">Option {i + 1}</div>
            <h4 style={{ fontSize: 19 }}>{h}</h4>
            <p>{p}</p>
            <span className="lens-cta" style={{ color: "var(--teal)" }}>Start <SlIcon name="arrow" size={14} /></span>
          </div>
        ))}
      </div>
    </div>
  );
}

function SharedContextSection({ answers, setAnswer, decisions, setDecision }) {
  return (
    <div>
      <SlHead kicker="Shared context" h="Let's start from the same understanding of the problem." />
      <div className="sc-frame">
        <div className="sc-frame-grad" />
        <p>It sounds like the current story works when Carter is in the room — but the next phase requires a story that can travel, to investors, strategic partners, and website visitors, with the same clarity and force.</p>
      </div>
      <p className="sl-sub" style={{ marginTop: 26 }}>
        Before we design anything, seven questions to validate the real strategic issue. Capture the answers live — they become the source of truth for the belief sequence, audience doorways, and proof ladder.
      </p>
      <div className="sc-list">
        {window.SL_QUESTIONS.map((item, i) => (
          <div className="sc-q" key={item.id}>
            <div className="sc-qnum">{String(i + 1).padStart(2, "0")}</div>
            <div className="sc-qbody">
              <h4>{item.q}</h4>
              <p className="sc-listen">{item.listen}</p>
              <textarea className="sc-input" placeholder="Capture Carter & Amritha's answer…"
                value={answers[item.id] || ""} onChange={(e) => setAnswer(item.id, e.target.value)} />
            </div>
          </div>
        ))}
      </div>
      <p className="note">Answers are held for this session to anchor the conversation. There is also a <a href="primer.html" style={{ color: "var(--teal)", fontWeight: 600 }}>primer article</a> that lays out this thinking in narrative form.</p>
      <div className="sl-insight" style={{ marginTop: 18 }}>
        <DecisionBar section="context" value={decisions.context} onSet={setDecision} />
      </div>
    </div>
  );
}

function HeardSection({ decisions, setDecision }) {
  return (
    <div>
      <SlHead kicker="What we heard" h="Validate the listening before advising." />
      <div className="sl-insight">
        <div className="ins-row">
          <div className="ins-lbl">What we heard</div>
          <p className="ins-txt big">You are not asking for prettier materials. You are trying to make the ProTGen story work for a new investor and partner audience — and survive without the founder narrating it.</p>
        </div>
        <div className="ins-row">
          <div className="ins-lbl">Why it matters</div>
          <p className="ins-txt">If we mishear the problem, we build the wrong website. A prettier brochure would miss the real job: portable conviction.</p>
        </div>
        <div className="ins-row">
          <div className="ins-lbl">Decision needed</div>
          <p className="ins-txt">Does this describe the challenge accurately?</p>
        </div>
        <DecisionBar section="heard" value={decisions.heard} onSet={setDecision} />
      </div>
    </div>
  );
}

function CruxSection({ chosen, setChosen, decisions, setDecision }) {
  return (
    <div>
      <SlHead kicker="The strategic crux" h="Align on the challenge before the solution."
        sub="What belief sequence will make ProTGen understandable, credible, and retellable without Carter in the room? Vote on the framing." />
      <div className="crux-list">
        {window.SL_CRUX.map((c) => (
          <div key={c.id} className={"crux-opt" + (chosen === c.id ? " chosen" : "")} onClick={() => setChosen(c.id)}>
            <div className="radio" />
            <div>
              <h4 className="ctitle">{c.title}</h4>
              <p className="cdesc">{c.desc}</p>
              <span className="ctag">{c.tag}</span>
            </div>
          </div>
        ))}
      </div>
      <div className="sl-insight" style={{ marginTop: 18 }}>
        <DecisionBar section="crux" value={decisions.crux} onSet={setDecision} />
      </div>
    </div>
  );
}

function BeliefBuilder({ order, setOrder, tags, setTag, decisions, setDecision }) {
  const [dragId, setDragId] = React.useState(null);
  const [overId, setOverId] = React.useState(null);
  const beliefs = window.SL_BELIEFS;
  const byId = Object.fromEntries(beliefs.map((b) => [b.id, b]));
  const cycleTag = (id) => {
    const seq = ["essential", "supporting", "toomuch"];
    const cur = tags[id] || "essential";
    setTag(id, seq[(seq.indexOf(cur) + 1) % seq.length]);
  };
  const onDrop = (targetId) => {
    if (!dragId || dragId === targetId) { setDragId(null); setOverId(null); return; }
    const next = [...order];
    const from = next.indexOf(dragId), to = next.indexOf(targetId);
    next.splice(to, 0, next.splice(from, 1)[0]);
    setOrder(next);
    setDragId(null); setOverId(null);
  };
  const leadBelief = byId[order[0]];
  const tagLabel = { essential: "Essential", supporting: "Supporting", toomuch: "Too much for now" };
  return (
    <div>
      <SlHead kicker="The belief sequence" h="Drag to reorder. Tag each belief. See what leading with it implies."
        sub="If an investor absorbs only one belief in the first 90 seconds, which must it be? Reorder the cards — the implication updates live." />
      <div className="belief-builder">
        {order.map((id, i) => {
          const b = byId[id];
          return (
            <div key={id} draggable
              className={"bb-row" + (dragId === id ? " dragging" : "") + (overId === id ? " dragover" : "")}
              onDragStart={() => setDragId(id)}
              onDragEnd={() => { setDragId(null); setOverId(null); }}
              onDragOver={(e) => { e.preventDefault(); if (overId !== id) setOverId(id); }}
              onDrop={() => onDrop(id)}>
              <div className="bb-handle"><span/><span/><span/></div>
              <div style={{ display: "flex", gap: 14, alignItems: "center", minWidth: 0 }}>
                <span className="bb-pos">{String(i + 1).padStart(2, "0")}</span>
                <div className="bb-body">
                  <h4>{b.h}</h4>
                  <p>{b.p}</p>
                </div>
              </div>
              <div className="bb-tags">
                <button className={"bb-tag on-" + (tags[id] || "essential")} onClick={() => cycleTag(id)}>{tagLabel[tags[id] || "essential"]}</button>
              </div>
            </div>
          );
        })}
      </div>
      <div className="bb-implication">
        <div className="impl-lbl">If “{leadBelief.h}” leads</div>
        <p>{window.SL_LEAD_IMPLICATION[leadBelief.lead]}</p>
      </div>
      <div className="sl-insight" style={{ marginTop: 18 }}>
        <DecisionBar section="belief" value={decisions.belief} onSet={setDecision} />
      </div>
    </div>
  );
}

function AudienceLens({ decisions, setDecision }) {
  const keys = Object.keys(window.SL_LENS);
  const [lens, setLens] = React.useState("Clinical");
  const L = window.SL_LENS[lens];
  return (
    <div>
      <SlHead kicker="Audience doorways" h="One story needs four different doors in."
        sub="Toggle the audience lens. The site must give each its own first‑90‑seconds and CTA — without becoming four different stories." />
      <div className="lens-tabs">
        {keys.map((k) => (
          <button key={k} className={"lens-tab" + (k === lens ? " active" : "")} onClick={() => setLens(k)}>
            {k === "Champion" ? "Internal champion" : k === "Clinical" ? "Clinical‑transition" : k === "Category" ? "Category‑creation" : "Strategic BD"}
          </button>
        ))}
      </div>
      <div className="lens-panel">
        <div className="lens-left">
          <div className="lens-word">One word · {L.word}</div>
          <h4>{L.h}</h4>
          <p>{L.need}</p>
          <div style={{ marginTop: 20, paddingTop: 18, borderTop: "1px solid var(--bone-200)" }}>
            <div className="lens-word" style={{ color: "var(--slate)" }}>First 90 seconds</div>
            <p style={{ fontFamily: "var(--font-serif)", fontSize: 18, color: "var(--fg-1)", lineHeight: 1.4 }}>“{L.first90}”</p>
          </div>
        </div>
        <div className="lens-right">
          <div className="lr-lbl">What this audience must see</div>
          <div className="lens-list">
            {L.show.map((s, i) => <div className="li" key={i}><SlIcon name="check" size={16} /><span>{s}</span></div>)}
          </div>
          <span className="lens-cta">CTA · {L.cta} <SlIcon name="arrow" size={14} /></span>
        </div>
      </div>
      <div className="sl-insight" style={{ marginTop: 18 }}>
        <DecisionBar section="audience" value={decisions.audience} onSet={setDecision} />
      </div>
    </div>
  );
}

function AssumptionRanker({ statuses, setStatus, decisions, setDecision }) {
  const [sort, setSort] = React.useState("priority");
  const scored = window.SL_ASSUMPTIONS.map((a) => ({ ...a, priority: +(a.consequence * a.uncertainty / a.testCost).toFixed(1) }));
  const sorted = [...scored].sort((a, b) => {
    if (sort === "priority") return b.priority - a.priority;
    if (sort === "cheapest") return a.testCost - b.testCost || b.priority - a.priority;
    return b.consequence - a.consequence;
  });
  const statusCycle = ["unknown", "validated", "invalidated"];
  const statusLabel = { unknown: "Unknown", validated: "Validated", invalidated: "Invalidated" };
  return (
    <div>
      <SlHead kicker="Assumption ranker" h="Turn guesses into a test plan."
        sub="Priority = Consequence × Uncertainty ÷ Test cost. Sort to find what to validate before we overbuild." />
      <div className="ar-controls">
        <span className="sortlbl">Sort by</span>
        <button className={"ar-sort" + (sort === "priority" ? " active" : "")} onClick={() => setSort("priority")}>Highest risk</button>
        <button className={"ar-sort" + (sort === "cheapest" ? " active" : "")} onClick={() => setSort("cheapest")}>Cheapest test</button>
        <button className={"ar-sort" + (sort === "consequence" ? " active" : "")} onClick={() => setSort("consequence")}>Consequence</button>
      </div>
      <div className="ar-headrow">
        <span>Assumption · counterfactual</span><span>Priority</span><span>Test cost</span><span>Status</span>
      </div>
      <div className="ar-board">
        {sorted.map((a, i) => {
          const cur = statuses[a.id] || a.status;
          const band = a.priority >= 6 ? "hi" : a.priority >= 3.5 ? "mid" : "lo";
          return (
            <div key={a.id} className={"ar-row" + (sort === "priority" && i === 0 ? " top" : "")}>
              <div className="ar-assumption">
                <h4>{a.h}</h4>
                <p className="cf">{a.cf}</p>
              </div>
              <div className={"ar-priority " + band}>
                <div className="pv">{a.priority}</div>
                <div className="mk" style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--slate)", marginTop: 4, textTransform: "uppercase", letterSpacing: ".08em" }}>{band === "hi" ? "High" : band === "mid" ? "Med" : "Low"}</div>
              </div>
              <div className="ar-metric"><div className="mv">{a.testCost}</div><div className="mk">cost</div></div>
              <div className="ar-status">
                <button className={"ar-statbtn" + (cur !== "unknown" ? " on" : "")}
                  onClick={() => { const n = statusCycle[(statusCycle.indexOf(cur) + 1) % 3]; setStatus(a.id, n); }}>
                  {statusLabel[cur]}
                </button>
              </div>
            </div>
          );
        })}
      </div>
      <p className="note">Tap a status to cycle Unknown → Validated → Invalidated. Top 3 by risk become the meeting agenda.</p>
      <div className="sl-insight" style={{ marginTop: 18 }}>
        <DecisionBar section="assume" value={decisions.assume} onSet={setDecision} />
      </div>
    </div>
  );
}

function ProofLadder({ decisions, setDecision }) {
  return (
    <div>
      <SlHead kicker="Proof ladder" h="Pair every claim with its evidence."
        sub="What proof do we have, how strong is it, and where does it appear? Claims without proof should not lead public‑facing copy." />
      <div className="pl-grid">
        <div className="pl-head"><span>Claim</span><span>Proof we have</span><span>Strength</span><span>Where it appears</span></div>
        {window.SL_PROOF.map((r, i) => (
          <div className="pl-row" key={i}>
            <div className="claim">{r.claim}</div>
            <div className="proof">{r.proof}<br/><span className="open" style={{ display: "block", marginTop: 6 }}>Open: {r.open}</span></div>
            <div className="pl-strength"><span className={"pl-pill " + r.strength}>{r.strength}</span></div>
            <div className="proof">{r.where}</div>
          </div>
        ))}
      </div>
      <div className="sl-insight" style={{ marginTop: 18 }}>
        <DecisionBar section="proof" value={decisions.proof} onSet={setDecision} />
      </div>
    </div>
  );
}

function ExperienceMap({ decisions, setDecision }) {
  const [active, setActive] = React.useState("hero");
  const node = window.SL_XMAP.find((x) => x.id === active);
  return (
    <div>
      <SlHead kicker="Website experience map" h="How the approved sequence becomes the homepage."
        sub="Click a module to see its purpose, essential copy, proof required, and the risk if it's unclear." />
      <div className="xmap">
        {window.SL_XMAP.map((x) => (
          <div key={x.id} className={"xnode" + (active === x.id ? " active" : "")} onClick={() => setActive(x.id)}>
            <span className="xphase">{x.phase}</span>
            <div className="xn">{x.n}</div>
            <div className="xt">{x.t}</div>
          </div>
        ))}
      </div>
      <div className="xdetail">
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", flexWrap: "wrap", gap: 12 }}>
          <h3 style={{ fontSize: 22, fontWeight: 600, margin: 0, letterSpacing: "-.01em" }}>{node.n} — {node.t}</h3>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--teal)" }}>{node.purpose}</span>
        </div>
        <div className="xd-grid">
          <div className="xd-cell"><div className="xdl">Essential copy</div><p style={{ fontStyle: "italic" }}>“{node.copy}”</p></div>
          <div className="xd-cell"><div className="xdl">Proof required</div><p>{node.proof}</p></div>
          <div className="xd-cell"><div className="xdl">Risk if unclear</div><p>{node.risk}</p></div>
          <div className="xd-cell"><div className="xdl">Phase</div><p>{node.phase} — build now.</p></div>
        </div>
      </div>
      <div className="sl-insight" style={{ marginTop: 18 }}>
        <DecisionBar section="xmap" value={decisions.xmap} onSet={setDecision} />
      </div>
    </div>
  );
}

function EmptyRoomTest() {
  const [vals, setVals] = React.useState({ does: "", matters: "", proves: "", next: "" });
  const [checked, setChecked] = React.useState(false);
  const fields = [
    ["does", "What ProTGen does"],
    ["matters", "Why it matters"],
    ["proves", "What ProT‑096 proves"],
    ["next", "What to do next"],
  ];
  const isVague = (v) => v.trim().length < 12;
  const gaps = fields.filter(([k]) => checked && isVague(vals[k]));
  return (
    <div>
      <SlHead kicker="Empty room test" h="Can the story travel without Carter?"
        sub="Imagine the one‑pager is forwarded to someone who has never met Carter. Fill in what they would repeat. Blank or vague answers flag a belief‑sequence gap." />
      <div className="ert">
        <div className="ert-grad" />
        <h3>The retellability check</h3>
        <p className="ert-sub">If any field stays empty or thin, the related part of the belief sequence isn't doing its job yet.</p>
        <div className="ert-grid">
          {fields.map(([k, label]) => (
            <div key={k} className={"ert-field" + (checked && isVague(vals[k]) ? " flagged" : "")}>
              <label>{label}</label>
              <textarea value={vals[k]} onChange={(e) => setVals({ ...vals, [k]: e.target.value })} placeholder="In their words…" />
              <span className="flag"><SlIcon name="alert" size={13} /> Gap — strengthen this belief</span>
            </div>
          ))}
        </div>
        <div className="ert-foot">
          <span className="ert-verdict">
            {checked
              ? (gaps.length === 0 ? <><b>The story travels.</b> All four fields hold up without the founder.</> : <><b>{gaps.length} gap{gaps.length > 1 ? "s" : ""}.</b> Strengthen the flagged beliefs before the design sprint.</>)
              : "Fill the four fields, then run the test."}
          </span>
          <button className="sl-btn sl-btn-primary" onClick={() => setChecked(true)}>Run the test <SlIcon name="check" size={15} /></button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  SlIcon, SlMark, DecisionBar, SlHead,
  OpeningSection, SharedContextSection, HeardSection, CruxSection, BeliefBuilder, AudienceLens,
  AssumptionRanker, ProofLadder, ExperienceMap, EmptyRoomTest,
});
