/* ============================================================
   O4 — Onboarding wizard
   connect → brand extraction (magic moment) → configure → import → ready
   ============================================================ */
const ONB_DEFAULTS = /*EDITMODE-BEGIN*/{
  "mood": "warm",
  "site": "riverapark.law",
  "startStep": 1
}/*EDITMODE-END*/;

/* ---------- WCAG contrast (the safety contract) ---------- */
function hexToRgb(h) { h = h.replace('#', ''); if (h.length === 3) h = h.split('').map((c) => c + c).join(''); const n = parseInt(h, 16); return [(n >> 16) & 255, (n >> 8) & 255, n & 255]; }
function relLum(rgb) { const f = (c) => { c /= 255; return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); }; return 0.2126 * f(rgb[0]) + 0.7152 * f(rgb[1]) + 0.0722 * f(rgb[2]); }
function contrast(a, b) { const la = relLum(hexToRgb(a)), lb = relLum(hexToRgb(b)); const hi = Math.max(la, lb), lo = Math.min(la, lb); return (hi + 0.05) / (lo + 0.05); }
function darken(hex, amt) { let [r, g, b] = hexToRgb(hex); const d = (x) => Math.max(0, Math.round(x * (1 - amt))); return '#' + [d(r), d(g), d(b)].map((x) => x.toString(16).padStart(2, '0')).join(''); }
function ensureAA(primary, on, target = 4.5) {
  const before = contrast(primary, on);
  if (before >= target) return { color: primary, adjusted: false, before, after: before };
  let cur = primary;
  for (let i = 0; i < 24 && contrast(cur, on) < target; i++) cur = darken(cur, 0.05);
  return { color: cur, adjusted: true, before, after: contrast(cur, on) };
}
const r1 = (n) => n.toFixed(1);

/* ---------- extraction presets (two contrasting firms) ---------- */
const SITES = {
  'riverapark.law': {
    name: 'Rivera Park IP', logo: 'R', tier: 'Growth · co-brand',
    on: '#FFFFFF', ink: '#2A1C12', inkMuted: '#6B5848', surface: '#FFFDF8', paper: '#FBF4E7', border: '#EAD9BF',
    display: 'Instrument Serif', body: 'Hanken Grotesk', radius: 10,
    swatches: ['#D2641C', '#B8430E', '#8F340B'],
    traits: ['Warm', 'Established', 'Reassuring'],
    sample: '“For three generations, we’ve protected what founders build.”',
  },
  'northstarip.com': {
    name: 'Northstar IP', logo: 'N', tier: 'Enterprise · white-label',
    on: '#FFFFFF', ink: '#0F1B2D', inkMuted: '#46546B', surface: '#FFFFFF', paper: '#EEF1F6', border: '#D8DEE8',
    display: 'Space Grotesk', body: 'Hanken Grotesk', radius: 16,
    swatches: ['#2F6BF2', '#2563EB', '#1D4FC4'],
    traits: ['Modern', 'Precise', 'Confident'],
    sample: '“Move fast. We’ll make sure your IP keeps up.”',
  },
};

const STEPS = ['Connect', 'Brand', 'Configure', 'Import', 'Ready'];

/* ---------- audit mini-summary for step 1 ---------- */
const MINI = [
  { sev: 'high', dot: 'var(--danger)', t: '118 leads untouched > 7 days', impact: '~$94k at risk' },
  { sev: 'med', dot: 'var(--warning)', t: '47 freeform tags to normalize', impact: '→ 5 clean dimensions' },
  { sev: 'high', dot: 'var(--danger)', t: '19h average first response', impact: '→ target < 1h' },
];

/* ============================================================ */
function Stepper({ step }) {
  return (
    <div className="stepper">
      {STEPS.map((s, i) => (
        <React.Fragment key={s}>
          <div className={'stp' + (i < step ? ' done' : i === step ? ' active' : '')}>
            <span className="dot">{i < step ? Ico.check : i + 1}</span>
            <span className="lb">{s}</span>
          </div>
          {i < STEPS.length - 1 && <span className={'stp-line' + (i < step ? ' done' : '')}></span>}
        </React.Fragment>
      ))}
    </div>
  );
}

