/* global React, ReactDOM, window */
const { useState: s4, useRef: r4, useEffect: e4 } = React;
let D4 = window.EI2;
const C4 = window.EI3;

const W4 = [92, 78, 64, 49, 35];
const RANGE_ROWS = [[0, 22, 45, 45], [0, 18, 38, 38], [0, 45, 72, 88], [0, 38, 52, 68], [0, 15, 38, 50], [0, 5, 40, 40]];
const SEGBAR_ROWS = [[78, 96, "a"], [62, 88, "b"], [24, 40, "c"]];
function V4z({ kind }) {
  if (kind === "rank") return <div className="v2-rank">{W4.map((w, i) => <div className="v2-rank__r" key={i}><span className="v2-rank__l"></span><span className="v2-rank__tr"><i style={{ width: w + "%" }}></i></span></div>)}</div>;
  if (kind === "dumbbell") return <div className="v2-db">{[[14, 62], [26, 80], [8, 44], [38, 72]].map(([a, b], i) => <div className="v2-db__r" key={i}><span className="v2-db__ln" style={{ left: a + "%", right: (100 - b) + "%" }}></span><span className="v2-db__d v2-db__d--a" style={{ left: a + "%" }}></span><span className="v2-db__d v2-db__d--b" style={{ left: b + "%" }}></span></div>)}</div>;
  if (kind === "venn") return <div className="v2-venn"><span className="v2-venn__c a"></span><span className="v2-venn__c b"></span></div>;
  if (kind === "range") return <div className="v2-range">{RANGE_ROWS.map(([lead0, barS, barE, trailE], i) => <div className="v2-range__r" key={i}>{barS > lead0 && <span className="v2-range__ln" style={{ left: lead0 + "%", width: (barS - lead0) + "%" }}></span>}<span className="v2-range__b" style={{ left: barS + "%", width: (barE - barS) + "%" }}></span>{trailE > barE && <span className="v2-range__ln" style={{ left: barE + "%", width: (trailE - barE) + "%" }}></span>}</div>)}</div>;
  if (kind === "segbar") return <div className="v2-segbar">{SEGBAR_ROWS.map(([w, trail, c], i) => <div className="v2-segbar__r" key={i}><span className={"v2-segbar__b v2-segbar__b--" + c} style={{ width: w + "%" }}></span>{trail > w && <span className={"v2-segbar__ln v2-segbar__ln--" + c} style={{ left: w + "%", width: (trail - w) + "%" }}></span>}</div>)}</div>;
  if (kind === "choice") return <div className="v2-choice">{[0, 1, 2].map(i => <div className="v2-choice__row" key={i}><span className="v2-choice__img"></span><span className="v2-choice__lines"><span className="v2-choice__l1"></span><span className="v2-choice__l2"></span></span><span className="v2-choice__price"></span><span className="v2-choice__cta"></span></div>)}</div>;
  if (kind === "reach") return <div className="v2-reach">{[[39, 39], [57, 18], [64, 7], [69, 5], [74, 4], [77, 3], [79, 2]].map(([cum, inc], i) => <div className="v2-reach__col" key={i}><span className="v2-reach__gray" style={{ height: cum * 1.15 + "px" }}></span><span className="v2-reach__purple" style={{ bottom: (cum - inc) * 1.15 + "px", height: Math.max(5, inc * 1.15) + "px" }}></span></div>)}</div>;
  if (kind === "markets") return <div className="v2-markets">{[["\uD83C\uDDFA\uD83C\uDDF8", "United States"], ["\uD83C\uDDEC\uD83C\uDDE7", "United Kingdom"], ["\uD83C\uDDE8\uD83C\uDDF3", "China"]].map(([flag, name], i) => <div className="v2-markets__r" key={i}><span className="v2-markets__tag"><i className="v2-markets__flag">{flag}</i></span><span className="v2-markets__chips">{["g", "g", "n", "n", "y", "y", "g", "n", "y", "n"].map((c, j) => <i key={j} className={"v2-markets__c v2-markets__c--" + (i === 1 && j === 1 ? "y" : i === 3 && j === 0 ? "n" : i === 2 && j === 7 ? "g" : c)}></i>)}</span></div>)}</div>;
  if (kind === "verdicts") return <div className="v2-verdicts">{[["g", 1], ["y", 2], ["y", 1]].map(([c, imgs], i) => <div className="v2-verdicts__card" key={i}><span className="v2-verdicts__hd"><i className={"v2-verdicts__dot v2-verdicts__dot--" + c}></i><i className="v2-verdicts__ln"></i></span>{i === 1 && <span className="v2-verdicts__flags"><i>{"\uD83C\uDDEC\uD83C\uDDE7"}</i><i>{"\uD83C\uDDFA\uD83C\uDDF8"}</i></span>}<span className="v2-verdicts__imgs">{Array.from({ length: imgs }).map((_, j) => <i key={j}></i>)}</span><span className="v2-verdicts__note"></span></div>)}</div>;
  if (kind === "insightbars") return <div className="v2-ibars"><span className="v2-ibars__box"><i className="v2-ibars__dot"></i>{[94, 78, 88, 66].map((w, i) => <i key={i} className="v2-ibars__ln" style={{ width: w + "%" }}></i>)}</span><span className="v2-ibars__bars">{[82, 74, 72, 50].map((w, i) => <i key={i}><em style={{ width: w + "%" }}></em></i>)}</span></div>;
  if (kind === "deepdive") return <div className="v2-deepdive"><div className="v2-deepdive__top"><span className="v2-deepdive__img"><i className="v2-deepdive__badge"></i></span><span className="v2-deepdive__ins">{[94, 78, 88, 66].map((w, i) => <i key={i}><em></em><b style={{ width: w + "%" }}></b></i>)}</span></div><div className="v2-deepdive__cols">{[[82, 74, 72, 50], [80, 55, 38, 22]].map((set, k) => <span className="v2-deepdive__bars" key={k}>{set.map((w, i) => <i key={i}><em style={{ width: w + "%" }}></em></i>)}</span>)}</div><div className="v2-deepdive__quotes">{[0, 1, 2, 3].map(i => <span key={i}></span>)}</div></div>;
  if (kind === "stack") return <div className="v2-stack">{[[52, 30, 18], [41, 24, 35], [64, 22, 14], [30, 26, 44]].map((s, i) => <div className="v2-stack__r" key={i}>{s.map((w, j) => <span key={j} className={"v2-stack__s s" + j} style={{ width: w + "%" }}></span>)}</div>)}</div>;
  /* Three moments' output pages call for a heat grid — Strategy Kickoff's
     "attributes that stand out", Product Naming's and Marketing's "the call,
     by market". V4z had no `heat`, so those pages rendered an empty box.
     Built from v2-rank's label stub and v2-markets' cell so the three read as
     one chart family. */
  if (kind === "heat") return <div className="v2-heatg">{[[.9, .55, .3, .7, .35], [.45, .85, .6, .25, .7], [.3, .5, .9, .4, .8]].map((row, i) => <div className="v2-heatg__r" key={i}><span className="v2-heatg__l"></span>{row.map((o, j) => <i key={j} style={{ opacity: o }}></i>)}</div>)}</div>;
  return null;
}

/* draggable divider — lives inside the pane it resizes */
function Resz4({ side, min = 230 }) {
  const h = r4(null);
  const down = (e) => {
    e.preventDefault();
    const node = h.current && h.current.parentElement; if (!node) return;
    const x0 = e.clientX, w0 = node.getBoundingClientRect().width;
    const parent = node.parentElement;
    const move = (ev) => {
      const avail = parent ? parent.getBoundingClientRect().width : 1440;
      const other = side === "left" ? 244 : 248;
      const max = Math.max(w0, Math.min(560, avail - 420 - other));
      const d = side === "left" ? ev.clientX - x0 : x0 - ev.clientX;
      node.style.width = Math.max(min, Math.min(max, w0 + d)) + "px";
    };
    const up = () => {
      window.removeEventListener("pointermove", move);
      window.removeEventListener("pointerup", up);
      document.body.style.cursor = ""; document.body.style.userSelect = "";
    };
    window.addEventListener("pointermove", move);
    window.addEventListener("pointerup", up);
    document.body.style.cursor = "col-resize"; document.body.style.userSelect = "none";
  };
  const reset = () => { const n = h.current && h.current.parentElement; if (n) n.style.width = ""; };
  return <div className={"i3-resz i3-resz--" + side} ref={h} onPointerDown={down} onDoubleClick={reset} title="Drag to resize · double-click to reset"></div>;
}

