// ce-flow-c.jsx — The Connection Experiment (version C) · full clickable flow
// Depends on ce-data-c.jsx (window.CE_QUESTIONS / computeResult) + ce-flow.css + ce-matrix.css.

const { useState: useS, useEffect: useE, useRef: useR } = React;

/* ---------------- data capture (Google Sheets) ---------------- */
function ceSessionId() {
  try {
    let id = localStorage.getItem("ce-session-id");
    if (!id) {
      id = "ce_" + Date.now().toString(36) + "_" + Math.random().toString(36).slice(2, 8);
      localStorage.setItem("ce-session-id", id);
    }
    return id;
  } catch (e) { return "ce_" + Date.now().toString(36); }
}

function ceFlatten(answers) {
  const a = answers || {};
  const mx = a.matrix || {};
  const join = (v) => Array.isArray(v) ? v.join(" | ") : (v == null ? "" : v);
  return {
    family:   join(mx.family),
    friends:  join(mx.friends),
    partner:  join(mx.partner),
    far_ones: join(a.q4),
    barriers: join(a.q5),
    role:     join(a.q6),
    location: join(a.q7),
    age:      join(a.q8),
    gender:   join(a.q9),
  };
}

function ceSend(payload) {
  const url = window.CE_ENDPOINT;
  if (!url) { console.log("[CE] No endpoint set \u2014 skipping save.", payload); return; }
  try {
    fetch(url, {
      method: "POST",
      mode: "no-cors",
      headers: { "Content-Type": "text/plain;charset=utf-8" },
      body: JSON.stringify(payload),
    }).catch(() => {});
  } catch (e) {}
}