/* ---------- live themed preview ---------- */
function LivePreview({ site, primaryAA, radius, display }) {
  const vars = {
    '--pf-primary': primaryAA, '--pf-on': site.on, '--pf-ink': site.ink, '--pf-ink-muted': site.inkMuted,
    '--pf-surface': site.surface, '--pf-border': site.border, '--pf-radius': radius + 'px',
    '--pf-display': `'${display}', Georgia, serif`, '--pf-body': `'${site.body}', system-ui, sans-serif`,
    '--pv-score': 84, background: site.paper,
  };
  return (
    <div className="prev-frame">
      <div className="prev-label"><span className="dotlive"></span>Live preview · what {site.name}’s clients will see</div>
      <div className="prev-browser">
        <div className="prev-chrome"><i></i><i></i><i></i><span className="addr">{Object.keys(SITES).find((k) => SITES[k] === site)}/start</span></div>
        <div className="prev-surface" style={vars}>
          <div className="pv-eyebrow">{site.name}</div>
          <div className="pv-h">You’re closer to protected than you think.</div>
          <div className="pv-sub">Take a free 5-minute readiness check and meet the attorney who already knows your situation.</div>
          <button className="pv-btn">Check my readiness {Ico.arrow}</button>
          <div className="pv-card">
            <div className="pv-gauge"><b>84</b></div>
            <div><div className="pc-t">Readiness: Strong</div><div className="pc-d">Distinctive mark, in use — let’s file before launch.</div></div>
          </div>
          <div className="pv-chips"><span className="pv-chip">Wordmark</span><span className="pv-chip">Class 42</span><span className="pv-chip">Pre-launch</span></div>
        </div>
      </div>
    </div>
  );
}