function Chat4({ brief, manual, dc, onDC, moment }) {
  const base = r4(null);
  if (!base.current) base.current = window.AT_INTAKE_TURNS(brief, moment);
  /* What the user has to answer sits in a fixed dock just above the composer,
     where their hands already are, rather than scrolling away inside the log. */
  const [pending, setPending] = s4(null);
  /* Turns the user actually caused. Nothing lands here on its own: the scripted
     region exchange is offered as a chip and runs only when it is picked, and a
     typed message gets a reply that does not pretend to have understood
     something specific. A transcript showing a question nobody asked is the
     moment a room realises it is watching a recording. */
  const [extra, setExtra] = s4([]);
  /* The drafting was already watched on the loading screen, so it arrives
     instantly. Anything the user asks for after that is new work, and gets the
     working animation it deserves. */
  const [live, setLive] = s4(false);
  const [draft, setDraft] = s4("");

  const send = (text) => {
    const t = (text || "").trim();
    if (!t) return;
    const sug = (window.AT_SUGGESTIONS || []).find(x => x.label === t);
    setDraft("");
    setLive(true);
    setExtra(xs => [...xs, sug ? sug.turn : window.AT_REPLY_TO(t)]);
  };

  /* Answering is the user doing something, so whatever the agent does next is
     new work and gets watched. Everything before the first answer was already
     watched once, on the loading screen. */
  const answer = (patch) => { setLive(true); onDC(patch); };

  const turns = base.current.concat(extra);
  const sugs = (window.AT_SUGGESTIONS || []).filter(x => !extra.some(e => e.me === x.label));

  return (
    <div className="i3-chat">
      <Resz4 side="left" />
      <div className="i3-chat__h"><i className="ti ti-sparkles"></i><b>MakerChat</b></div>
      <div className={"i3-log" + (pending ? " is-muted" : "")} style={{ gap: 4 }}>
        {manual ? (
          <div className="i3-msg ai">Building manually — ask MakerChat to draft objectives or questions any time, or keep going below.</div>
        ) : <window.AgentThread turns={turns} animate={live} answers={dc} onAnswer={answer} onPending={setPending} />}
      </div>
      {!manual && <window.ATDock pending={pending} answers={dc} onAnswer={answer} />}
      {/* Suggested-prompt chips removed from the chat per feedback 2026-08-26.
          `sugs` stays computed above so a typed match still gets the canned
          scripted reply — only the clickable offer is hidden. */}
      {manual && <div className="i3-sugs">{C4.sugs.map(t => <button className="i3-sug" key={t}>{t}</button>)}</div>}
      <div className="i3-comp">
        <input placeholder="Tell MakerChat what to change…" value={draft}
          onChange={e => setDraft(e.target.value)}
          onKeyDown={e => { if (e.key === "Enter") send(draft); }} />
        <button onClick={() => send(draft)}><i className="ti ti-arrow-up"></i></button>
      </div>
    </div>
  );
}

/* tab 1 — an objective, the page it produces, and one line to the questions */
function What4({ objTitles, onEditor }) {
  const [open, setOpen] = s4(null);
  return (
    <React.Fragment>
      {D4.objectives.map(o => (
        <div className="i4-obj" key={o.n} id={"qsec-o" + o.n}>
          <div className="i4-obj__k">OBJECTIVE {o.n}</div>
          <div className="i4-obj__t">{(objTitles && objTitles[o.n - 1]) || o.label}</div>
          <div className="i4-card">
            <div className="i4-exc__k"><i className="rule"></i>{o.page} · EXAMPLE</div>
            <div className="i4-exc__h">{o.chart}</div>
            <V4z kind={o.viz} />
          </div>
          <div className="i3-cuts">{o.cuts.map(c => <span className="i3-cut" key={c}>{c}</span>)}</div>
          <button className="i4-dis" onClick={() => setOpen(open === o.n ? null : o.n)}>
            <i className={"ti ti-chevron-" + (open === o.n ? "down" : "right")}></i>{o.qs.length} questions create this
          </button>
          {open === o.n && (
            <React.Fragment>
              <div className="i3-qs">{o.qs.map(q => <div className="i3-q" key={q.l}><span className="i3-q__t">{q.t}</span><span className="i3-r__v">{q.l}</span></div>)}</div>
              <button className="i4-nudge" onClick={() => onEditor && onEditor()}><i className="ti ti-list-details"></i>To change the wording, answers or order, open the Study editor<i className="ti ti-arrow-right"></i></button>
            </React.Fragment>
          )}
        </div>
      ))}
    </React.Fragment>
  );
}
const OPTS = {
  Scale: ["Definitely would not buy", "Probably would not buy", "Might buy", "Probably would buy", "Definitely would buy"],
  Single: ["A department store", "A specialist retailer", "The brand's own store", "Online only"],
  Multi: ["Shape", "Color", "Material", "Price", "Brand"],
  Grid: ["Brand A", "Brand B", "Brand C", "None of these"],
  "Open end": null
};

/* ============================================================
   Questions tab — the live survey editor, fully editable:
   question text, answer options, order (questions and answers),
   Required / Randomized flags, and anchored options that stay
   pinned to the bottom of the list. Objectives first, demographics last.
   ============================================================ */
const QMETA = {
  Scale: { icon: "heart", label: "Sentiment score", ctl: "stars" },
  Single: { icon: "circle-check", label: "Single select", ctl: "single" },
  Multi: { icon: "checks", label: "Multi select", ctl: "multi" },
  Grid: { icon: "layout-grid", label: "Grid", ctl: "multi" },
  "Open end": { icon: "abc", label: "Long text", ctl: "text" }
};
const ANCHOR_OPTS = ["Other", "None of the above"];
let __qid = 0;
const qid = () => "q" + (++__qid);

const DEMO_QS = [
  { t: "Single", l: "What's your gender?", opts: ["Male", "Female", "Non-binary"], anchors: ["Prefer not to say"], req: true, rand: false, icon: "gender-bigender", label: "Gender" },
  { t: "Single", l: "How old are you?", opts: ["18–24", "25–34", "35–44", "45–54", "55+"], anchors: [], req: true, rand: false, icon: "cake", label: "Age" },
  { t: "Single", l: "Which country do you live in?", opts: ["United Kingdom", "France", "Germany"], anchors: ["None of the above"], req: true, rand: false, icon: "map-pin", label: "Country" }
];

function buildSections() {
  const secs = D4.objectives.map(o => ({
    id: "o" + o.n, n: o.n, title: "Objective " + o.n + " · " + o.page, icon: "layout-list",
    // Sentiment score leads the survey unless someone reorders it by hand.
    qs: [...o.qs].sort((a, b) => (b.t === "Scale") - (a.t === "Scale")).map(q => {
      const m = QMETA[q.t] || QMETA.Single;
      return { id: qid(), t: q.t, l: q.l, opts: (q.o || OPTS[q.t] || []).slice(), anchors: [], req: true,
        rand: m.ctl === "single" || m.ctl === "multi",
        cond: q.t === "Open end" ? { q: (D4.objectives[0].qs.find(x => x.t === "Scale") || D4.objectives[0].qs[0]).l, vals: ["Probably would buy", "Definitely would buy"] } : null };
    })
  }));
  secs.push({ id: "demo", title: "Demographics", icon: "users",
    qs: DEMO_QS.map(d => ({ id: qid(), ...d, cond: null })) });
  return secs;
}

/* new-question templates, one per type the editor supports */
const QTYPES = [
  { t: "Scale", l: "How likely are you to buy this style?", opts: [], req: true, rand: false },
  { t: "Single", l: "New question", opts: ["Option 1", "Option 2", "Option 3"], req: true, rand: true },
  { t: "Multi", l: "Which of these apply? Select all that apply.", opts: ["Option 1", "Option 2", "Option 3"], req: true, rand: true },
  { t: "Grid", l: "How do you rate each of these?", opts: ["Brand A", "Brand B", "Brand C"], req: true, rand: true },
  { t: "Open end", l: "Tell us more about your choice.", opts: [], req: false, rand: false }
];

