// EpochCore · Configure your front desk — where the homepage CTA lands.
// Fill in your business once → a GROUNDED live preview of your own front-desk
// agent on the right. The preview answers ONLY from what's entered (config +
// sources); anything else is escalated to a human, never invented. The chat is
// canned-but-grounded (no API) — a faithful spec for the real backend.

const CFG_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "face": "light",
  "accent": "#6a3df0",
  "showSources": "on"
}/*EDITMODE-END*/;

window.__mountConfigure = function (DS) {
const { Button, Badge, Input, Card, FrameLabel, CheckItem, Stamp } = DS;
const { useState, useEffect, useRef, useMemo, useId } = React;

const MONO = "var(--font-mono)";
const SERIF = "var(--font-serif)";
const RULE = "1px solid var(--line)";
const RULE2 = "1px solid var(--line2)";
const RADIUS = "var(--radius)";
const FR = 10; // softer field radius (customer-facing form)

function uid() { return "s" + Math.random().toString(36).slice(2, 9); }
function fmtBytes(n) { if (!n) return "0 B"; if (n >= 1048576) return (n / 1048576).toFixed(1) + " MB"; if (n >= 1024) return (n / 1024).toFixed(1) + " kB"; return n + " B"; }

const BIZ_TYPES = ["Dental", "HVAC", "Law", "Salon", "Auto", "Restaurant", "Med spa", "Chiropractor", "Plumbing", "Veterinary", "Real estate", "Other"];
const TONES = ["friendly", "professional", "warm", "concise"];
const AGENT_DEFAULT = { Dental: "Smile Assistant", HVAC: "Dispatch", Law: "Reception", Salon: "Front Desk", Auto: "Service Desk", Restaurant: "Host", Other: "Front Desk" };
const TYPE_HINTS = {
  Dental: { services: "Cleanings, fillings, crowns, whitening…", q: ["What are your hours?", "Do you take my insurance?", "Can I book a cleaning?"] },
  HVAC: { services: "AC repair, furnace install, maintenance plans…", q: ["Do you do emergency calls?", "How much is a tune-up?", "Can someone come today?"] },
  Law: { services: "Consultations, estate planning, filings…", q: ["Do you offer free consults?", "What are your hours?", "Can I speak to an attorney?"] },
  Salon: { services: "Cuts, color, blowouts, treatments…", q: ["Do you take walk-ins?", "How much is a cut & color?", "Can I book Saturday?"] },
  Auto: { services: "Oil changes, brakes, diagnostics, tires…", q: ["What are your hours?", "How much for brakes?", "Can I get a quote?"] },
  Restaurant: { services: "Lunch, dinner, catering, private events…", q: ["Are you open tonight?", "Can I book a table for 6?", "Do you do catering?"] },
  "Med spa": { services: "Botox, fillers, facials, laser treatments…", q: ["How much is Botox?", "Do I need a consult first?", "Can I book a facial?"] },
  Chiropractor: { services: "Adjustments, decompression, sports injury care…", q: ["Do you take walk-ins?", "Do you take my insurance?", "Can I book an adjustment?"] },
  Plumbing: { services: "Drain cleaning, water heaters, leak repair…", q: ["Do you do emergency calls?", "How much to unclog a drain?", "Can someone come today?"] },
  Veterinary: { services: "Wellness exams, vaccines, dental, surgery…", q: ["What are your hours?", "Can I book a checkup?", "Do you see emergencies?"] },
  "Real estate": { services: "Buying, selling, rentals, home valuations…", q: ["Can I schedule a showing?", "What's my home worth?", "Do you handle rentals?"] },
  Other: { services: "List exactly what you offer…", q: ["What are your hours?", "What do you offer?", "Can I book?"] },
};

// ── grounded responder (the guardrail, demonstrated) ─────
function agentName(c) { return (c.agent || "").trim() || AGENT_DEFAULT[c.type] || "your front desk"; }
function bizName(c) { return (c.name || "").trim() || "your business"; }
function greeting(c) {
  const b = bizName(c), a = agentName(c);
  const custom = (c.greeting || "").trim();
  if (custom) return custom.replace(/\{business\}/gi, b).replace(/\{agent\}/gi, a);
  switch (c.tone) {
    case "professional": return `${b}, this is ${a} speaking. How may I direct your call?`;
    case "warm": return `Hi there — thanks so much for calling ${b}. This is ${a}. What can I do for you?`;
    case "concise": return `${b}, ${a} here. How can I help?`;
    default: return `Thanks for calling ${b}! This is ${a}. How can I help you today?`;
  }
}
function escalate(c, thing) {
  return { text: `I don't have ${thing} in front of me, and I won't guess. Let me have a team member follow up${c.phone ? ` at ${c.phone}` : ""} so you get it exactly right.`, escalated: true };
}
function respond(qRaw, c) {
  const q = qRaw.toLowerCase();
  if (/^(hi|hello|hey|yo|good (morning|afternoon|evening))\b/.test(q)) return { text: `Hi! This is ${agentName(c)} at ${bizName(c)}. What can I help with?` };
  if (/thank|thanks|appreciate/.test(q)) return { text: `Of course — anything else I can help with?` };
  if (/hour|open|close|when.*(open|close)|today|tonight|right now/.test(q)) return c.hours ? { text: `We're open ${c.hours}.` } : escalate(c, "our exact hours");
  if (/price|cost|how much|rate|fee|charge|quote|\$/.test(q)) return c.pricing ? { text: `Here's what I can quote: ${c.pricing}. Anything outside that, I'll have the team confirm.` } : escalate(c, "pricing");
  if (/book|appointment|schedule|reserve|table|walk.?in|availability/.test(q)) {
    const notify = (c.leadNotify || c.phone || "").trim();
    const bk = (c.booking || "").trim();
    if (bk) return { text: `Here's how we book: ${bk} What day and time work for you?${notify ? ` I'll send the details to ${notify}.` : ""}` };
    return { text: `Happy to set that up. What day and time work for you? I'll confirm with ${bizName(c)}${notify ? ` and send the details to ${notify}` : ""}.` };
  }
  if (/where|address|located|location|direction|park|find you/.test(q)) return c.city ? { text: `We're in ${c.city}.` } : escalate(c, "our address");
  if (/service|offer|do you (do|have|sell)|menu|provide/.test(q)) return c.services ? { text: `We offer ${c.services}.` } : escalate(c, "our full list of services");
  if (/human|person|manager|owner|representative|talk to|speak (to|with)|someone/.test(q)) return { text: `Absolutely — I'll connect you with the team${c.phone ? ` at ${c.phone}` : ""} right now.`, escalated: true };
  if (/insurance|accept|cover/.test(q)) return escalate(c, "what we accept");
  return { text: `That's outside what ${bizName(c)} has given me, so I won't make something up. I'll pass this to a person${c.phone ? ` at ${c.phone}` : ""} so it's answered right.`, escalated: true };
}

// ── checkout handoff + lead capture ──────────────────────
// Persist the entered config so /purchase can prefill from it. "eib-configure"
// is a NEW key (full draft snapshot); "eib-business-name" is the existing
// homepage key and keeps its existing format — the plain name string.
function persistConfig(c, sources) {
  try {
    localStorage.setItem("eib-configure", JSON.stringify({
      c,
      sources: sources.map((s) => ({ name: s.name, type: s.type })),
      saved_at: new Date().toISOString(),
    }));
    if (c.name && c.name.trim()) localStorage.setItem("eib-business-name", c.name);
  } catch (e) { /* storage disabled/full — never block checkout */ }
}
// Best-effort lead capture on "Start your 2 weeks free" — fire-and-forget,
// never awaited, never blocks or breaks the UI.
function captureLead(c) {
  try {
    fetch("/api/lead", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ business: c.name, type: c.type, phone: c.phone, leadNotify: c.leadNotify, source: "configure-start-free" }),
    }).catch(() => {});
  } catch (e) { /* best-effort only */ }
}