/* ---------- STEP 1: connect ---------- */
function StepConnect({ data, setData }) {
  const conns = window.AUDIT.connectors;
  return (
    <div className="step-fade">
      <div className="wiz-head">
        <div className="kicker">Step 1 · Connect</div>
        <h1>Connect your CRM. We’ll audit it.</h1>
        <p>Read-only — we read your contacts and pipeline once to build your workspace, then generate a clean config. We can’t change anything in your CRM.</p>
      </div>
      <div className="oc-grid">
        {conns.map((c) => (
          <button key={c.id} className={'oc-card' + (data.conn === c.id ? ' sel' : '')} onClick={() => setData({ ...data, conn: c.id })}>
            <span className="glyph" style={{ background: c.tint }}>{c.glyph}</span>
            <span className="nm">{c.name}</span>
            <span className="st">{c.status === 'live' ? 'Supported' : 'Beta'}</span>
          </button>
        ))}
      </div>
      <div className="oc-mini">
        <div className="mh">
          <Gauge value={61} size={64} stroke={8} label="" />
          <div><div className="mt">Full audit complete</div><div className="md">1,248 contacts read · top fixes baked into your workspace</div></div>
        </div>
        <div className="ml">
          {MINI.map((m, i) => (
            <div className="mi" key={i}><span className="md2" style={{ background: m.dot }}></span><div><b>{m.t}</b><div style={{ color: 'var(--ink-3)', fontSize: 12, marginTop: 2 }}>{m.impact}</div></div></div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ---------- STEP 2: brand extraction ---------- */
function StepBrand({ data, setData }) {
  const [phase, setPhase] = useState(data.brandDone ? 'result' : 'url');
  const [url, setUrl] = useState(data.siteKey);
  const site = SITES[data.siteKey];
  const primaryAA = useMemo(() => ensureAA(data.primary, site.on), [data.primary, site.on]);
  const [count, setCount] = useState(10);
  const [paused, setPaused] = useState(false);

  // scan when entering
  useEffect(() => {
    if (phase !== 'scan') return;
    const t = setTimeout(() => { setPhase('result'); setData((d) => ({ ...d, brandDone: true })); }, 2100);
    return () => clearTimeout(t);
  }, [phase]);

  // confirm countdown
  useEffect(() => {
    if (phase !== 'result' || paused || data.confirmed) return;
    if (count <= 0) { setData((d) => ({ ...d, confirmed: true })); return; }
    const t = setTimeout(() => setCount((c) => c - 1), 1000);
    return () => clearTimeout(t);
  }, [phase, count, paused, data.confirmed]);

  const run = () => { setPhase('scan'); setCount(10); setPaused(false); };
  const C = 2 * Math.PI * 17;

  return (
    <div className="step-fade">
      <div className="wiz-head">
        <div className="kicker">Step 2 · Brand · Magic moment</div>
        <h1>Paste your site. We’ll wear your brand.</h1>
        <p>Every surface your clients touch will be themed in your brand — never ours. We extract it, you confirm, and you can tweak anything before it goes live.</p>
      </div>

      {phase === 'url' && (
        <div>
          <div className="bx-url">
            <input className="input" value={url} onChange={(e) => setUrl(e.target.value)} placeholder="yourfirm.com" />
            <button className="btn btn-primary" onClick={run}>Extract brand {Ico.arrow}</button>
          </div>
          <div className="bx-suggest">
            <span className="sl">Try a demo firm:</span>
            {Object.keys(SITES).map((k) => (
              <button key={k} className="bx-chip" onClick={() => { setUrl(k); setData((d) => ({ ...d, siteKey: k, primary: SITES[k].swatches[0], radius: SITES[k].radius, display: SITES[k].display, confirmed: false })); setTimeout(run, 0); }}>{k}</button>
            ))}
          </div>
        </div>
      )}

      {phase === 'scan' && (
        <div className="bx-scan">
          <div className="ring"></div>
          <div><div className="bt">Reading {url}…</div><div className="bd">Pulling logo, palette, type & tone of voice</div></div>
        </div>
      )}

      {phase === 'result' && (
        <div className="bx-split">
          {/* extracted + tweak */}
          <div>
            <div className="bx-card">
              <div className="bxh"><span className="t">Extracted brand</span><span className="src">from {Object.keys(SITES).find((k) => SITES[k] === site)}</span></div>
              <div className="bx-body">
                <div className="bx-field">
                  <div className="fl">{Ico.building} Logo &amp; name</div>
                  <div className="bx-logo"><span className="lg" style={{ background: primaryAA.color }}>{site.logo}</span><div><div className="lgn" style={{ fontFamily: `'${data.display}', serif` }}>{site.name}</div><div className="lgd">{site.tier}</div></div></div>
                </div>
                <div className="bx-field">
                  <div className="fl">{Ico.palette} Primary color · pick or keep</div>
                  <div className="bx-swatches">
                    {site.swatches.map((sw) => (
                      <div key={sw} className={'bx-sw' + (data.primary === sw ? ' sel' : '')} onClick={() => setData({ ...data, primary: sw })}>
                        <span className="chip" style={{ background: sw }}>{data.primary === sw && <svg viewBox="0 0 24 24" fill="none" stroke={contrast(sw, '#fff') >= 2.2 ? '#fff' : '#000'} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l4 4 10-10" /></svg>}</span>
                        <span className="hx">{sw}</span>
                      </div>
                    ))}
                  </div>
                  <div className={'bx-contrast ' + (primaryAA.adjusted ? 'nudged' : 'ok')}>
                    {primaryAA.adjusted ? Ico.shield : Ico.check}
                    <div>
                      {primaryAA.adjusted
                        ? <span><b>We nudged it darker so buttons stay readable.</b><div className="cd">Your <span className="ratio">{data.primary}</span> scored <span className="ratio">{r1(primaryAA.before)}:1</span> on white — below the AA minimum. We’re rendering <span className="ratio">{primaryAA.color}</span> at <span className="ratio">{r1(primaryAA.after)}:1</span>. Your real brand still shows everywhere text isn’t on top.</div></span>
                        : <span><b>Contrast verified — WCAG AA.</b><div className="cd">Button text hits <span className="ratio">{r1(primaryAA.after)}:1</span> on your primary. No adjustment needed.</div></span>}
                    </div>
                  </div>
                </div>
                <div className="bx-field">
                  <div className="fl">{Ico.type} Typeface</div>
                  <div className="bx-fontpick">
                    {[site.display, 'Bricolage Grotesque'].map((f) => (
                      <button key={f} className={data.display === f ? 'on' : ''} style={{ fontFamily: `'${f}', serif` }} onClick={() => setData({ ...data, display: f })}>{f}</button>
                    ))}
                  </div>
                </div>
                <div className="bx-field">
                  <div className="fl">{Ico.spark} Tone of voice</div>
                  <div className="bx-tone">{site.traits.map((t) => <span className="tt" key={t}>{t}</span>)}</div>
                  <div className="bx-sample" style={{ fontFamily: `'${data.display}', serif` }}>{site.sample}</div>
                </div>
                <div className="bx-field">
                  <div className="fl">{Ico.sliders} Corner radius</div>
                  <div className="bx-radius">
                    <input type="range" min="0" max="22" value={data.radius} onChange={(e) => setData({ ...data, radius: +e.target.value })} />
                    <span className="rv">{data.radius}px</span>
                  </div>
                </div>
              </div>
            </div>

            {!data.confirmed ? (
              <div className="bx-confirm">
                <div className="cring">
                  <svg width="42" height="42" viewBox="0 0 42 42"><circle cx="21" cy="21" r="17" fill="none" stroke="rgba(255,255,255,.2)" strokeWidth="3" /><circle cx="21" cy="21" r="17" fill="none" stroke="#6E8DF6" strokeWidth="3" strokeLinecap="round" strokeDasharray={C} strokeDashoffset={C * (1 - count / 10)} style={{ transition: 'stroke-dashoffset 1s linear' }} /></svg>
                  <span className="cn">{count}</span>
                </div>
                <div><div className="ct">{paused ? 'Paused — tweak away' : 'Applying your brand…'}</div><div className="cd">{paused ? 'Hit apply when it looks right.' : 'Auto-applies in ' + count + 's. Tweak anything above to pause.'}</div></div>
                <div className="sp"></div>
                {!paused && <button className="btn btn-pause btn-sm" onClick={() => setPaused(true)}>Pause</button>}
                <button className="btn btn-primary btn-sm" onClick={() => setData((d) => ({ ...d, confirmed: true }))}>Apply {Ico.check}</button>
              </div>
            ) : (
              <div className="bx-confirm" style={{ background: 'var(--protected)', color: '#fff' }}>
                <span style={{ width: 42, height: 42, display: 'grid', placeItems: 'center', background: 'rgba(255,255,255,.16)', borderRadius: '50%' }}>{Ico.check}</span>
                <div><div className="ct">Brand applied.</div><div className="cd" style={{ color: 'rgba(255,255,255,.85)' }}>{site.name}’s theme is live across every client surface.</div></div>
              </div>
            )}
          </div>

          {/* live preview */}
          <LivePreview site={site} primaryAA={primaryAA.color} radius={data.radius} display={data.display} />
        </div>
      )}
    </div>
  );
}

/* ---------- STEP 3: configure ---------- */
function StepConfigure({ data, setData }) {
  const c = window.AUDIT.config;
  const [tab, setTab] = useState('stages');
  return (
    <div className="step-fade">
      <div className="wiz-head">
        <div className="kicker">Step 3 · Configure</div>
        <h1>Review the operating system we generated.</h1>
        <p>Built from your audit — your pipeline, taxonomy and packages. Everything here is editable now and later. Nothing is locked.</p>
      </div>
      <div className="cfg-note">{Ico.spark} Generated from 1,248 contacts and your current pipeline. Edit anything, or accept as-is.</div>
      <div className="cfg-tabs">
        {[['stages', 'Pipeline'], ['taxonomy', 'Taxonomy'], ['packages', 'Packages']].map(([k, l]) => (
          <button key={k} className={'cfg-tab' + (tab === k ? ' on' : '')} onClick={() => setTab(k)}>{l}</button>
        ))}
      </div>
      {tab === 'stages' && (
        <div className="cfg-panel">
          {c.stages.map((s, i) => (
            <div className="cfg-line" key={i}><span className="num">{String(i + 1).padStart(2, '0')}</span><span className="gd" style={{ background: s.dot }}></span><span className="nm">{s.name}</span><span className="ed">Rename</span></div>
          ))}
        </div>
      )}
      {tab === 'taxonomy' && (
        <div className="cfg-panel">
          {c.taxonomy.map((t, i) => (
            <div className="cfg-line" key={i}><span className="nm" style={{ flex: '0 0 130px' }}>{t.dim}</span><span className="tt">{t.tags.map((tag) => <span className="lozenge" key={tag}><span className="d"></span>{tag}</span>)}</span><span className="sp" style={{ flex: 1 }}></span><span className="ed">Edit</span></div>
          ))}
        </div>
      )}
      {tab === 'packages' && (
        <div className="cfg-panel">
          {c.packages.map((p, i) => (
            <div className="cfg-line" key={i}><span className="nm">{p.name}<div style={{ fontWeight: 400, fontSize: 12.5, color: 'var(--ink-3)', marginTop: 2 }}>{p.scope}</div></span><span className="pp">{p.price}</span><span className="ed">Edit</span></div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ---------- STEP 4: import ---------- */
const IMPORT_TASKS = [
  { t: 'Provisioning your workspace', v: 'riverapark.lectual.app' },
  { t: 'Importing 1,248 contacts', v: '1,248' },
  { t: 'Applying clean taxonomy', v: '5 dimensions' },
  { t: 'Mapping leads onto 10 stages', v: '312 leads' },
  { t: 'Theming every client surface', v: 'your brand' },
  { t: 'Arming HIGH / MED / NURTURE drips', v: '3 sequences' },
];
function StepImport({ onDone }) {
  const [idx, setIdx] = useState(0);
  useEffect(() => {
    if (idx >= IMPORT_TASKS.length) { const t = setTimeout(onDone, 700); return () => clearTimeout(t); }
    const t = setTimeout(() => setIdx((n) => n + 1), 720);
    return () => clearTimeout(t);
  }, [idx]);
  return (
    <div className="step-fade imp">
      <div className="wiz-head" style={{ textAlign: 'center' }}>
        <div className="kicker">Step 4 · Import</div>
        <h1>Building your workspace…</h1>
      </div>
      <div className="imp-list">
        {IMPORT_TASKS.map((task, i) => {
          const state = i < idx ? 'done' : i === idx ? 'run' : 'wait';
          return (
            <div className={'imp-row ' + state} key={i}>
              <span className="imp-ic">{i < idx ? Ico.check : null}</span>
              <span className="it">{task.t}</span>
              {i < idx && <span className="iv">{task.v}</span>}
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ---------- STEP 5: ready ---------- */
function StepReady({ data }) {
  const site = SITES[data.siteKey];
  const primaryAA = ensureAA(data.primary, site.on).color;
  const colors = [primaryAA, '#1B6B4C', '#9C6209', '#2F5BE6', site.ink];
  return (
    <div className="step-fade ready">
      <div className="confetti" aria-hidden="true">
        {Array.from({ length: 22 }).map((_, i) => (
          <i key={i} style={{ left: (4 + i * 4.3) + '%', background: colors[i % colors.length], animationDelay: (i % 6) * 0.08 + 's', transform: `translateY(0) rotate(${i * 36}deg)` }} />
        ))}
      </div>
      <div className="seal">{Ico.check}</div>
      <h1>Your workspace is ready.</h1>
      <p>{site.name} is live on Lectual — clean data, your stages, your brand on every client surface. Founders who finish a readiness check now land straight in your pipeline.</p>
      <div className="ready-card">
        <span className="rlogo" style={{ background: primaryAA }}>{site.logo}</span>
        <div style={{ flex: 1 }}><div className="rt">{site.name}</div><div className="rd">riverapark.lectual.app · {site.tier}</div></div>
        <span className="lozenge" style={{ color: 'var(--protected)', borderColor: 'transparent', background: 'var(--protected-bg)', fontWeight: 700 }}><span className="d" style={{ background: 'var(--protected)' }}></span>Live</span>
      </div>
      <div className="ready-stats">
        <div className="rs"><b>1,248</b><span>contacts imported</span></div>
        <div className="rs"><b>312</b><span>leads mapped</span></div>
        <div className="rs"><b className="c-strong">+$182k</b><span>recoverable / yr</span></div>
      </div>
      <div className="ready-cta">
        <a className="btn btn-primary btn-lg" href="Lectual Attorney CRM.html">Open my workspace {Ico.arrow}</a>
        <a className="btn btn-secondary btn-lg" href="Lectual Public Audit.html">View full audit</a>
      </div>
    </div>
  );
}

/* ---------- tweaks ---------- */
function Tweaks({ t, setTweak }) {
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Atmosphere" />
      <TweakRadio label="Mood" value={t.mood} options={[{ value: 'warm', label: 'Warm' }, { value: 'cool', label: 'Cool' }, { value: 'dark', label: 'Dark' }]} onChange={(v) => setTweak('mood', v)} />
      <TweakSection label="Demo" />
      <TweakRadio label="Firm to extract" value={t.site} options={[{ value: 'riverapark.law', label: 'Rivera Park' }, { value: 'northstarip.com', label: 'Northstar' }]} onChange={(v) => setTweak('site', v)} />
      <TweakSlider label="Start on step" value={t.startStep} min={1} max={5} onChange={(v) => setTweak('startStep', v)} />
    </TweaksPanel>
  );
}

/* ---------- wizard shell ---------- */
function Wizard() {
  const [t, setTweak] = useTweaks(ONB_DEFAULTS);
  const [step, setStep] = useState((t.startStep || 1) - 1);
  const [data, setData] = useState(() => ({ conn: 'lawmatics', siteKey: t.site, primary: SITES[t.site].swatches[0], radius: SITES[t.site].radius, display: SITES[t.site].display, confirmed: false, brandDone: false }));
  useEffect(() => { applyMood(t.mood); }, [t.mood]);
  useEffect(() => { setStep((t.startStep || 1) - 1); }, [t.startStep]);
  useEffect(() => { setData((d) => ({ ...d, siteKey: t.site, primary: SITES[t.site].swatches[0], radius: SITES[t.site].radius, display: SITES[t.site].display, confirmed: false, brandDone: false })); }, [t.site]);

  const site = SITES[data.siteKey];
  const next = () => setStep((s) => Math.min(STEPS.length - 1, s + 1));
  const back = () => setStep((s) => Math.max(0, s - 1));
  const canContinue = step !== 1 || data.confirmed;
  const continueLabel = step === 2 ? 'Looks good — import' : step === 0 ? 'Start with my brand' : 'Continue';

  return (
    <div className="wiz">
      <div className="wiz-top">
        <Echo size={19} />
        <span className="ctx">Setting up <b>{site.name}</b></span>
        <span className="sp"></span>
        <a className="exit" href="Lectual Public Audit.html">{Ico.x} Save &amp; exit</a>
      </div>
      <Stepper step={step} />
      <div className="wiz-body">
        <div className={'wiz-content' + (step === 1 ? ' wide' : '')}>
          {step === 0 && <StepConnect data={data} setData={setData} />}
          {step === 1 && <StepBrand data={data} setData={setData} />}
          {step === 2 && <StepConfigure data={data} setData={setData} />}
          {step === 3 && <StepImport onDone={next} />}
          {step === 4 && <StepReady data={data} />}
        </div>
        {step < 3 && (
          <div className="wiz-nav">
            <div className="inner">
              <button className="back" onClick={back} disabled={step === 0} style={{ opacity: step === 0 ? 0.35 : 1 }}><span style={{ transform: 'scaleX(-1)', display: 'inline-flex' }}>{Ico.arrow}</span>Back</button>
              <span className="sp"></span>
              {step === 1 && !data.confirmed && <span className="hint">Confirm your brand to continue</span>}
              <button className="btn btn-primary" disabled={!canContinue} style={{ opacity: canContinue ? 1 : 0.4, pointerEvents: canContinue ? 'auto' : 'none' }} onClick={next}>{continueLabel} {Ico.arrow}</button>
            </div>
          </div>
        )}
      </div>
      <Tweaks t={t} setTweak={setTweak} />
    </div>
  );
}
ReactDOM.createRoot(document.getElementById('root')).render(<Wizard />);