/* pick a question type — the popup behind every “Add a question” */
function TypeMenu({ label, onPick, wide, className }) {
  const [open, setOpen] = s4(false);
  const wrap = r4(null);
  e4(() => {
    if (!open) return;
    const away = ev => { if (wrap.current && !wrap.current.contains(ev.target)) setOpen(false); };
    document.addEventListener("mousedown", away);
    return () => document.removeEventListener("mousedown", away);
  }, [open]);
  return (
    <div className={"i4q-addwrap" + (wide ? " is-wide" : "")} ref={wrap}>
      <button type="button" className={className || "i4q-add"} onClick={() => setOpen(o => !o)}>
        <i className="ti ti-plus"></i>{label || "Add a question"}
      </button>
      {open && (
        <div className="i4-menu i4-menu--c">
          <div className="i4-menu__h">Question type</div>
          <div className="i4-menu__l">
            {QTYPES.map(x => {
              const m = QMETA[x.t];
              return <button type="button" className="i4-menu__o i4-menu__o--ic" key={x.t}
                onClick={() => { setOpen(false); onPick(x); }}><i className={"ti ti-" + m.icon}></i>{m.label}</button>;
            })}
          </div>
        </div>
      )}
    </div>
  );
}

const reorder = (arr, from, to) => {
  const out = arr.slice();
  out.splice(to, 0, out.splice(from, 1)[0]);
  return out;
};

function Ed({ value, onCommit, className, tag }) {
  const T = tag || "div";
  return <T className={className} contentEditable suppressContentEditableWarning
    onBlur={e => onCommit(e.currentTarget.textContent.trim() || value)}
    onKeyDown={e => { if (e.key === "Enter") { e.preventDefault(); e.currentTarget.blur(); } }}>{value}</T>;
}

function QCard({ q, api, drag, onGrab, onOver, anchorId }) {
  const m = QMETA[q.t] || QMETA.Single;
  const sel = m.ctl === "single" || m.ctl === "multi";
  const [grab, setGrab] = s4(false);
  const [oDrag, setODrag] = s4(null);   // index of the option being dragged
  const [oGrab, setOGrab] = s4(false);
  return (
    <div className={"i4q-q" + (drag ? " is-drag" : "")} id={anchorId} draggable={grab}
      onDragStart={e => { e.dataTransfer.effectAllowed = "move"; onGrab(); }}
      onDragEnd={() => { setGrab(false); onGrab(null); }}
      onDragOver={e => { e.preventDefault(); onOver(); }}>
      <div className="i4q-q__in">
        <div className="i4q-chips">
          <span className="i4q-grip" title="Drag to reorder" onMouseDown={() => setGrab(true)} onMouseUp={() => setGrab(false)}><i className="ti ti-grip-vertical"></i></span>
          <span className="i4q-chip is-type"><i className={"ti ti-" + (q.icon || m.icon)}></i>{q.label || m.label}</span>
          <button type="button" className={"i4q-chip is-tog" + (q.req ? " on" : "")} onClick={() => api.patch({ req: !q.req })}>
            <i className={"ti ti-" + (q.req ? "check" : "plus")}></i>Required
          </button>
          {sel && (
            <button type="button" className={"i4q-chip is-tog" + (q.rand ? " on" : "")} onClick={() => api.patch({ rand: !q.rand })}>
              <i className={"ti ti-" + (q.rand ? "check" : "plus")}></i>Randomized
            </button>
          )}
          {q.cond && <span className="i4q-chip">Conditional logic</span>}
          <span className="i4q-q__sp"></span>
          <span className="i4q-tools">
            <button type="button" title="Delete question" onClick={api.delQ}><i className="ti ti-trash"></i></button>
          </span>
        </div>
        <h3 className="i4q-q__t"><Ed tag="span" className="i4q-q__te" value={q.l} onCommit={v => api.patch({ l: v })} />{q.req && <em>*</em>}</h3>
        {m.ctl === "stars" && <div className="i4q-stars">{[0, 1, 2, 3, 4].map(k => <i className="ti ti-star" key={k}></i>)}</div>}
        {m.ctl === "text" && <div className="i4q-free"><div className="i4q-free__l">Answer</div><div className="i4q-free__b">Type your answer</div></div>}
        {sel && (
          <div className="i4q-opts">
            {q.opts.map((o, oi) => (
              <div className={"i4q-opt" + (oDrag === oi ? " is-drag" : "")} key={oi} draggable={oGrab}
                onDragStart={e => { e.stopPropagation(); e.dataTransfer.effectAllowed = "move"; setODrag(oi); }}
                onDragEnd={() => { setODrag(null); setOGrab(false); }}
                onDragOver={e => {
                  e.preventDefault(); e.stopPropagation();
                  if (oDrag === null || oDrag === oi) return;
                  api.reorderOpt(oDrag, oi); setODrag(oi);
                }}>
                <span className="i4q-grip i4q-grip--o" title="Drag to reorder" onMouseDown={() => setOGrab(true)} onMouseUp={() => setOGrab(false)}><i className="ti ti-grip-vertical"></i></span>
                <span className={"i4q-mark" + (m.ctl === "multi" ? " i4q-mark--m" : "")}></span>
                <Ed className="i4q-opt__t" value={o} onCommit={v => api.setOpt(oi, v)} />
                <span className="i4q-tools i4q-tools--o">
                  <button type="button" title="Remove option" onClick={() => api.delOpt(oi)}><i className="ti ti-x"></i></button>
                </span>
              </div>
            ))}
            {q.anchors.map(a => (
              <div className="i4q-opt is-anchor" key={a}>
                <span className="i4q-grip i4q-grip--o is-off"><i className="ti ti-pin"></i></span>
                <span className={"i4q-mark" + (m.ctl === "multi" ? " i4q-mark--m" : "")}></span>
                <span className="i4q-opt__t">{a}</span>
                <i className="i4q-anchortag">Anchored</i>
                <span className="i4q-tools i4q-tools--o">
                  <button type="button" title="Remove option" onClick={() => api.delAnchor(a)}><i className="ti ti-x"></i></button>
                </span>
              </div>
            ))}
          </div>
        )}
        {sel && (
          <div className="i4q-qft">
            <button type="button" className="i4q-obtn" onClick={api.addOpt}>Add option</button>
            {ANCHOR_OPTS.filter(a => !q.anchors.includes(a)).map(a => (
              <button type="button" className="i4q-lbtn" key={a} onClick={() => api.addAnchor(a)}>Add “{a}”</button>
            ))}
          </div>
        )}
      </div>
      {q.cond && (
        <div className="i4q-cond">
          <div className="i4q-cond__h"><i className="ti ti-eye"></i>Display this question if</div>
          <div className="i4q-cond__q"><i className="ti ti-heart"></i>{q.cond.q}</div>
          <div className="i4q-cond__r">
            <span>In</span>
            <div className="i4q-cond__vals">{q.cond.vals.map(v => <span key={v}>{v}</span>)}</div>
          </div>
        </div>
      )}
    </div>
  );
}

function QNav({ secs, scroller }) {
  const [sel, setSel] = s4(null);
  const go = (id) => {
    setSel(id);
    const el = document.getElementById("qsec-" + id);
    const box = scroller && scroller.current;
    if (el && box) box.scrollTo({ top: Math.max(0, el.offsetTop - box.offsetTop - 6), behavior: "smooth" });
  };
  return (
    <nav className="i4q-nav">
      {secs.map(s => (
        <React.Fragment key={s.id}>
          <button className={"i4q-nav__s" + (sel === s.id ? " on" : "")} onClick={() => go(s.id)}>
            <span>{s.id === "demo" ? "Demographics" : s.title.split(" · ")[0]}</span><i>{s.qs.length}</i>
          </button>
        </React.Fragment>
      ))}
    </nav>
  );
}