// ── dark header bar ──────────────────────────────────────
function Header() {
  return (
    <div style={{ background: "#15121d", borderBottom: "1px solid rgba(243,240,250,.10)" }}>
      <div style={{ maxWidth: 1240, margin: "0 auto", height: 56, padding: "0 28px", display: "flex", alignItems: "center", gap: 12 }}>
        <span style={{ width: 8, height: 8, borderRadius: "50%", background: "#2dd881", boxShadow: "0 0 9px #2dd881", flex: "none" }} />
        <a href={(window.__NAV && window.__NAV.home) || "../"} style={{ display: "inline-flex", alignItems: "center", gap: 10, textDecoration: "none" }}>
          <img src={(window.__resources && window.__resources.epochLogo) || "../assets/vendor/epochcore-logo.png"} alt="" style={{ width: 22, height: 22 }} />
          <span style={{ fontFamily: MONO, fontSize: 13, fontWeight: 600, letterSpacing: "1.5px", color: "#f3f0fa" }}>EPOCH-IN-A-BOX</span>
        </a>
        <span style={{ fontFamily: MONO, fontSize: 11, letterSpacing: "1.6px", color: "rgba(243,240,250,.5)", textTransform: "uppercase" }}>· Configure your front desk</span>
        <div style={{ flex: 1 }} />
        <span style={{ fontFamily: MONO, fontSize: 10, letterSpacing: "1px", color: "rgba(243,240,250,.4)", textTransform: "uppercase" }}>$99 install · no hallucinations</span>
      </div>
    </div>
  );
}