/* ---------------- icons ---------------- */
function Glyphs({ light }) {
  return (
    <svg width="68" height="14" viewBox="0 0 70 14" fill="none" aria-hidden="true"
    style={{ color: "currentColor", opacity: light ? 1 : 0.92 }}>
      <rect x="0" y="8" width="3" height="6" rx="1" fill="currentColor" />
      <rect x="5" y="6" width="3" height="8" rx="1" fill="currentColor" />
      <rect x="10" y="3.5" width="3" height="10.5" rx="1" fill="currentColor" />
      <rect x="15" y="1" width="3" height="13" rx="1" fill="currentColor" />
      <path d="M24 5.6a11 11 0 0 1 14 0" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
      <path d="M26.6 8.2a7 7 0 0 1 8.8 0" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
      <circle cx="31" cy="11" r="1.5" fill="currentColor" />
      <rect x="46.5" y="2" width="19" height="11" rx="3" stroke="currentColor" strokeWidth="1.2" opacity="0.55" />
      <rect x="48.5" y="4" width="13" height="7" rx="1.4" fill="currentColor" />
      <rect x="67" y="5" width="1.6" height="5" rx="0.8" fill="currentColor" opacity="0.55" />
    </svg>);

}
function Chevron() {
  return (
    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
    strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6" /></svg>);

}
function Tick() {
  return (
    <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor"
    strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12.5l4.2 4.2L19 7" /></svg>);

}
function Pin() {
  return (
    <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor"
    strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 21s7-5.5 7-11a7 7 0 1 0-14 0c0 5.5 7 11 7 11z" /><circle cx="12" cy="10" r="2.4" />
    </svg>);

}

/* ---------------- shared bits ---------------- */
function StatusTime() {return <span className="ce-time">9:41</span>;}

function StagesProgress({ stage, stagePos, stageLen }) {
  const fills = [0, 1, 2].map((s) =>
  s < stage ? 100 : s === stage ? Math.round(stagePos / stageLen * 100) : 0
  );
  return (
    <div className="ce-prog">
      {fills.map((f, i) =>
      <span className="ce-stage-seg" key={i}><i style={{ width: f + "%" }} /></span>
      )}
    </div>);

}

function PhotoHeader({ photo, onBack, onSkip, photoH, focus }) {
  return (
    <div className="ce-photo" style={{ backgroundImage: `url(${photo})`, backgroundPosition: focus || "center", "--photo-h": photoH + "px" }}>
      <div className="ce-status on-photo"><StatusTime /><Glyphs light /></div>
      <div className="ce-photobar">
        <button className="ce-back" onClick={onBack} aria-label="Back"><Chevron /></button>
        {onSkip ? <button className="ce-skip" onClick={onSkip}>Skip</button> : <span />}
      </div>
    </div>);

}

/* ---------------- intro ---------------- */
function IntroScreen({ photo, onBegin }) {
  return (
    <div className="ce-intro" style={{ backgroundImage: `url(${photo})` }}>
      <div className="ce-intro-status"><StatusTime /><Glyphs light /></div>
      <div className="ce-intro-inner">
        <img className="ce-intro-mark" src="assets/logos/monograma-cool-ivory.png" alt="" />
        <p className="ce-intro-eyebrow">An experiment by Momenta</p>
        <h1 className="ce-intro-title">the connection experiment</h1>
        <p className="ce-intro-body">
          Connecting with the people you love used to be easy. Somewhere along the way it became a job.
          Answer a few honest questions and find out what kind of friend you really are, and the one
          move that brings you all closer.
        </p>
        <button className="ce-cta" onClick={onBegin}>Begin</button>
        <p className="ce-intro-meta">A few honest questions · about 3 minutes</p>
      </div>
    </div>);

}

/* ---------------- matrix (per-row segmented scale) ---------------- */
function boldPhrase(text, phrases) {
  if (!phrases) return text;
  const list = Array.isArray(phrases) ? phrases : [phrases];
  let parts = [text];
  list.forEach((ph, pi) => {
    const out = [];
    parts.forEach((seg) => {
      if (typeof seg !== "string") { out.push(seg); return; }
      let rest = seg, idx, n = 0;
      while ((idx = rest.indexOf(ph)) >= 0) {
        if (idx > 0) out.push(rest.slice(0, idx));
        out.push(<strong key={"em" + pi + "-" + (n++)} className="ce-em">{ph}</strong>);
        rest = rest.slice(idx + ph.length);
      }
      if (rest) out.push(rest);
    });
    parts = out;
  });
  return parts;
}

function MatrixScreen({ q, answer, setAnswer, onBack, onSkip, onNext }) {
  const value = answer && typeof answer === "object" ? answer : {};
  const setRow = (key, val) => setAnswer(q.id, (prev) => {
    const base = prev && typeof prev === "object" ? prev : {};
    return { ...base, [key]: val };
  });
  const pts = q.scale.points;
  const answered = q.rows.every((r) => value[r.key] != null);

  return (
    <div className="ce-screen">
      <PhotoHeader photo={q.photo} onBack={onBack} onSkip={onSkip} photoH={168} focus={CE_FOCUS[q.id]} />
      <div className="ce-panel">
        <StagesProgress stage={q.stage} stagePos={q.stagePos} stageLen={q.stageLen} />
        <div className="ce-q ce-q-mx">
          <p className="ce-eyebrow">{q.eyebrow}</p>
          <h2 className="ce-title sm">{boldPhrase(q.title, q.bold)}</h2>
        </div>

        <div className="ce-sc-stack">
          {q.rows.map((row) => {
            const v = value[row.key];
            const na = v === "na";
            const selIdx = na ? -1 : pts.indexOf(v);
            return (
              <div className="ce-sc-row" key={row.key}>
                <div className="ce-sc-head">
                  <span className="ce-sc-label">{row.label}</span>
                </div>
                <div className={"ce-sc-bar" + (na ? " off" : "")}>
                  <span className="ce-sc-line" aria-hidden="true" />
                  {pts.map((p, i) =>
                  <button type="button" key={p} aria-label={p}
                    className={"ce-sc-hit" + (!na && i === selIdx ? " sel" : "")}
                    onClick={() => setRow(row.key, p)}>
                      <span className="ce-sc-dot" />
                    </button>
                  )}
                </div>
                <div className="ce-sc-ends">
                  {q.scale.labeled.map((li, k) =>
                  <span key={li} className={"ce-sc-end p" + k}>
                    {k === 0 ? pts[li].replace(" than", "\nthan") : pts[li]}
                  </span>
                  )}
                </div>
                <div className="ce-sc-naline">
                  <button type="button"
                    className={"ce-sc-na" + (na ? " on" : "")}
                    onClick={() => setRow(row.key, na ? null : "na")}>
                    {q.na}
                  </button>
                </div>
              </div>);

          })}
        </div>

        <div className="ce-foot">
          <button className="ce-cta" disabled={!answered} onClick={onNext}>Continue</button>
          <div className="ce-home" />
        </div>
      </div>
    </div>);

}

/* ---------------- question (single / multi / text) ---------------- */
function QuestionScreen({ q, answer, setAnswer, onBack, onSkip, onNext }) {
  const isMulti = q.type === "multi";
  const isText = q.type === "text";
  const photoH = q.options && q.options.length > 6 ? 210 : 248;

  const selectSingle = (opt) => setAnswer(q.id, opt);
  const toggleMulti = (opt) => {
    const cur = Array.isArray(answer) ? answer : [];
    setAnswer(q.id, cur.includes(opt) ? cur.filter((x) => x !== opt) : [...cur, opt]);
  };

  let answered;
  if (isText) answered = !!(answer && answer.trim());else
  if (isMulti) answered = Array.isArray(answer) && answer.length > 0;else
  answered = !!answer;

  // scroll affordance for long option lists
  const listRef = useR(null);
  const [fadeTop, setFadeTop] = useS(false);
  const [fadeBot, setFadeBot] = useS(false);
  const [remaining, setRemaining] = useS(0);
  const onListScroll = () => {
    const el = listRef.current;if (!el) return;
    setFadeTop(el.scrollTop > 4);
    const more = el.scrollTop + el.clientHeight < el.scrollHeight - 4;
    setFadeBot(more);
    if (!more) {setRemaining(0);return;}
    const bottom = el.scrollTop + el.clientHeight;
    let hidden = 0;
    el.querySelectorAll(".ce-row").forEach((r) => {
      if (r.offsetTop + r.offsetHeight - 8 > bottom) hidden++;
    });
    setRemaining(hidden);
  };
  const scrollMore = () => {
    const el = listRef.current;if (!el) return;
    el.scrollBy({ top: el.clientHeight * 0.82, behavior: "smooth" });
  };
  useE(() => {
    const el = listRef.current;if (!el) return;
    onListScroll();
    const canMove = el.scrollHeight > el.clientHeight + 6;
    const okMotion = window.matchMedia("(prefers-reduced-motion: no-preference)").matches;
    if (canMove && okMotion) {
      const t1 = setTimeout(() => el.scrollTo({ top: 16, behavior: "smooth" }), 420);
      const t2 = setTimeout(() => el.scrollTo({ top: 0, behavior: "smooth" }), 920);
      return () => {clearTimeout(t1);clearTimeout(t2);};
    }
  }, [q.id]);

  return (
    <div className="ce-screen">
      <PhotoHeader photo={q.photo} onBack={onBack} onSkip={onSkip} photoH={photoH} focus={CE_FOCUS[q.id]} />
      <div className="ce-panel">
        <StagesProgress stage={q.stage} stagePos={q.stagePos} stageLen={q.stageLen} />
        <div className="ce-q">
          <p className="ce-eyebrow">{q.eyebrow}</p>
          <h2 className={"ce-title" + (q.title.length > 90 ? " sm" : "")}>{q.title}</h2>
          {q.hint && <p className="ce-hint">{q.hint}</p>}
        </div>

        {isText ?
        <div className="ce-field-wrap">
            <input
            className="ce-field" type="text" placeholder={q.placeholder}
            value={answer || ""} onChange={(e) => setAnswer(q.id, e.target.value)} />
          
          </div> :

        <div className="ce-list-wrap">
            <div className="ce-list" ref={listRef} onScroll={onListScroll}>
              {q.options.map((opt) => {
              const sel = isMulti ? Array.isArray(answer) && answer.includes(opt) : answer === opt;
              return (
                <div key={opt} className={"ce-row" + (sel ? " sel" : "")}
                onClick={() => isMulti ? toggleMulti(opt) : selectSingle(opt)}>
                    <span className="ce-lbl">{opt}</span>
                    <span className={"ce-check" + (isMulti ? " sq" : "")}><Tick /></span>
                  </div>);

            })}
            </div>
            <div className={"ce-fade top" + (fadeTop ? " on" : "")} />
            <div className={"ce-fade bot" + (fadeBot ? " on" : "")} />
            <button type="button" className={"ce-more" + (fadeBot ? " on" : "")}
            onClick={scrollMore} aria-label="Show more options">
              <span>{remaining > 0 ? remaining + " more" : "More"}</span>
              <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor"
              strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M6 9l6 6 6-6" /></svg>
            </button>
          </div>
        }

        <div className="ce-foot">
          <button className="ce-cta" disabled={!answered} onClick={onNext}>Continue</button>
          <div className="ce-home" />
        </div>
      </div>
    </div>);

}

/* ---------------- reveal ---------------- */
function RevealScreen({ photo, result, onBack, onNext }) {
  return (
    <div className="ce-screen ce-reveal">
      <PhotoHeader photo={photo} onBack={onBack} onSkip={null} photoH={224} focus={CE_FOCUS.reveal} />
      <div className="ce-panel">
        <div className="ce-reveal-scroll">
          <p className="ce-type-eyebrow">{result.eyebrow}</p>
          <h2 className="ce-type-name" style={{ letterSpacing: "-1px" }}>{result.name}</h2>
          <div className="ce-type-rule" />
          <p className="ce-type-desc">{result.desc}</p>
          <div className="ce-cost">
            <p className="ce-cost-label">The cost</p>
            <p className="ce-cost-text">{result.cost}</p>
          </div>
          <div className="ce-move">
            <p className="ce-move-label">Your move</p>
            <p className="ce-move-text">{result.move}</p>
          </div>
        </div>
        <div className="ce-foot">
          <p className="ce-reveal-hook">Your move is a start. We built something bigger.</p>
          <button className="ce-cta ce-cta-go" onClick={onNext}>
            <span>Show me the fix</span>
            <svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor"
            strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6" /></svg>
          </button>
          <div className="ce-home" />
        </div>
      </div>
    </div>);

}

/* ---------------- waitlist (media-led, two screens) ---------------- */
const WL_MEDIA = "assets/imagery/coctel.jpg";

function PlayGlyph() {
  return (
    <span>
      <svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" aria-hidden="true"
      style={{ marginLeft: "3px" }}><path d="M8 5v14l11-7z" /></svg>
    </span>);

}

// SCREEN 1 — email capture
function WaitlistScreen({ email, setEmail, onBack, onSubmit }) {
  const valid = /\S+@\S+\.\S+/.test(email);
  return (
    <div className="ce-screen ce-wl2">
      <div className="ce-wl2-media" style={{ backgroundImage: `url(${WL_MEDIA})` }}>
        <div className="ce-status on-photo"><StatusTime /><Glyphs light /></div>
        <div className="ce-wl2-bar">
          <button className="ce-back" onClick={onBack} aria-label="Back"><Chevron /></button>
          <span />
        </div>
        <div className="ce-wl2-play"><PlayGlyph /></div>
        <span className="ce-wl2-reel">Warm reel · placeholder</span>
      </div>
      <div className="ce-wl2-panel">
        <p className="ce-wl2-kicker">The fix</p>
        <h2 className="ce-wl2-head">drifting apart is not normal. it is just unfixed.</h2>
        <p className="ce-wl2-sub">
          You just saw what is quietly pulling you and your people apart. We are building Momenta to fix
          exactly that, to take the planning, the chasing, and the coordinating off your plate so you
          actually see the people you love. Want in when it is ready?
        </p>
        <input
          className="ce-field" type="email" placeholder="you@email.com"
          value={email} onChange={(e) => setEmail(e.target.value)} />
        <button className="ce-cta" disabled={!valid} onClick={onSubmit}>Count me in</button>
        <a className="ce-wl2-link" href="https://www.instagram.com/no.more.soon/" target="_blank" rel="noopener noreferrer">
          or just follow along <u>@no.more.soon</u>
        </a>
        <div className="ce-home" />
      </div>
    </div>);

}

// SCREEN 2 — success state
function SuccessScreen({ onFollow }) {
  return (
    <div className="ce-screen ce-wl2">
      <div className="ce-wl2-media" style={{ backgroundImage: `url(${WL_MEDIA})` }}>
        <div className="ce-status on-photo"><StatusTime /><Glyphs light /></div>
      </div>
      <div className="ce-wl2-panel success">
        <h2 className="ce-wl2-head">you're in.</h2>
        <p className="ce-wl2-sub">
          We will find you when it is time. For now, follow along for what comes next.
        </p>
        <button className="ce-cta handle" onClick={onFollow}>Follow @no.more.soon</button>
        <div className="ce-home" />
      </div>
    </div>);

}

/* ---------------- app ---------------- */
const CE_STEPS = ["intro", ...CE_QUESTIONS.map((q) => q.id), "reveal", "waitlist"];
const CE_KEY = "ce-flow-c-state-v1";

function App() {
  const [stepIdx, setStepIdx] = useS(0);
  const [answers, setAnswers] = useS({});
  const [email, setEmail] = useS("");
  const [submitted, setSubmitted] = useS(false);
  const scalerRef = useR(null);
  const savedRef = useR(false);

  // restore
  useE(() => {
    try {
      const raw = localStorage.getItem(CE_KEY);
      if (raw) {
        const s = JSON.parse(raw);
        if (typeof s.stepIdx === "number") setStepIdx(s.stepIdx);
        if (s.answers) setAnswers(s.answers);
        if (s.email) setEmail(s.email);
      }
    } catch (e) {}
  }, []);
  // persist
  useE(() => {
    try {localStorage.setItem(CE_KEY, JSON.stringify({ stepIdx, answers, email }));} catch (e) {}
  }, [stepIdx, answers, email]);

  // scale to fit
  useE(() => {
    const fit = () => {
      if (window.matchMedia("(max-width: 520px)").matches) {
        if (scalerRef.current) scalerRef.current.style.transform = "none";
        return;
      }
      const s = Math.min((window.innerHeight - 28) / 844, (window.innerWidth - 20) / 390, 1);
      if (scalerRef.current) scalerRef.current.style.transform = `scale(${s})`;
    };
    fit();
    window.addEventListener("resize", fit);
    return () => window.removeEventListener("resize", fit);
  }, []);

  const setAnswer = (id, val) => setAnswers((a) => ({ ...a, [id]: typeof val === "function" ? val(a[id]) : val }));
  const go = (i) => setStepIdx(Math.max(0, Math.min(CE_STEPS.length - 1, i)));
  const next = () => go(stepIdx + 1);
  const back = () => go(stepIdx - 1);

  const step = CE_STEPS[stepIdx];

  // Save the completed quiz once, when the reveal is reached.
  useE(() => {
    if (step !== "reveal" || savedRef.current) return;
    const sid = ceSessionId();
    let already = false;
    try { already = localStorage.getItem("ce-quiz-saved") === sid; } catch (e) {}
    if (already) { savedRef.current = true; return; }
    savedRef.current = true;
    const result = computeResult(answers);
    ceSend({
      type: "quiz",
      sessionId: sid,
      timestamp: new Date().toISOString(),
      result: result.name,
      ...ceFlatten(answers),
    });
    try { localStorage.setItem("ce-quiz-saved", sid); } catch (e) {}
  }, [step]);

  let screen;
  if (step === "intro") {
    screen = <IntroScreen photo={CE_PHOTOS.intro} onBegin={next} />;
  } else if (step === "reveal") {
    screen = <RevealScreen photo={CE_PHOTOS.reveal} result={computeResult(answers)} onBack={back} onNext={next} />;
  } else if (step === "waitlist") {
    screen = submitted ?
    <SuccessScreen onFollow={() => window.open("https://www.instagram.com/no.more.soon/", "_blank", "noopener")} /> :
    <WaitlistScreen email={email} setEmail={setEmail}
    onBack={back} onSubmit={() => {
      ceSend({ type: "email", sessionId: ceSessionId(), email });
      setSubmitted(true);
    }} />;
  } else {
    const q = CE_QUESTIONS.find((x) => x.id === step);
    const Comp = q.type === "matrix" ? MatrixScreen : QuestionScreen;
    screen =
    <Comp
      key={q.id} q={q} answer={answers[q.id]} setAnswer={setAnswer}
      onBack={back} onSkip={next} onNext={next} />;


  }

  return (
    <div className="ce-stage">
      <div className="ce-scaler" ref={scalerRef}>
        <div className="ce-app">{screen}</div>
      </div>
    </div>);

}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