function Questions4({ manual, rows, secs, setSecs, scroller, objTitles, setObjTitles }) {
  const onSec = (sid, fn) => setSecs(ss => ss.map(s => s.id === sid ? { ...s, qs: fn(s.qs) } : s));
  const onQ = (sid, qid_, patch) => onSec(sid, qs => qs.map(q => q.id === qid_ ? { ...q, ...patch } : q));
  const apiFor = (sid, q) => ({
    patch: p => onQ(sid, q.id, p),
    delQ: () => onSec(sid, qs => qs.filter(x => x.id !== q.id)),
    setOpt: (i, v) => onQ(sid, q.id, { opts: q.opts.map((o, k) => k === i ? v : o) }),
    delOpt: i => onQ(sid, q.id, { opts: q.opts.filter((o, k) => k !== i) }),
    reorderOpt: (from, to) => onQ(sid, q.id, { opts: reorder(q.opts, from, to) }),
    addOpt: () => onQ(sid, q.id, { opts: [...q.opts, "New option"] }),
    addAnchor: a => onQ(sid, q.id, { anchors: [...q.anchors, a] }),
    delAnchor: a => onQ(sid, q.id, { anchors: q.anchors.filter(x => x !== a) })
  });
  const [dq, setDq] = s4(null);   // { sid, id } of the question being dragged
  const grab = (sid, id) => v => setDq(v === null ? null : { sid, id });
  const over = (sid, id) => () => {
    if (!dq || dq.sid !== sid || dq.id === id) return;
    onSec(sid, qs => {
      const from = qs.findIndex(x => x.id === dq.id), to = qs.findIndex(x => x.id === id);
      return from < 0 || to < 0 ? qs : reorder(qs, from, to);
    });
  };
  const addQ = (sid, x) => onSec(sid, qs => [...qs, { id: qid(), t: x.t, l: x.l, opts: x.opts.slice(), anchors: [], req: x.req, rand: x.rand, cond: null }]);
  const setSecTitle = (sid, v) => setSecs(ss => ss.map(s => s.id === sid ? { ...s, title: v } : s));
  const addSec = (first) => {
    const sid = "s" + (++__qid);
    const n = secs.filter(s => s.id !== "demo").length + 1;
    setSecs(ss => {
      const sec = { id: sid, title: "Objective 0" + n + " · what this objective answers", icon: "layout-list", qs: first ? [{ id: qid(), t: first.t, l: first.l, opts: first.opts.slice(), anchors: [], req: first.req, rand: first.rand, cond: null }] : [] };
      const di = ss.findIndex(s => s.id === "demo");
      return di < 0 ? [...ss, sec] : [...ss.slice(0, di), sec, ...ss.slice(di)];
    });
    return sid;
  };
  const addDemo = () => setSecs(ss => ss.some(s => s.id === "demo") ? ss
    : [...ss, { id: "demo", title: "Demographics", icon: "users", qs: DEMO_QS.map(d => ({ id: qid(), ...d, cond: null })) }]);
  const prods = (rows || []).filter(r => r.url);
  if (!secs.length) return (
    <div className="i4q-wrap">
      <div className="i4q-col">
        <div className="i4q-blank">
          <div className="i4q-blank__t">No questions yet</div>
          <div className="i4q-blank__s">Start with a question and group it under an objective, or drop in the standard demographics block.</div>
          <div className="i4q-blank__row">
            <TypeMenu label="Add a question" className="i3-btn i3-btn--p" onPick={x => addSec(x)} />
            <button className="i3-btn" onClick={addDemo}><i className="ti ti-users"></i>Add demographics</button>
          </div>
        </div>
      </div>
    </div>
  );
  return (
    <div className="i4q-wrap">
      <div className="i4q-col">
      {!!prods.length && (
        <div className="i4q-prod">
          <div className="i4q-prod__h">Products<span className="i4q-prod__n">{prods.length}</span></div>
          <div className="i4q-prod__strip">{prods.map(p => <span className="i4q-thumb" key={p.id}><img src={p.url} alt={p.name} /></span>)}</div>
        </div>
      )}
      {secs.map(s => (
        <React.Fragment key={s.id}>
          <div className="i4q-sech" id={"qsec-" + s.id}>
            <i className={"ti ti-" + s.icon}></i>
            {s.n ? (
              <b>Objective {s.n} · <Ed tag="span" className="i4q-sech__e" value={(objTitles && objTitles[s.n - 1]) || s.title}
                onCommit={v => setObjTitles(ts => ts.map((x, i) => i === s.n - 1 ? v : x))} /></b>
            ) : s.id === "demo" ? <b>{s.title}</b> : (
              <b><Ed tag="span" className="i4q-sech__e" value={s.title} onCommit={v => setSecTitle(s.id, v)} /></b>
            )}
            <span className="i4q-sech__s">{s.qs.length} question{s.qs.length === 1 ? "" : "s"}</span>
            {s.id !== "demo" && <span className="i4q-tools i4q-tools--s"><button type="button" title="Delete objective" onClick={() => setSecs(ss => ss.filter(x => x.id !== s.id))}><i className="ti ti-trash"></i></button></span>}
          </div>
          {s.qs.map(q => <QCard key={q.id} q={q} anchorId={"qsec-" + q.id} api={apiFor(s.id, q)} drag={!!dq && dq.id === q.id}
            onGrab={grab(s.id, q.id)} onOver={over(s.id, q.id)} />)}
          <TypeMenu wide onPick={x => addQ(s.id, x)} />
        </React.Fragment>
      ))}
      <div className="i4q-secadd">
        <TypeMenu label="Add an objective" className="i4q-add i4q-add--sec" onPick={x => addSec(x)} />
        {!secs.some(s => s.id === "demo") && <button className="i4q-add i4q-add--sec" onClick={addDemo}><i className="ti ti-users"></i>Add demographics</button>}
      </div>
      </div>
    </div>
  );
}
const ASSET_FMTS = ["off-body sample", "on-body sample", "flat sketch", "3D render", "lifestyle photo"];
function Assets4({ reading, onFiles, rows, setRows }) {
  const [drag, setDrag] = s4(false);
  const [libOpen, setLibOpen] = s4(false);
  const inputRef = r4(null);
  const set = (id, k, v) => setRows(r => r.map(x => x.id === id ? { ...x, [k]: v } : x));
  const pick = () => inputRef.current && inputRef.current.click();
  const addLib = (items) => {
    setRows(r => [...r, ...items.filter(it => !r.some(x => x.id === it.id)).map(it => ({
      id: it.id, pid: it.pid, url: it.url, name: it.name, price: String(it.price || "").replace("$", ""), desc: it.tags.join(", "), fmt: "lifestyle photo", source: "library"
    }))]);
    setLibOpen(false);
  };
  const libBtn = (
    <button className="i4-libbtn" onClick={() => setLibOpen(true)}><i className="ti ti-shirt"></i>Add from product library</button>
  );
  return (
    <React.Fragment>
      <input ref={inputRef} type="file" accept="image/*" multiple style={{ display: "none" }}
        onChange={e => { onFiles(e.target.files); e.target.value = ""; }} />
      <div className="i4-libwrap">
        <div className={"i4-drop" + (drag ? " is-drag" : "")} onClick={pick}
          onDragOver={e => { e.preventDefault(); if (!drag) setDrag(true); }}
          onDragLeave={e => { if (e.currentTarget === e.target) setDrag(false); }}
          onDrop={e => { e.preventDefault(); setDrag(false); onFiles(e.dataTransfer.files); }}>
          <i className="ti ti-photo"></i>
          <span>{reading ? "Reading your product media…" : drag ? "Drop to add" : "Drop or select product media"}</span>
        </div>
        <div className="i4-librow">{libBtn}</div>
        {libOpen && <window.ProductLibraryPanel initialFilter={{}} attached={rows.filter(r => r.pid).map(r => r.pid)} onClose={() => setLibOpen(false)} onAdd={addLib} />}
      </div>
      {rows.length ? (
        <div className="i4-ptab">
          <div className="i4-ptab__hd"><span></span><span>Name</span><span>Price</span><span>Description</span><span>Asset format</span><span></span></div>
          {rows.map(row => (
            <div className="i4-ptab__r" key={row.id}>
              <span className={"i4-pthumb" + (reading && row.url ? " is-scanning" : "")}>{row.url ? <img src={row.url} alt={row.name} /> : <i className="ti ti-shirt"></i>}</span>
              <input className="i4-in" value={row.name} onChange={e => set(row.id, "name", e.target.value)} />
              <span className="i4-price"><input className="i4-in" value={row.price} onChange={e => set(row.id, "price", e.target.value)} /><i>USD</i></span>
              <input className="i4-in" value={row.desc} onChange={e => set(row.id, "desc", e.target.value)} />
              <span className="i4-sel"><select value={row.fmt} onChange={e => set(row.id, "fmt", e.target.value)}>{ASSET_FMTS.map(f => <option key={f}>{f}</option>)}</select><i className="ti ti-selector"></i></span>
              <button className="i4-del" onClick={() => setRows(r => r.filter(x => x.id !== row.id))} aria-label={"Remove " + row.name}><i className="ti ti-trash"></i></button>
            </div>
          ))}
          <button className="i4-addp" onClick={pick}><i className="ti ti-plus"></i>Add products</button>
        </div>
      ) : (
        <div className="i4-pempty">
          <span className="i4-pempty__i"><i className="ti ti-shirt"></i></span>
          <div className="i4-pempty__t">You didn't add any product yet</div>
          <div className="i4-pempty__s">Add and manage your products on this page.</div>
          <button className="i3-btn i3-btn--p" onClick={pick}><i className="ti ti-plus"></i>Add products</button>
          <div className="i4-pempty__or">{libBtn}</div>
        </div>
      )}
    </React.Fragment>
  );
}
const COUNTRY_FREQ = ["Australia", "Brazil", "China", "France", "Germany", "Japan", "Korea", "New Zealand", "United Kingdom", "United States"];
const COUNTRY_REGIONS = [
  ["Africa", ["Algeria", "Djibouti", "Egypt", "Kenya", "Morocco", "Nigeria", "South Africa"]],
  ["Americas", ["Argentina", "Brazil", "Canada", "Chile", "Colombia", "Mexico", "United States"]],
  ["Asia", ["China", "India", "Indonesia", "Japan", "Korea", "Malaysia", "Singapore", "Thailand", "Vietnam"]],
  ["Europe", ["Austria", "Belgium", "Denmark", "France", "Germany", "Ireland", "Italy", "Netherlands", "Norway", "Poland", "Portugal", "Spain", "Sweden", "Switzerland", "United Kingdom"]],
  ["Oceania", ["Australia", "New Zealand"]]
];
const COUNTRY_ALL = COUNTRY_REGIONS.flatMap(([, xs]) => xs);
const AUD_OPTS = {
  genders: ["Women", "Men", "Non-binary"],
  ages: ["18–24", "25–34", "35–44", "45–54", "55+"]
};
const PROFILES = [
  { name: "Retailer A platform buyer", color: "#6d4cd9", desc: "Buys footwear on the platform several times a year." },
  { name: "Retailer C full-price shopper", color: "#d6563a", desc: "Buys at full price in department retail." },
  { name: "Fashion-forward 25–34", color: "#d69d2b", desc: "Reads the category as fashion first." },
  { name: "Conservative 35–55 buyer", color: "#3a8518", desc: "Buys less often and keeps things longer." },
  { name: "Core loyalist", color: "#0f9b8e", desc: "Buys the franchise every season." },
  { name: "Trend-led switcher", color: "#0070eb", desc: "Follows silhouettes over brands." },
  { name: "Lapsed customer", color: "#8c5800", desc: "Owned the brand once, moved to a competitor." },
  { name: "Value seeker", color: "#636c79", desc: "Waits for markdown or shops off-price." }
  /* The eight above are all sell-in shapes — retailer buyers and loyalists —
     which is right for the account moment and wrong for the six others.
     window.EI_PROFILES adds the ones the other use cases field against
     (category newcomers, premium payers, competitor buyers). They live in the
     use-case file because that is where the audiences that reference them
     live; concatenating here keeps one list for the Add-group menu. */
].concat(window.EI_PROFILES || []);
const initials = (n) => n.split(/[\s&]+/).filter(Boolean).slice(0, 2).map(w => w[0]).join("").toUpperCase();