// ── form atoms ───────────────────────────────────────────
const fieldStyle = { width: "100%", padding: "13px 15px", fontFamily: SERIF, fontSize: 16, color: "var(--ink)", background: "var(--field)", border: RULE2, borderRadius: FR, outline: "none" };
function Field({ label, req, hint, error, children }) {
  const id = useId(); // ties the label to its child control (a11y)
  const child = React.isValidElement(children) ? React.cloneElement(children, { id }) : children;
  return (
    <div style={{ marginBottom: 22 }}>
      <label htmlFor={id} style={{ display: "block", fontFamily: MONO, fontSize: 11, letterSpacing: "1.2px", textTransform: "uppercase", color: "var(--mute)", marginBottom: 9 }}>
        {label}{req && <span style={{ color: "var(--accent)" }}> *</span>}
      </label>
      {child}
      {error ? <div style={{ marginTop: 7, fontFamily: MONO, fontSize: 11, letterSpacing: ".2px", color: "var(--warn)" }}>{error}</div>
        : hint ? <div style={{ marginTop: 7, fontFamily: MONO, fontSize: 11, letterSpacing: ".2px", color: "var(--mute)" }}>{hint}</div> : null}
    </div>
  );
}
function Text({ id, value, onChange, placeholder, area }) {
  const [foc, setFoc] = useState(false);
  const st = { ...fieldStyle, borderColor: foc ? "var(--accent)" : "var(--line2)", ...(area ? { minHeight: 92, resize: "vertical", lineHeight: 1.55 } : {}) };
  const props = { id, value, placeholder, style: st, onChange: (e) => onChange(e.target.value), onFocus: () => setFoc(true), onBlur: () => setFoc(false) };
  return area ? <textarea {...props} /> : <input {...props} />;
}
function SelectField({ id, value, onChange }) {
  const [foc, setFoc] = useState(false);
  return (
    <div style={{ position: "relative" }}>
      <select id={id} value={value} onChange={(e) => onChange(e.target.value)} onFocus={() => setFoc(true)} onBlur={() => setFoc(false)}
        style={{ ...fieldStyle, appearance: "none", WebkitAppearance: "none", cursor: "pointer", borderColor: foc ? "var(--accent)" : "var(--line2)", color: value ? "var(--ink)" : "var(--faint)", paddingRight: 40 }}>
        <option value="">— Choose your business —</option>
        {BIZ_TYPES.map((t) => <option key={t} value={t} style={{ color: "var(--ink)" }}>{t}</option>)}
      </select>
      <span style={{ position: "absolute", right: 15, top: "50%", transform: "translateY(-50%)", pointerEvents: "none", color: "var(--mute)" }}>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="m6 9 6 6 6-6" /></svg>
      </span>
    </div>
  );
}
function Segmented({ id, value, options, onChange }) {
  return (
    <div id={id} role="group" style={{ display: "inline-flex", border: RULE2, borderRadius: FR, overflow: "hidden", flexWrap: "wrap" }}>
      {options.map((o, i) => (
        <button key={o} onClick={() => onChange(o)} style={{
          fontFamily: MONO, fontSize: 11, letterSpacing: ".5px", textTransform: "uppercase", padding: "10px 16px", border: "none", borderLeft: i ? RULE2 : "none",
          cursor: "pointer", background: value === o ? "var(--accent)" : "var(--field)", color: value === o ? "#fff" : "var(--dim)",
        }}>{o}</button>
      ))}
    </div>
  );
}