/* searchable add-menu: frequently used first, then the full list */
function AddMenu({ label, freq, all, groups, chosen, onPick, onCreate }) {
  const [open, setOpen] = s4(false);
  const [q, setQ] = s4("");
  const wrap = r4(null);
  e4(() => {
    if (!open) return;
    const away = (ev) => { if (wrap.current && !wrap.current.contains(ev.target)) setOpen(false); };
    document.addEventListener("mousedown", away);
    return () => document.removeEventListener("mousedown", away);
  }, [open]);
  const m = (x) => !q || x.toLowerCase().includes(q.toLowerCase());
  const fr = (freq || []).filter(m).filter(x => !chosen.includes(x));
  const ok = (x) => m(x) && !chosen.includes(x) && !fr.includes(x);
  const rest = all.filter(ok);
  const sections = groups ? groups.map(([g, xs]) => [g, xs.filter(ok)]).filter(([, xs]) => xs.length) : null;
  const take = (v) => { onPick(v); setQ(""); setOpen(false); };
  return (
    <div className="i4-add" ref={wrap}>
      <button type="button" className={"i4-add__b" + (open ? " on" : "")} onClick={() => setOpen(o => !o)}>
        {label}<i className="ti ti-selector"></i>
      </button>
      {open && (
        <div className="i4-menu">
          <div className="i4-menu__s"><i className="ti ti-search"></i><input autoFocus value={q} placeholder="Search…" onChange={e => setQ(e.target.value)} /></div>
          <div className="i4-menu__l">
            {!!fr.length && <div className="i4-menu__h">Frequently used</div>}
            {fr.map(x => <button type="button" className="i4-menu__o" key={"f" + x} onClick={() => take(x)}>{x}</button>)}
            {sections ? sections.map(([g, xs]) => (
              <React.Fragment key={g}>
                <div className="i4-menu__h">{g}</div>
                {xs.map(x => <button type="button" className="i4-menu__o" key={g + x} onClick={() => take(x)}>{x}</button>)}
              </React.Fragment>
            )) : (
              <React.Fragment>
                {!!rest.length && !!fr.length && <div className="i4-menu__h">All</div>}
                {rest.map(x => <button type="button" className="i4-menu__o" key={x} onClick={() => take(x)}>{x}</button>)}
              </React.Fragment>
            )}
            {!fr.length && !rest.length && <div className="i4-menu__e">Nothing matches “{q}”</div>}
          </div>
          {onCreate && <button type="button" className="i4-menu__new" onClick={() => { setOpen(false); onCreate(); }}><i className="ti ti-plus"></i>Create new consumer profile</button>}
        </div>
      )}
    </div>
  );
}

const PROFILE_COLORS = ["#3a8518", "#a5cf8e", "#050301", "#9aa4af", "#5c6b7a", "#c5d2dd", "#c0392b", "#f0a9a0", "#0070eb", "#8fc7f5", "#c78a12", "#f3ce7c", "#7040d6", "#c0a8f0"];
function ProfileModal({ onClose, onSave }) {
  const [name, setName] = s4("");
  const [color, setColor] = s4(PROFILE_COLORS[0]);
  const [desc, setDesc] = s4("");
  const [crit, setCrit] = s4({ genders: [], ages: [] });
  const [save, setSave] = s4(false);
  const tog = (k, v) => setCrit(c => ({ ...c, [k]: c[k].includes(v) ? c[k].filter(x => x !== v) : [...c[k], v] }));
  const QS = [{ k: "genders", q: "What's your gender?", tag: "Gender", opts: ["Male", "Female", "Non-binary", "Prefer not to say"] },
    { k: "ages", q: "How old are you?", tag: "Age", opts: ["<18", "18–24", "25–34", "35–44", "45–54", "55+"] }];
  return (
    <div className="i4-veil" onMouseDown={onClose}>
      <div className="i4-pmodal" onMouseDown={e => e.stopPropagation()}>
        <div className="i4-pmodal__hd">
          <b>Create new consumer profile</b>
          <button className="i4-x" onClick={onClose}><i className="ti ti-x"></i></button>
        </div>
        <div className="i4-pmodal__name">
          <span className="i4-pmark" style={{ background: color }}>{initials(name || "Profile Name")}</span>
          <input value={name} placeholder="Profile Name" onChange={e => setName(e.target.value)} />
          <i className="ti ti-pencil"></i>
        </div>
        <div className="i4-pmodal__body">
          <div className="i4-pcol">
            <div className="i4-plab">Study questions</div>
            {QS.map(g => (
              <div className="i4-pq" key={g.k}>
                <div className="i4-pq__hd"><span>{g.q}</span><i className="i4-ptag">{g.tag}</i></div>
                <div className="i4-audf__c">{g.opts.map(o => <button key={o} type="button" className={"i4-chip" + (crit[g.k].includes(o) ? " on" : "")} onClick={() => tog(g.k, o)}>{o}</button>)}</div>
              </div>
            ))}
          </div>
          <div className="i4-pside">
            <div className="i4-plab">Color</div>
            <div className="i4-pswatch">{PROFILE_COLORS.map(c => <button key={c} type="button" className={"i4-psw" + (c === color ? " on" : "")} style={{ background: c }} onClick={() => setColor(c)} aria-label={c} />)}</div>
            <div className="i4-plab">Description</div>
            <textarea className="i4-audta" rows={3} value={desc} placeholder="Describe who this profile represents (optional)" onChange={e => setDesc(e.target.value)} />
            <label className="i4-pchk"><input type="checkbox" checked={save} onChange={e => setSave(e.target.checked)} /><span>Also save to brand library</span></label>
            <div className="i4-pchk__n">Saves this profile to brand level so other studies can apply this profile.</div>
          </div>
        </div>
        <div className="i4-pmodal__ft">
          <button className="i3-btn" onClick={onClose}>Cancel</button>
          <button className="i3-btn i3-btn--p" disabled={!name.trim()} onClick={() => onSave({ name: name.trim(), color, desc })}>Create profile</button>
        </div>
      </div>
    </div>
  );
}