// ── sources (compact Knowledge Base) ─────────────────────
function Sources({ sources, setSources }) {
  const [adding, setAdding] = useState(null); // 'url' | 'text'
  const [v1, setV1] = useState("");
  const fileRef = useRef(null);
  function add(s) { setSources((p) => [...p, { id: uid(), ...s }]); }
  function commitUrl() { const u = v1.trim(); if (!u) return; add({ name: u.replace(/^https?:\/\//, "").replace(/\/$/, ""), type: "URL", size: 4000 + Math.floor(Math.random() * 9000) }); setV1(""); setAdding(null); }
  function commitText() { const t = v1.trim(); if (!t) return; add({ name: t, type: "Text", size: 1200 + Math.floor(Math.random() * 4000) }); setV1(""); setAdding(null); }
  const total = sources.reduce((a, s) => a + s.size, 0);
  const chip = { fontFamily: MONO, fontSize: 11, letterSpacing: ".5px", color: "var(--dim)", background: "var(--field)", border: RULE2, borderRadius: 999, padding: "7px 13px", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 7 };
  return (
    <div style={{ marginTop: 4 }}>
      <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 12, marginBottom: 12 }}>
        <label style={{ fontFamily: MONO, fontSize: 11, letterSpacing: "1.2px", textTransform: "uppercase", color: "var(--mute)" }}>Add deeper sources <span style={{ color: "var(--faint)" }}>· optional</span></label>
        <a href={(window.__NAV && window.__NAV.kb) || "../knowledge-base/"} style={{ fontFamily: MONO, fontSize: 10.5, letterSpacing: ".4px", color: "var(--accent)", textDecoration: "none" }}>Open Knowledge Base →</a>
      </div>
      <div style={{ display: "flex", gap: 9, flexWrap: "wrap" }}>
        <button className="cfg-chip" style={chip} onClick={() => { setAdding(adding === "url" ? null : "url"); setV1(""); }}>＋ Add URL</button>
        <button className="cfg-chip" style={chip} onClick={() => fileRef.current && fileRef.current.click()}>＋ Add Files</button>
        <button className="cfg-chip" style={chip} onClick={() => { setAdding(adding === "text" ? null : "text"); setV1(""); }}>＋ Create Text</button>
        <input ref={fileRef} type="file" multiple style={{ display: "none" }} onChange={(e) => { const fs = [...(e.target.files || [])]; e.target.value = ""; fs.forEach((f) => add({ name: f.name, type: "File", size: f.size })); }} />
      </div>
      {adding && (
        <div style={{ marginTop: 11, display: "flex", gap: 9 }}>
          <input autoFocus value={v1} onChange={(e) => setV1(e.target.value)} onKeyDown={(e) => e.key === "Enter" && (adding === "url" ? commitUrl() : commitText())}
            placeholder={adding === "url" ? "dear-dads.com/menu" : "Paste or write a source the agent may use…"}
            style={{ ...fieldStyle, borderColor: "var(--accent)", flex: 1, padding: "10px 13px", fontSize: 14 }} />
          <Button variant="primary" size="sm" icon={null} onClick={adding === "url" ? commitUrl : commitText}>Add</Button>
        </div>
      )}
      {sources.length > 0 && (
        <div style={{ marginTop: 13, border: RULE, borderRadius: RADIUS, overflow: "hidden", background: "var(--field)" }}>
          {sources.map((s, i) => (
            <div key={s.id} className="cfg-src" style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", borderBottom: i === sources.length - 1 ? "none" : RULE }}>
              <span style={{ fontFamily: MONO, fontSize: 8.5, letterSpacing: ".5px", textTransform: "uppercase", color: "var(--accent)", border: "1px solid var(--accent-line)", borderRadius: 999, padding: "2px 7px", flex: "none" }}>{s.type}</span>
              <span style={{ flex: 1, minWidth: 0, fontFamily: SERIF, fontSize: 14, color: "var(--ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{s.name}</span>
              <span style={{ fontFamily: MONO, fontSize: 10.5, color: "var(--mute)", flex: "none" }}>{fmtBytes(s.size)}</span>
              <button className="cfg-src-x" onClick={() => setSources((p) => p.filter((x) => x.id !== s.id))} style={{ opacity: 0, transition: "opacity .15s", border: "none", background: "none", color: "var(--mute)", cursor: "pointer", flex: "none", fontFamily: MONO, fontSize: 14, lineHeight: 1 }}>✕</button>
            </div>
          ))}
          <div style={{ padding: "8px 12px", borderTop: RULE, background: "var(--surface)", fontFamily: MONO, fontSize: 10, letterSpacing: ".4px", textTransform: "uppercase", color: "var(--mute)", display: "flex", justifyContent: "space-between" }}>
            <span>{sources.length} source{sources.length === 1 ? "" : "s"} · chunked & embedded</span><span>{fmtBytes(total)}</span>
          </div>
        </div>
      )}
    </div>
  );
}

// ── technical config (collapsible) ───────────────────────
function TechConfig({ c, sources }) {
  const [open, setOpen] = useState(false);
  const cfg = {
    agent: agentName(c), business: bizName(c), type: c.type || null, tone: c.tone,
    grounding: { greeting: greeting(c), hours: c.hours || null, services: c.services ? c.services.split(/,\s*/) : [], pricing: c.pricing || null, city: c.city || null, booking: c.booking || null, lead_notify: (c.leadNotify || c.phone) || null, escalate_to: c.phone || null, sources: sources.map((s) => s.name) },
    policy: "discuss_only_listed · escalate_unknown · no_hallucination",
    seal: "Ed25519 + ML-DSA-87",
  };
  return (
    <Card style={{ background: "var(--field)", padding: 0, overflow: "hidden" }}>
      <button onClick={() => setOpen(!open)} style={{ width: "100%", display: "flex", alignItems: "center", gap: 10, padding: "13px 16px", border: "none", background: "transparent", cursor: "pointer", fontFamily: MONO, fontSize: 11, letterSpacing: ".6px", textTransform: "uppercase", color: "var(--dim)" }}>
        <span style={{ transform: open ? "rotate(90deg)" : "none", transition: "transform .18s", display: "inline-flex", color: "var(--accent)" }}>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="m9 6 6 6-6 6" /></svg>
        </span>
        Show technical config
        <span style={{ flex: 1 }} />
        <span style={{ fontFamily: MONO, fontSize: 9.5, color: "var(--ok)", letterSpacing: ".5px" }}>● sealed · wxo/v3.1</span>
      </button>
      {open && (
        <pre style={{ margin: 0, padding: "12px 16px", borderTop: RULE, maxHeight: 240, overflow: "auto", fontFamily: MONO, fontSize: 11, lineHeight: 1.6, color: "var(--ink)", background: "var(--surface)", whiteSpace: "pre-wrap", wordBreak: "break-word" }}>
          {"agent.config.wxo\n" + JSON.stringify(cfg, null, 2)}
        </pre>
      )}
    </Card>
  );
}

// ── live preview chat ────────────────────────────────────
function PreviewChat({ c }) {
  const [msgs, setMsgs] = useState([{ who: "a", text: greeting(c) }]);
  const [draft, setDraft] = useState("");
  const [speaking, setSpeaking] = useState(false);
  const lastGreeting = useRef(greeting(c));
  const scroller = useRef(null);
  const initialCount = useRef(msgs.length);
  const audioRef = useRef(null);
  // P4b — hear the greeting through the same server-side TTS proxy the
  // homepage demo uses (allowlisted voice, key stays server-side).
  function hearIt() {
    if (speaking) return;
    setSpeaking(true);
    fetch("/api/tts", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ voiceId: "Aq4NkWZkTCTjCIjDlhdv", text: greeting(c) }),
    })
      .then((r) => (r.ok ? r.blob() : Promise.reject(new Error("tts " + r.status))))
      .then((b) => {
        const url = URL.createObjectURL(b);
        const a = new Audio(url);
        audioRef.current = a;
        a.onended = () => { setSpeaking(false); URL.revokeObjectURL(url); };
        a.onerror = () => { setSpeaking(false); URL.revokeObjectURL(url); };
        return a.play();
      })
      .catch(() => setSpeaking(false));
  }
  // keep the opening line in sync as the business/agent/tone changes, until the user starts chatting
  useEffect(() => {
    const g = greeting(c);
    setMsgs((m) => (m.length === 1 && m[0].who === "a" ? [{ who: "a", text: g }] : m));
    lastGreeting.current = g;
  }, [c.name, c.agent, c.tone, c.type, c.greeting]);
  useEffect(() => { if (scroller.current) scroller.current.scrollTop = scroller.current.scrollHeight; }, [msgs]);
  function send(text) {
    const q = (text == null ? draft : text).trim(); if (!q) return;
    const a = respond(q, c);
    setMsgs((m) => [...m, { who: "u", text: q }, { who: "a", text: a.text, escalated: a.escalated }]);
    setDraft("");
  }
  const suggestions = (TYPE_HINTS[c.type] || TYPE_HINTS.Other).q;
  return (
    <Card style={{ background: "var(--field)", padding: 0, overflow: "hidden", boxShadow: "var(--shadow-lg, 0 14px 36px rgba(20,14,8,.12))" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 11, padding: "13px 16px", borderBottom: RULE }}>
        <span style={{ width: 34, height: 34, borderRadius: RADIUS, background: "var(--accent)", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center", fontFamily: MONO, fontSize: 12, fontWeight: 700, flex: "none" }}>
          {(agentName(c).slice(0, 2) || "FR").toUpperCase()}
        </span>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ fontFamily: SERIF, fontWeight: 700, fontSize: 15, color: "var(--ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{agentName(c)}</div>
          <div style={{ fontFamily: MONO, fontSize: 9.5, letterSpacing: ".6px", textTransform: "uppercase", color: "var(--ok)", display: "flex", alignItems: "center", gap: 6, marginTop: 2 }}>
            <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--ok)" }} />Live preview · grounded
          </div>
        </div>
        <button onClick={hearIt} aria-label="Hear the greeting" title="Hear the greeting"
          style={{ fontFamily: MONO, fontSize: 10, letterSpacing: ".6px", textTransform: "uppercase", color: speaking ? "var(--mute)" : "var(--accent)", background: "var(--accent-soft)", border: "1px solid var(--accent-line)", borderRadius: 999, padding: "6px 12px", cursor: speaking ? "default" : "pointer", flex: "none", display: "flex", alignItems: "center", gap: 6 }}>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" /><path d="M15.5 8.5a5 5 0 0 1 0 7" /></svg>
          {speaking ? "Playing…" : "Hear it"}
        </button>
      </div>
      <div ref={scroller} style={{ padding: "14px 16px", display: "flex", flexDirection: "column", gap: 10, maxHeight: 252, overflowY: "auto" }}>
        {msgs.map((m, i) => (
          <div key={i} style={{ alignSelf: m.who === "u" ? "flex-end" : "flex-start", maxWidth: "86%", animation: i >= initialCount.current ? "cfgmsg .2s ease both" : "none" }}>
            <div style={{
              fontFamily: SERIF, fontSize: 14, lineHeight: 1.5, padding: "9px 13px", borderRadius: 14,
              background: m.who === "u" ? "var(--accent)" : m.escalated ? "color-mix(in srgb, var(--warn) 12%, var(--surface))" : "var(--surface)",
              color: m.who === "u" ? "#fff" : "var(--ink)",
              border: m.who === "u" ? "none" : "1px solid " + (m.escalated ? "color-mix(in srgb, var(--warn) 40%, var(--line))" : "var(--line)"),
              borderBottomRightRadius: m.who === "u" ? 4 : 14, borderBottomLeftRadius: m.who === "u" ? 14 : 4,
            }}>{m.text}</div>
            {m.escalated && <div style={{ marginTop: 4, fontFamily: MONO, fontSize: 9, letterSpacing: ".5px", textTransform: "uppercase", color: "var(--warn)", display: "flex", alignItems: "center", gap: 5 }}>⛨ escalated · not guessed</div>}
          </div>
        ))}
      </div>
      <div style={{ padding: "0 16px 12px", display: "flex", gap: 7, flexWrap: "wrap" }}>
        {suggestions.map((s) => (
          <button key={s} onClick={() => send(s)} style={{ fontFamily: SERIF, fontSize: 12.5, color: "var(--accent)", background: "var(--accent-soft)", border: "1px solid var(--accent-line)", borderRadius: 999, padding: "5px 11px", cursor: "pointer" }}>{s}</button>
        ))}
      </div>
      <div style={{ display: "flex", gap: 8, padding: "12px 14px", borderTop: RULE, background: "var(--surface)" }}>
        <input value={draft} onChange={(e) => setDraft(e.target.value)} onKeyDown={(e) => e.key === "Enter" && send()} placeholder="Ask your agent anything…"
          style={{ flex: 1, padding: "10px 14px", fontFamily: SERIF, fontSize: 14, color: "var(--ink)", background: "var(--field)", border: RULE2, borderRadius: 999, outline: "none" }} />
        <button onClick={() => send()} aria-label="Send" style={{ width: 40, height: 40, borderRadius: "50%", border: "none", background: "var(--ink)", color: "var(--on-ink)", cursor: "pointer", flex: "none", display: "flex", alignItems: "center", justifyContent: "center" }}>
          <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6" /></svg>
        </button>
      </div>
    </Card>
  );
}

// ── ROOT ─────────────────────────────────────────────────
function ConfigureApp() {
  const [tw, setTweak] = useTweaks(CFG_TWEAK_DEFAULTS);
  useEffect(() => {
    document.body.classList.toggle("dark", tw.face === "dark");
    const r = document.documentElement.style;
    r.setProperty("--accent", tw.accent);
    r.setProperty("--accent-line", "color-mix(in srgb, " + tw.accent + " 38%, transparent)");
    r.setProperty("--accent-soft", "color-mix(in srgb, " + tw.accent + " 11%, transparent)");
  }, [tw.face, tw.accent]);

  const [c, setC] = useState({ type: "", name: "", agent: "", city: "", phone: "", hours: "", services: "", pricing: "", tone: "friendly", greeting: "", booking: "", leadNotify: "" });
  const set = (k, v) => setC((p) => ({ ...p, [k]: v }));
  const [sources, setSources] = useState([]);
  const [touched, setTouched] = useState(false);
  const [started, setStarted] = useState(false);
  const hints = TYPE_HINTS[c.type] || TYPE_HINTS.Other;
  const factCount = ["hours", "services", "pricing", "city", "phone", "booking", "leadNotify", "greeting"].filter((k) => c[k].trim()).length + sources.length;

  return (
    <div style={{ minHeight: "100vh", display: "flex", flexDirection: "column", fontFamily: SERIF }}>
      <TweaksPanel>
        <TweakSection label="Face" />
        <TweakRadio label="Theme" value={tw.face} options={["light", "dark"]} onChange={(v) => setTweak("face", v)} />
        <TweakSection label="Accent" />
        <TweakColor label="Accent" value={tw.accent} options={["#6a3df0", "#2a6fdb", "#1f8a5b", "#c2691c"]} onChange={(v) => setTweak("accent", v)} />
        <TweakSection label="Form" />
        <TweakRadio label="Deeper sources" value={tw.showSources} options={["on", "off"]} onChange={(v) => setTweak("showSources", v)} />
      </TweaksPanel>

      <Header />

      <div className="cfg-grid" style={{ flex: 1, width: "100%", maxWidth: 1240, margin: "0 auto", padding: "44px 28px 64px", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 56, alignItems: "start" }}>
        {/* LEFT — form */}
        <div>
          <FrameLabel framed>Step 1 · tell us about you</FrameLabel>
          <h1 style={{ margin: "18px 0 0", fontFamily: SERIF, fontWeight: 800, fontSize: "clamp(30px,3.6vw,46px)", lineHeight: 1.05, letterSpacing: "-1px", color: "var(--ink)" }}>Tell us about your business</h1>
          <p style={{ margin: "12px 0 28px", maxWidth: 460, fontFamily: SERIF, fontSize: 16, lineHeight: 1.55, color: "var(--dim)" }}>
            Fill this in once. Your front desk only ever talks about what you put here — <em style={{ color: "var(--accent)", fontStyle: "italic" }}>nothing made up</em>.
          </p>

          <Field label="What kind of business?"><SelectField value={c.type} onChange={(v) => set("type", v)} /></Field>
          <Field label="Business name" req error={touched && !c.name.trim() ? "Add your business name to continue." : null}>
            <Text value={c.name} onChange={(v) => { set("name", v); }} placeholder="Lakeview Dental" />
          </Field>
          <Field label="What should your agent be called?" hint="Leave blank and we'll name it for you.">
            <Text value={c.agent} onChange={(v) => set("agent", v)} placeholder={AGENT_DEFAULT[c.type] || "Smile Assistant"} />
          </Field>
          <Field label="City & state"><Text value={c.city} onChange={(v) => set("city", v)} placeholder="Austin, TX" /></Field>
          <section id="escalation">
            <Field label="Your phone number" hint="Shown when your agent passes someone to a human (escalation line).">
              <Text value={c.phone} onChange={(v) => set("phone", v)} placeholder="(512) 555-0192" />
            </Field>
          </section>
          <section id="lead-capture">
            <Field label="Text or email new leads to" hint="Where the agent sends a summary when it captures a booking or lead. Defaults to your phone.">
              <Text value={c.leadNotify} onChange={(v) => set("leadNotify", v)} placeholder={c.phone || "you@business.com or (512) 555-0192"} />
            </Field>
          </section>
          <section id="hours">
            <Field label="When are you open?"><Text value={c.hours} onChange={(v) => set("hours", v)} placeholder="Mon–Fri 9am–5pm · Sat 10am–2pm" /></Field>
          </section>
          <section id="knowledge">
            <Field label="What services do you offer?" hint="Only listed services will be discussed — this is your agent's knowledge base.">
              <Text area value={c.services} onChange={(v) => set("services", v)} placeholder={hints.services} />
            </Field>
          </section>
          <Field label="Pricing" hint="Only quoted prices get discussed — everything else escalates.">
            <Text area value={c.pricing} onChange={(v) => set("pricing", v)} placeholder="Cleaning $129 · whitening $299 · consult free" />
          </Field>
          <section id="booking">
            <Field label="How are appointments booked?" hint="How your agent should handle scheduling — a link, your hours, or your process. Leave blank to just collect day & time.">
              <Text area value={c.booking} onChange={(v) => set("booking", v)} placeholder="We book Mon–Fri; I'll take your name & number and the office confirms same day. — or — book at calendly.com/lakeview" />
            </Field>
          </section>
          <section id="greeting">
            <Field label="How should your agent sound?"><Segmented value={c.tone} options={TONES} onChange={(v) => set("tone", v)} /></Field>
            <Field label="Greeting / opening line" hint="Optional — the first line the agent says. Use {business} and {agent} as placeholders; leave blank for the tone default.">
              <Text area value={c.greeting} onChange={(v) => set("greeting", v)} placeholder={greeting({ ...c, greeting: "" })} />
            </Field>
          </section>

          {tw.showSources === "on" && <Sources sources={sources} setSources={setSources} />}

          <div style={{ marginTop: 30, display: "flex", alignItems: "center", gap: 14, flexWrap: "wrap" }}>
            <Button variant="primary" size="lg" onClick={() => { if (!c.name.trim()) { setTouched(true); return; } if (!started) captureLead(c); setStarted(true); }}>Start your 2 weeks free</Button>
            <span style={{ fontFamily: MONO, fontSize: 10.5, letterSpacing: ".4px", textTransform: "uppercase", color: "var(--mute)" }}>No card · $99 install · cancel anytime</span>
          </div>
          {started && (
            <div style={{ marginTop: 16, padding: "15px 16px", borderRadius: RADIUS, border: RULE, borderLeft: "3px solid var(--ok)", background: "color-mix(in srgb, var(--ok) 8%, transparent)", fontFamily: SERIF, fontSize: 14, color: "var(--ink)" }}>
              <div style={{ marginBottom: 12 }}><b>{agentName(c)}</b> is configured for <b>{bizName(c)}</b>. One step left — start your free trial and your front desk goes live.</div>
              <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
                <Button variant="primary" size="md" href="/purchase" onClick={() => persistConfig(c, sources)}>Make it live →</Button>
                <span style={{ fontFamily: MONO, fontSize: 10, letterSpacing: ".4px", textTransform: "uppercase", color: "var(--mute)" }}>2 weeks free · $249/mo or $999/yr after</span>
              </div>
            </div>
          )}
        </div>

        {/* RIGHT — live preview */}
        <div className="cfg-preview" style={{ position: "sticky", top: 24, display: "flex", flexDirection: "column", gap: 16 }}>
          <TechConfig c={c} sources={sources} />

          <Card style={{ background: "var(--field)" }}>
            <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
                <span style={{ width: 7, height: 7, borderRadius: "50%", background: "var(--ok)", boxShadow: "0 0 8px var(--ok)" }} />
                <span style={{ fontFamily: SERIF, fontSize: 15, color: "var(--ink)" }}>Grounded — only discusses what you enter <span style={{ fontFamily: MONO, fontSize: 11, color: "var(--mute)" }}>({factCount} fact{factCount === 1 ? "" : "s"})</span></span>
              </div>
              <CheckItem>No hallucinations</CheckItem>
              <div style={{ display: "flex", alignItems: "center", gap: 9, fontFamily: SERIF, fontSize: 15, color: "var(--ink)" }}>
                <span style={{ color: "var(--accent)", display: "inline-flex" }}><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3l7 3v6c0 4-3 7-7 9-4-2-7-5-7-9V6z" /></svg></span>
                Human escalation on
              </div>
              <CheckItem>Verifiable · cancel anytime</CheckItem>
            </div>
          </Card>

          <div>
            <h2 style={{ margin: "4px 0 12px", fontFamily: SERIF, fontWeight: 800, fontSize: 24, letterSpacing: "-0.5px", color: "var(--ink)" }}>Here's what your front desk will say</h2>
            <PreviewChat c={c} />
          </div>

          <Card style={{ background: "var(--surface)" }}>
            <div style={{ fontFamily: MONO, fontSize: 10, letterSpacing: "1px", textTransform: "uppercase", color: "var(--mute)", marginBottom: 12 }}>It can</div>
            <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
              <CheckItem>Answer questions about your hours, services & location</CheckItem>
              <CheckItem>Book and confirm appointments</CheckItem>
              <CheckItem>Capture leads and text you a summary</CheckItem>
              <CheckItem>Hand off to a human when it matters</CheckItem>
            </div>
            <div style={{ marginTop: 16, paddingTop: 14, borderTop: RULE, fontFamily: SERIF, fontSize: 14.5, color: "var(--dim)" }}>
              <b style={{ color: "var(--ink)", fontWeight: 600 }}>Simple pricing:</b> 2 weeks free, then <b style={{ color: "var(--ink)", fontWeight: 600 }}>$99</b> install + <b style={{ color: "var(--ink)", fontWeight: 600 }}>$249</b>/mo · unlimited conversations.
            </div>
          </Card>
        </div>
      </div>
    </div>
  );
}

  var rootEl = document.getElementById("root");
  if (!window.__cfgRoot) window.__cfgRoot = ReactDOM.createRoot(rootEl);
  window.__cfgRoot.render(<ConfigureApp />);
};
(function () {
  var NS = "EpochCoreDesignSystem_1d529c";
  if (!window.__SUITE && window[NS] && window[NS].Button) { try { window.__mountConfigure(window[NS]); } catch (e) {} }
})();