function Audience4({ t, aud, setAud }) {
  const sel = aud;
  const [other, setOther] = s4("");
  const [profiles, setProfiles] = s4(PROFILES);
  const [creating, setCreating] = s4(false);
  const toggle = (k, v) => setAud(s => ({ ...s, [k]: s[k].includes(v) ? s[k].filter(x => x !== v) : [...s[k], v] }));
  const drop = (k, v) => setAud(s => ({ ...s, [k]: s[k].filter(x => x !== v) }));
  const add = (k, v) => setAud(s => ({ ...s, [k]: s[k].includes(v) ? s[k] : [...s[k], v] }));
  const profOf = (n) => profiles.find(p => p.name === n);
  return (
    <React.Fragment>
      <div className="i4-audtot"><b>{t.total.toLocaleString()}</b> suggested respondents in total</div>
      <div className="i4-audset">
        <div className="i4-audf">
          <div className="i4-audf__l">Country<span>Where we field</span></div>
          <div className="i4-audf__c">
            {sel.countries.map(v => <span className="i4-tag" key={v}>{v}<button type="button" onClick={() => drop("countries", v)} aria-label={"Remove " + v}><i className="ti ti-x"></i></button></span>)}
            <AddMenu label="Add country…" freq={COUNTRY_FREQ} all={COUNTRY_ALL} groups={COUNTRY_REGIONS} chosen={sel.countries} onPick={v => add("countries", v)} />
          </div>
        </div>
        {["genders", "ages"].map(k => (
          <div className="i4-audf" key={k}>
            <div className="i4-audf__l">{k === "genders" ? "Gender" : "Age"}</div>
            <div className="i4-audf__c">
              {AUD_OPTS[k].map(v => <button key={v} type="button" className={"i4-chip" + (sel[k].includes(v) ? " on" : "")} onClick={() => toggle(k, v)}>{v}</button>)}
            </div>
          </div>
        ))}
        <div className="i4-audf">
          <div className="i4-audf__l">Key groups</div>
          <div className="i4-audf__c">
            {sel.keyGroups.map(v => {
              const p = profOf(v);
              return <span className="i4-tag i4-tag--p" key={v}><i className="i4-tag__m" style={{ background: (p && p.color) || "#636c79" }}>{initials(v)}</i>{v}<button type="button" onClick={() => drop("keyGroups", v)} aria-label={"Remove " + v}><i className="ti ti-x"></i></button></span>;
            })}
            <AddMenu label="Add group…" freq={profiles.slice(0, 4).map(p => p.name)} all={profiles.map(p => p.name)} chosen={sel.keyGroups} onPick={v => add("keyGroups", v)} onCreate={() => setCreating(true)} />
          </div>
        </div>
        <div className="i4-audf">
          <div className="i4-audf__l">Other requirements</div>
          <textarea className="i4-audta" rows={3} value={other} onChange={e => setOther(e.target.value)}
            placeholder="e.g. bought footwear in the last 12 months, household income over £50k, shops both online and in store" />
        </div>
      </div>
      {creating && <ProfileModal onClose={() => setCreating(false)} onSave={(p) => { setProfiles(v => [...v, p]); add("keyGroups", p.name); setCreating(false); }} />}
    </React.Fragment>
  );
}
/* ---------------------------------------------------------------------
   Decision context, derived rather than picked.

   TIERS stays exactly as it was — it is still the model everything
   downstream reads (audience, publish, the objectives pages). What changes
   is who chooses it. The user used to pick Quick / Standard / Extended,
   which is a method bundled with a timeline: choosing it meant choosing the
   approach before the question had been stated. Now the three chat answers
   decide which tier applies, and the rail reports the consequence.

   Confidence is the one word for the axis. "Certainty", "insight depth",
   "fidelity" and "Gut check / Decision support / Defensible research" were
   all names for the same thing. Budget is the one word for the cost, because
   credits are our unit rather than the user's concern.
   --------------------------------------------------------------------- */
const DC_WHEN = { today: "Today", days: "In a few days", weeks: "In a week or two", open: "No hard deadline" };
const DC_WHO = { exec: "Executive leadership", team: "My team", cross: "Colleagues in other teams", self: "Just myself" };
const DC_TEAMS = { design: "Design and product", merch: "Merchandising and planning", sales: "Sales and marketing" };
const DC_BUDGET = { cheap: "Cheapest mix", flexible: "Flexible on cost", best: "Best results" };

/* The four answers, read back as consequences.

   The rail does not repeat the questions, it reports what they cost. Timeline
   becomes a turnaround, confidence becomes a bar with a blurb, stakeholders
   become the reason the bar sits where it does, and budget becomes credits and
   the saving Digital Twins bought.

   The arithmetic is window.AT_PLAN, which the chat reads too, so the number
   MakerChat says out loud and the number in the rail are the same number by
   construction rather than by discipline. */
function dcDerive(ans) {
  if (!ans) return null;
  const out = {};
  const p = (window.AT_PLAN && window.AT_PLAN(ans)) || null;
  if (ans.when) {
    /* Any question can be answered in free text, in which case the value is
       the user's own words rather than an option id. Fall back to showing it. */
    out.timeline = {
      v: DC_WHEN[ans.when] || ans.when,
      note: p ? (p.late ? "Needs " + p.leadLabel + ", past that date" : "Results in " + p.leadLabel) : "Sized once the rest lands",
      inferred: ans.when === "weeks"
    };
  }
  if (ans.who) {
    out.who = {
      v: DC_WHO[ans.who] || ans.who,
      note: ans.who === "cross"
        ? (DC_TEAMS[ans.teams] || ans.teams || null)
        : (p && p.auto ? "Set the confidence bar" : null)
    };
  }
  if (p) {
    out.bar = p.bar;
    out.tier = p.tier;
    out.confidence = { v: p.label, note: p.blurb, inferred: p.auto };
    /* A Digital Twin costs a tenth of a recruited shopper, so the saving is
       the thing worth showing and credits are never a lump sum. */
    out.budget = {
      v: p.credits.toLocaleString() + " credits",
      note: (DC_BUDGET[ans.budget] || "Balanced mix") + " · saved " + p.saved.toLocaleString()
    };
    out.audience = { total: p.total, twins: p.twins, humans: p.humans, markets: p.markets };
  }
  return out;
}

/* right rail — the four, each blank until the chat turn that earns it */
const TIERS = [
  { id: "quick", label: "Quick", sub: "~2 hrs · Digital Twins",
    steps: [["Today", "You start the study"], ["About 2 hours", "Digital Twins answer"], ["Today", "Your three pages land"]],
    who: "Digital Twins of your shoppers", total: 300, unit: "twins", perMarket: 100, markets: "UK, FR, DE", groups: 2,
    countries: ["United Kingdom", "France", "Germany"], genders: ["Women"], ages: ["18–24", "25–34", "35–44"],
    keyGroups: ["Retailer A platform buyer", "Fashion-forward 25–34"], segIds: ["retailer a", "ff2534"] },
  { id: "standard", label: "Standard", sub: "2–3 days · Twins + consumers",
    steps: [["Today", "You start the study"], ["2–3 days", "Twins, then real shoppers"], ["Friday", "Your three pages land"]],
    who: "Women 18–44 who buy lifestyle footwear", total: 1240, unit: "shoppers", perMarket: 248, markets: "UK, FR, DE", groups: 4,
    countries: ["United Kingdom", "France", "Germany"], genders: ["Women"], ages: ["18–24", "25–34", "35–44"],
    keyGroups: ["Retailer A platform buyer", "Fashion-forward 25–34", "Retailer C full-price shopper", "Core loyalist"], segIds: ["retailer a", "ff2534", "retailer c", "loyalist"] },
  { id: "extended", label: "Extended", sub: "10–14 days · full consumer panel",
    steps: [["Today", "You start the study"], ["10–14 days", "Full consumer panel"], ["In about 2 weeks", "Your three pages land"]],
    who: "Women 18–44 who buy lifestyle footwear", total: 2000, unit: "shoppers", perMarket: 500, markets: "UK, FR, DE, US", groups: 5,
    countries: ["United Kingdom", "France", "Germany", "United States"], genders: ["Women", "Men"], ages: ["18–24", "25–34", "35–44", "45–54"],
    keyGroups: ["Retailer A platform buyer", "Fashion-forward 25–34", "Retailer C full-price shopper", "Core loyalist", "Lapsed customer"], segIds: ["retailer a", "ff2534", "retailer c", "loyalist", "lapsed"] }
];
/* the chat sizes off the same table the rail reads */
window.AT_TIER_INFO = TIERS.reduce((m, x) => { m[x.id] = { total: x.total, markets: x.markets, perMarket: x.perMarket, who: x.who }; return m; }, {});

/* Humans and Twins, which is the only audience split that costs money. */
function AudSplit({ a, who }) {
  const pct = a.total ? Math.round(a.twins / a.total * 100) : 0;
  return (
    <React.Fragment>
      <div className="i4-audtot"><b>{a.total.toLocaleString()}</b> respondents{a.markets ? " · " + a.markets : ""}</div>
      <div className="i4-split">
        <i className="i4-split__t" style={{ width: pct + "%" }}></i>
        <i className="i4-split__h" style={{ width: (100 - pct) + "%" }}></i>
      </div>
      <div className="i4-legend">
        <span><i className="i4-key i4-key--t"></i>Digital Twins<b>{a.twins.toLocaleString()}</b></span>
        <span><i className="i4-key i4-key--h"></i>Recruited shoppers<b>{a.humans.toLocaleString()}</b></span>
      </div>
      {who && <div className="i4-audwho">{who}</div>}
    </React.Fragment>
  );
}

function DCRow({ k, d }) {
  return (
    <div className="i4-arow">
      <b>{k}</b>
      <span>
        {d
          ? <React.Fragment>
              <span className={"i4-dcv" + (d.inferred ? " is-inf" : "")}>{d.v}</span>
              {d.note && <span className="i4-dcn">{d.note}</span>}
            </React.Fragment>
          : <span className="i4-dcw">Waiting on the chat</span>}
      </span>
    </div>
  );
}
function Rail4({ tier, setTier, onPreview, onPublish, aud, onEditAudience, live, dc, ans, who }) {
  const t = TIERS.find(x => x.id === tier);
  return (
    <div className="i4-rail">
      <Resz4 side="right" min={238} />
      <div style={{ display: "flex", gap: 8, marginBottom: 18 }}>
        {live ? (
          <React.Fragment>
            <button className="i3-btn i3-btn--icon" title="Preview" aria-label="Preview" onClick={onPreview}><i className="ti ti-player-play"></i></button>
            <span className="srp-status" style={{ flex: 1, justifyContent: "center", height: 38, borderRadius: 8 }}><i className="ti ti-circle-check-filled"></i>Fielded</span>
          </React.Fragment>
        ) : null}
        {live ? null : (
        <React.Fragment>
        <button className="i3-btn i3-btn--icon" title="Preview" aria-label="Preview" onClick={onPreview}><i className="ti ti-player-play"></i></button>
        <span className="i4-gowrap" style={{ flex: 1 }}>
          <button className="i3-btn i3-btn--p" style={{ width: "100%", height: 38, justifyContent: "center", fontSize: 13.5, fontWeight: 700 }}
            onClick={() => onPublish && onPublish(tier, dc, ans)}>Check Out<i className="ti ti-arrow-right"></i></button>
        </span>
        </React.Fragment>
        )}
      </div>
      <div className="i4-sec">
        <div className="i4-sec__k">DECISION CONTEXT</div>
        <DCRow k="Timeline" d={dc && dc.timeline} />
        <DCRow k="Confidence" d={dc && dc.confidence} />
        <DCRow k="Stakeholders" d={dc && dc.who} />
        <DCRow k="Budget" d={dc && dc.budget} />
        {dc && dc.confidence && (
          <div className="i3-tl" style={{ marginTop: 12 }}>
            {t.steps.map(([k, v], i) => (
              <div className={"i3-tl__r" + (i === 2 ? " soft" : "")} key={i}><span className="i3-tl__d"></span><span className="i3-tl__t"><b>{k}</b><span>{v}</span></span></div>
            ))}
          </div>
        )}
      </div>
      {/* Country, gender, age and key groups all used to sit here, and none of
          them is a decision anyone makes on this screen — they belong to the
          Audience tab, one click away. What the rail owes the user is the one
          split that costs money. */}
      <div className="i4-sec">
        <div className="i4-sec__k">AUDIENCE</div>
        {/* `who` and the market list follow the study, not the tier. The tier's
            own copy is one sentence — "Women 18–44 who buy lifestyle footwear"
            — and one frozen market string, both of which were read out over
            every use case. The markets are derived from the countries actually
            selected on the Audience tab, so editing the audience moves the
            rail instead of leaving it asserting UK, FR, DE. */}
        {dc && dc.audience
          ? <AudSplit a={Object.assign({}, dc.audience, { markets: window.EI_MARKETS(aud && aud.countries) || dc.audience.markets })} who={who} />
          : <div className="i4-audtot"><span className="i4-dcw">Sized once the chat has what it needs</span></div>}
        <button className="i4-audedit" onClick={onEditAudience}>Edit the audience<i className="ti ti-arrow-right"></i></button>
      </div>
    </div>
  );
}

/* respondent preview — laptop and mobile */
function Preview4({ onClose }) {
  const qs = D4.objectives.flatMap(o => o.qs.map(q => ({ ...q, sec: "Objective " + o.n })));
  const [i, setI] = s4(0);
  const [dev, setDev] = s4("laptop");
  const [pick, setPick] = s4({});
  const q = qs[i];
  const opts = q.o || OPTS[q.t];
  return (
    <div className="i4-veil" onMouseDown={onClose}>
      <div className="i4-modal" onMouseDown={e => e.stopPropagation()}>
        <div className="i4-mhd">
          <span className="i4-mhd__t">Preview</span>
          <span className="i4-mhd__ey"></span>
          <span className="i4-mhd__sp"></span>
          <div className="i4-dev">
            <button className={dev === "laptop" ? "on" : ""} onClick={() => setDev("laptop")}><i className="ti ti-device-laptop"></i>Laptop</button>
            <button className={dev === "mobile" ? "on" : ""} onClick={() => setDev("mobile")}><i className="ti ti-device-mobile"></i>Mobile</button>
          </div>
          <button className="i4-x" onClick={onClose}><i className="ti ti-x"></i></button>
        </div>
        <div className="i4-stagearea">
          <div className={"i4-screen i4-screen--" + dev}>
            <div className="i4-prog"><i style={{ width: ((i + 1) / qs.length * 100) + "%" }}></i></div>
            <div className="i4-qbody">
              <div className="i4-qsec">{q.sec}</div>
              <div className="i4-qtext">{q.l}</div>
              {opts ? (
                <div className="i4-opts">
                  {opts.map(o => (
                    <button key={o} className={"i4-opt" + (pick[i] === o ? " on" : "")} onClick={() => setPick(p => ({ ...p, [i]: o }))}>
                      <span className="i4-mark">{pick[i] === o && <i className="ti ti-check"></i>}</span>{o}
                    </button>
                  ))}
                </div>
              ) : (
                <textarea rows={4} placeholder="Type your answer…" style={{ font: "inherit", fontSize: 13.5, padding: 12, border: "1px solid #e5ebf1", borderRadius: 11, resize: "none", outline: "none" }} />
              )}
            </div>
            <div className="i4-qfoot"><span>{i + 1} of {qs.length}</span><span className="i4-qfoot__sp"></span><button className="i4-cta" onClick={() => setI(Math.min(qs.length - 1, i + 1))}>{i >= qs.length - 1 ? "Submit" : "Continue"}</button></div>
          </div>
        </div>
        <div className="i4-mnav">
          <button disabled={i === 0} onClick={() => setI(Math.max(0, i - 1))}>Previous</button>
          <button disabled={i >= qs.length - 1} onClick={() => setI(Math.min(qs.length - 1, i + 1))}>Next</button>
          <span className="i4-mnav__sp"></span>
          <span></span>
        </div>
      </div>
    </div>
  );
}

const TABS4 = [
  { id: "what", label: "Output example", icon: "bulb", C: What4 },
  { id: "qs", label: "Study editor", icon: "list-details", sub: () => "7", C: Questions4 },
  { id: "assets", label: "Assets", icon: "shirt", sub: () => "14", C: Assets4 },
  { id: "audience", label: "Audience", icon: "users", sub: t => t.total.toLocaleString(), C: Audience4 }
];

function Screen4({ bare, brief, briefFiles, onPublish, initialTab, manual, embedded, moment, studyName }) {
  /* The fallback used to be window.EI2 — the Key Account Sell-In study — and
     EI_MOMENTS only held two of the seven moments, so picking Marketing,
     Pricing, Naming or Strategy Kickoff on home opened a study about which
     styles each account should carry (Lucy, 2026-09-09). All seven are in
     EI_MOMENTS now, and the fallback is the generic study, which is what a
     typed brief with no moment should get: three pages that fit any read and
     no claim to a use case nobody picked. */
  D4 = (window.EI_MOMENTS && window.EI_MOMENTS[moment]) || window.EI_GENERIC;
  const [tab, setTab] = s4(initialTab || "what");
  const [tier, setTier] = s4("standard");
  const [dcAns, setDcAns] = s4({});
  const [preview, setPreview] = s4(false);
  const [uploaded, setUploaded] = s4([]);
  // Products are only ever the user's own: whatever they attached to the brief,
  // plus anything dropped on the Assets tab. Never seeded, never faked.
  const [rows, setRows] = s4(() => (briefFiles || []).map(f => ({
    id: f.id, name: f.name.replace(/\.[^.]+$/, ""), price: "", desc: "", fmt: "off-body sample", url: f.url })));
  /* The moment decides WHO the study fields against; the tier decides HOW MANY
     of them it can afford. The two are independent facts and TIERS used to own
     both, so every use case fielded against Women 18–44 who buy lifestyle
     footwear, segmented by "Retailer A platform buyer" — the sell-in audience,
     on a pricing study. Now the use case brings the countries, gender, ages
     and key groups, and the tier trims them to what it buys: markets to the
     tier's own market count, key groups to its group count. Stepping up to
     Extended is what buys the fourth market. */
  const audOf = (x) => {
    const a = window.EI_AUD(moment);
    return {
      countries: a.countries.slice(0, x.countries.length),
      genders: a.genders.slice(),
      ages: a.ages.slice(),
      keyGroups: a.keyGroups.slice(0, x.groups)
    };
  };
  const [aud, setAud] = s4(() => audOf(TIERS.find(x => x.id === (tier || "standard"))));
  const [reading, setReading] = s4(false);
  const [secs, setSecs] = s4(() => manual ? [] : buildSections());
  const [objTitles, setObjTitles] = s4(() => D4.objectives.map(o => o.label));
  const bodyRef = r4(null);
  const pickTier = (id) => { setTier(id); setAud(audOf(TIERS.find(x => x.id === id))); };
  const dc = dcDerive(dcAns);
  /* The answers choose the tier; the user no longer does. The dock submits a
     whole card at once, so the rail fills in one move instead of jittering
     question by question while someone is still making up their mind. */
  const answerDC = (patch) => {
    const next = Object.assign({}, dcAns, patch);
    setDcAns(next);
    const d = dcDerive(next);
    if (d && d.tier && d.tier !== tier) pickTier(d.tier);
  };
  const T = TABS4.find(x => x.id === tab);
  const t = TIERS.find(x => x.id === tier);
  function handleAssetFiles(fileList) {
    const files = Array.from(fileList || []).filter(f => f.type.startsWith("image/"));
    if (!files.length) return;
    const items = files.map((f, i) => ({ id: "u" + Date.now() + "-" + i, url: URL.createObjectURL(f), name: f.name }));
    setUploaded(prev => [...prev, ...items]);
    setRows(prev => [...items.map(u => ({ id: u.id, name: u.name.replace(/\.[^.]+$/, ""), price: "", desc: "", fmt: "off-body sample", url: u.url })), ...prev]);
    setReading(true);
    setTimeout(() => setReading(false), 1200);
  }
  const work = (
    <React.Fragment>
        {embedded ? null : <Chat4 brief={brief} manual={manual} moment={moment} dc={dcAns} onDC={answerDC} />}
        <div className="i3-main">
          <div className="i3-tabs">
            {TABS4.map(x => <button key={x.id} className={"i3-tab" + (x.id === tab ? " on" : "")} onClick={() => setTab(x.id)}><i className={"ti ti-" + x.icon}></i>{x.label}{x.id === "assets" ? <span>{rows.length}</span> : x.id === "qs" ? <span>{secs.reduce((a, s) => a + s.qs.length, 0)}</span> : x.sub && <span>{x.sub(t)}</span>}</button>)}
          </div>
          <div className="i3-body" ref={bodyRef}><div className="i4-pane">{tab === "assets" ? <Assets4 reading={reading} onFiles={handleAssetFiles} rows={rows} setRows={setRows} /> : tab === "audience" ? <Audience4 t={t} aud={aud} setAud={setAud} /> : tab === "qs" ? <Questions4 manual={manual} rows={rows} secs={secs} setSecs={setSecs} scroller={bodyRef} objTitles={objTitles} setObjTitles={setObjTitles} /> : <T.C key={tier} t={t} manual={manual} objTitles={objTitles} onEditor={() => setTab("qs")} />}</div></div>
        </div>
        <Rail4 dc={dc} ans={dcAns} who={window.EI_AUD(moment).who} tier={tier} setTier={pickTier} onPreview={() => setPreview(true)} onPublish={onPublish} aud={aud} onEditAudience={() => setTab("audience")} live={embedded} />
    </React.Fragment>
  );
  if (embedded) return (
    <React.Fragment>
      {work}
      {preview && <Preview4 onClose={() => setPreview(false)} />}
    </React.Fragment>
  );
  if (bare) return (
    <div className="sf-work" style={{ position: "relative" }} data-screen-label="Intake">
      {work}
      {preview && <Preview4 onClose={() => setPreview(false)} />}
    </div>
  );
  return (
    <div className="i3-frame" style={{ width: 1440, height: 840, position: "relative" }} data-screen-label="Intake · simple">
      <div className="i3-top">
        <span className="i3-top__logo">MAKER<b>/</b>SIGHTS</span>
        <span className="i3-top__crumb">New study / {studyName || window.EH.studyFor(moment)}</span>
        <span className="i3-top__sp"></span>
      </div>
      <div className="i3-work">
        <div className="i3-nav">{["home", "clipboard-list", "shirt", "books"].map((ic, i) => <span key={ic} className={"i3-nav__b" + (i === 1 ? " on" : "")}><i className={"ti ti-" + ic}></i></span>)}</div>
        {work}
      </div>
      {preview && <Preview4 onClose={() => setPreview(false)} />}
    </div>
  );
}

const TW4 = /*EDITMODE-BEGIN*/{
  "zoom": 100
}/*EDITMODE-END*/;

function App4() {
  const [tweaks, setTweak] = window.useTweaks(TW4);
  const ref = r4(null);
  const [sc, setSc] = s4(1);
  e4(() => {
    const f = () => { if (ref.current) setSc(Math.min(1, (ref.current.clientWidth - 44) / 1440)); };
    f(); window.addEventListener("resize", f);
    return () => window.removeEventListener("resize", f);
  }, []);
  const z = sc * tweaks.zoom / 100;
  return (
    <React.Fragment>
      <div className="i4-stage">
        <div className="i3-bar">
          <span className="i3-bar__t">Intake — simple</span>
          <span className="i3-bar__n">Example chart inside each objective · one choice in the rail</span>
          <span className="i3-bar__sp"></span>
          <label>Zoom<input type="range" min="50" max="100" step="5" value={tweaks.zoom} onChange={e => setTweak("zoom", +e.target.value)} /><span style={{ width: 32, color: "#fff" }}>{tweaks.zoom}%</span></label>
        </div>
        <div className="i4-body" ref={ref}>
          <div className="i4-fit" style={{ transform: `scale(${z})`, width: 1440, height: 840 }}><Screen4 /></div>
        </div>
      </div>
      <window.TweaksPanel title="Intake — simple">
        <window.TweakSection label="View" />
        <window.TweakSlider label="Zoom" value={tweaks.zoom} min={50} max={100} step={5} unit="%" onChange={v => setTweak("zoom", v)} />
      </window.TweaksPanel>
    </React.Fragment>
  );
}

Object.assign(window, { IntakeScreen: Screen4, Resz4 });
if (!window.__COMBINED) ReactDOM.createRoot(document.getElementById("root")).render(<App4 />);
