// src/quiz.jsx — Adaptive quiz w/ Bayesian cohort inference (R2)
// R2 changes:
//  - Codex MED4: transition microcopy uses useCohortTransitions hook (no stale closure)
//  - Codex LOW1: paid-social-neutral labels ("Weight-management support" not "Lose 30+ lb")
//  - Kimi LOW + FinalCTA copy alignment: extended from 8 → 12 questions
//  - Mobile UX: options always 1-col ≤768px; sticky-top progress; 48pt+ touch targets per age
//  - Codex MED3 baked: nonbinary → forced.gender = 'unknown' (handled in cohort.jsx recordAnswer)

const { useState: useStateQ, useEffect: useEffectQ, useMemo: useMemoQ, useRef: useRefQ, useCallback: useCallbackQ } = React;

const QUIZ = [
  // ── Q1 — Goal (locks goal cohort dimension) ──────────────────────────────
  {
    id: 'goal', type: 'single', stage: 'goal',
    title: 'What are you hoping a peptide protocol can do for you?',
    sub: 'Pick the closest fit — you can refine later.',
    why: 'This shapes which protocols a clinician would even consider — and which we’ll skip.',
    options: [
      { key: 'weight_loss',     label: 'Weight-management support',           weights: { gender: { f: 1.6, m: 0.7 }, age: { '30-44': 1.2, '45-59': 1.2 } }, locks: { goal: 'weight_loss' } },
      { key: 'lean_muscle',     label: 'Build lean muscle · body recomp',     weights: { gender: { f: 0.6, m: 1.6 }, age: { '18-29': 1.5, '30-44': 1.2 } }, locks: { goal: 'lean_muscle' } },
      { key: 'recovery',        label: 'Recover from injury · train faster',  weights: { gender: { f: 0.85, m: 1.3 }, age: { '18-29': 1.2, '30-44': 1.3 } }, locks: { goal: 'recovery' } },
      { key: 'energy_vitality', label: 'More energy · better days',           weights: { gender: { f: 1.2, m: 0.9 }, age: { '30-44': 1.1, '45-59': 1.2 } }, locks: { goal: 'energy_vitality' } },
      { key: 'longevity',       label: 'Healthy aging · longevity support',   weights: { gender: { f: 1.0, m: 1.1 }, age: { '45-59': 1.5, '60+': 1.6 } }, locks: { goal: 'longevity' } },
      { key: 'sleep_stress',    label: 'Better sleep · stress recovery',      weights: { gender: { f: 1.3, m: 0.9 }, age: { '30-44': 1.2, '45-59': 1.2 } }, locks: { goal: 'sleep_stress' } },
      { key: 'hormone',         label: 'Hormone optimization',                weights: { gender: { f: 1.1, m: 1.2 }, age: { '45-59': 1.4, '60+': 1.3 } }, locks: { goal: 'hormone' } },
    ],
  },

  // ── Q2 — Lifestyle ───────────────────────────────────────────────────────
  {
    id: 'lifestyle', type: 'single', stage: 'lifestyle',
    title: 'How would you describe your typical week?',
    why: 'Activity level changes which protocols are appropriate — and how a doctor would dose them.',
    options: [
      { key: 'lift',           label: 'I lift / strength train regularly',  weights: { gender: { f: 0.75, m: 1.5 }, age: { '18-29': 1.3, '30-44': 1.2 } } },
      { key: 'cardio_pilates', label: 'Cardio · pilates · yoga',             weights: { gender: { f: 1.7, m: 0.6 } } },
      { key: 'mixed',          label: 'Mixed — some of both',                weights: { gender: { f: 1.0, m: 1.0 } } },
      { key: 'sedentary',      label: 'Mostly sedentary · want to start',    weights: { gender: { f: 1.2, m: 0.95 }, age: { '45-59': 1.3, '60+': 1.3 } } },
    ],
  },

  // ── Q4 — Success-feels-like (strongest implicit gender signal) ───────────
  {
    id: 'success', type: 'single', stage: 'gender-signal',
    title: 'What would success feel like, six months in?',
    sub: 'Pick the one that lands closest.',
    why: 'Strong personalization signal — how we explain progress to you depends on what "progress" means to you.',
    options: [
      { key: 'toned_lean',  label: 'I want to look toned and lean.',              weights: { gender: { f: 1.6, m: 0.6 } } },
      { key: 'bigger',      label: 'I want to look bigger and more muscular.',    weights: { gender: { f: 0.35, m: 1.9 } } },
      { key: 'strong',      label: 'I want to feel strong and energetic.',        weights: { gender: { f: 1.0, m: 1.0 } } },
      { key: 'clothes_fit', label: 'I want my clothes to fit like they used to.', weights: { gender: { f: 1.5, m: 0.7 } } },
      { key: 'labs',        label: 'I want my doctor happy with my labs.',         weights: { gender: { f: 1.0, m: 1.0 }, age: { '45-59': 1.3, '60+': 1.4 } } },
    ],
  },

  // ── Q5 — History (age signal) ────────────────────────────────────────────
  {
    id: 'history', type: 'single', stage: 'age-inference',
    title: 'When you think about your body now vs. ten years ago…',
    sub: 'Pick the one that lands closest.',
    why: 'Helps us understand which protocols make sense for where you are.',
    options: [
      { key: 'same',     label: 'Honestly, not much has changed.',                       weights: { age: { '18-29': 1.8, '30-44': 1.3 } } },
      { key: 'maintain', label: 'I’ve had to work harder to stay the same.',             weights: { age: { '30-44': 1.6, '45-59': 1.2 } } },
      { key: 'slower',   label: 'Things feel slower — recovery, energy, weight.',       weights: { age: { '45-59': 1.7, '60+': 1.3 } } },
      { key: 'shifted',  label: 'My body has shifted in ways that feel new.',           weights: { age: { '45-59': 1.5, '60+': 1.6 } } },
    ],
  },

  // ── Lead capture — MOVED DEEPER (cont.14 2026-06-02) ─────────────────────
  // Now after 4 real questions (goal/lifestyle/success/history) so the OPTIONAL
  // email-save lands once the user is invested — NOT right after Q1 (operator:
  // "asked one question and then asked for email ... can't have slop like this").
  {
    id: 'lead_capture', type: 'lead',
    title: 'Save your progress?',
    sub: 'We’ll email you a copy of your protocol summary. No spam, no upsells — you can skip.',
  },

  // ── Q6 — Tech comfort (age signal) ───────────────────────────────────────
  {
    id: 'tech', type: 'single', stage: 'age-inference',
    title: 'How do you usually handle health stuff online?',
    why: 'We adapt explanations and detail level to where you are.',
    options: [
      { key: 'apps',    label: 'Use apps, track stuff, comfortable with all of it.', weights: { age: { '18-29': 1.6, '30-44': 1.3 } } },
      { key: 'some',    label: 'Use some apps, read the rest.',                       weights: { age: { '30-44': 1.4, '45-59': 1.2 } } },
      { key: 'careful', label: 'I prefer reading things over before deciding.',       weights: { age: { '45-59': 1.4, '60+': 1.3 } } },
      { key: 'talk',    label: 'I’d rather talk to a person.',                        weights: { age: { '60+': 1.7, '45-59': 1.2 } } },
    ],
  },

  // ── Q7 — Health concerns (multi-signal age + gender) ─────────────────────
  {
    id: 'health_concerns', type: 'single', stage: 'multi-signal',
    title: 'Any specific health goals beyond your primary one?',
    options: [
      { key: 'energy_clarity', label: 'Energy + mental clarity',                       weights: { age: { '30-44': 1.2, '45-59': 1.2 } } },
      { key: 'joint',          label: 'Joint pain · mobility',                          weights: { age: { '45-59': 1.5, '60+': 1.5 } } },
      { key: 'cardio_metab',   label: 'Blood pressure · cholesterol · cardio-metabolic', weights: { age: { '45-59': 1.4, '60+': 1.4 } } },
      { key: 'aesthetics',     label: 'Looking my best for an event',                   weights: { age: { '18-29': 1.4, '30-44': 1.3 } } },
      { key: 'hormone_sx',     label: 'Hormone symptoms · hot flashes · perimenopause', weights: { gender: { f: 2.4, m: 0.05 }, age: { '45-59': 1.7 } } },
      { key: 'none',           label: 'Nothing specific beyond the primary goal',       weights: null },
    ],
  },

  // ── Q8 — Age bracket (explicit lock) ─────────────────────────────────────
  {
    id: 'age', type: 'single', stage: 'lock-age',
    title: 'Which age range describes you?',
    sub: 'Required for safe protocol assignment. Used by the physician reviewing your intake.',
    options: [
      { key: '18-29', label: '18 – 29', meta: { age: '18-29', locksAge: true } },
      { key: '30-44', label: '30 – 44', meta: { age: '30-44', locksAge: true } },
      { key: '45-59', label: '45 – 59', meta: { age: '45-59', locksAge: true } },
      { key: '60+',   label: '60 +',    meta: { age: '60+',   locksAge: true } },
    ],
  },

  // ── Q9 — Gender confirm (skippable when confident) ───────────────────────
  {
    id: 'gender_confirm', type: 'single', stage: 'gender-confirm', skipIfConfident: true,
    title: 'Which best describes you?',
    sub: 'Used only for protocol safety + dose calibration. Skip if you’d rather not say.',
    options: [
      { key: 'f',         label: 'Female',                            meta: { gender: 'f', locksGender: true } },
      { key: 'm',         label: 'Male',                              meta: { gender: 'm', locksGender: true } },
      { key: 'nonbinary', label: 'Nonbinary · prefer not to say',     meta: { gender: 'unknown' } },
    ],
  },

  // ── Q10 — Tried-other-approaches (sunk-cost validation; age signal) ──────
  {
    id: 'tried_before', type: 'single', stage: 'context',
    title: 'Have you tried other approaches to this goal before?',
    options: [
      { key: 'apps_trackers',   label: 'Apps and trackers',                       weights: { age: { '18-29': 1.3, '30-44': 1.3 } } },
      { key: 'medical',         label: 'Medical interventions (Rx, clinic)',      weights: { age: { '30-44': 1.2, '45-59': 1.4 } } },
      { key: 'researching',     label: 'I’m new to this — researching options',   weights: null },
      { key: 'doctor_already',  label: 'I already work with a doctor on this',    weights: { age: { '45-59': 1.4, '60+': 1.5 } } },
    ],
  },

  // ── Q11 — Medical safety (multi-select; clinician hard-stops flagged) ──
  {
    id: 'medical', type: 'multi', stage: 'safety',
    title: 'Any of these in your history?',
    sub: 'Check all that apply. Some conditions require a clinician to review before any prescription can be issued.',
    why: 'Required for safety. Your clinician sees this before signing off on any protocol.',
    options: [
      { key: 'thyroid',         label: 'Thyroid conditions' },
      { key: 'pancreatitis',    label: 'History of pancreatitis' },
      { key: 'diabetes_t1',     label: 'Type 1 diabetes' },
      { key: 'mtc',             label: 'Family history of medullary thyroid cancer' },
      { key: 'eating_disorder', label: 'Past or current eating disorder' },
      { key: 'pregnancy',       label: 'Currently pregnant or breastfeeding' },
      { key: 'none',            label: 'None of the above' },
    ],
  },

  // ── Q12 — Commitment ─────────────────────────────────────────────────────
  {
    id: 'commit', type: 'single', stage: 'preference',
    title: 'How long would you want to give this if your doctor approves?',
    options: [
      { key: '1m', label: '1 month — I want to see if it’s for me.' },
      { key: '3m', label: '3 months — willing to commit to a real trial.' },
      { key: '6m', label: '6+ months — I’m thinking long-term.' },
    ],
  },
];

// ─────────────────────────────────────────────────────────────────────────────
// QUIZ CONTAINER
// ─────────────────────────────────────────────────────────────────────────────
function Quiz({ onComplete, onExit, showVariantTags }) {
  const cohort = useCohort();
  const [idx, setIdx] = useStateQ(0);
  const [answers, setAnswers] = useStateQ({});
  const [transitionMsg, setTransitionMsg] = useStateQ(null);
  const transitionMsgTimer = useRefQ(null);
  const [transitionPhase, setTransitionPhase] = useStateQ('idle'); // 'idle' | 'leaving' | 'entering'

  // Effective question list with skip logic (skipped at render time, not pre-filtered,
  // so confidence-based skipping is recomputed every render).
  const questions = useMemoQ(() => QUIZ.filter((q) => {
    if (q.id === 'gender_confirm' && q.skipIfConfident && cohort.state.confidence.gender >= 0.88) return false;
    return true;
  }), [cohort.state.confidence.gender]);

  const current = questions[idx];
  const isLast = idx === questions.length - 1;
  const progress = ((idx + 1) / (questions.length + 1)) * 100;

  // R4-03 CRIT guard: if `current` is undefined (e.g. idx overshoots questions array via
  // rapid back-to-back clicks during Babel-transformer compile pause OR onComplete race),
  // bail to onComplete immediately instead of throwing TypeError + crashing entire app.
  useEffectQ(() => {
    if (!current && idx > 0) {
      onComplete({ answers, cohort: cohort.resolved, cohortKey: cohort.cohortKey });
    }
  }, [current, idx]);

  // cont.14 A.3.a (Sub-C §2.3): fire `quiz_start` ONCE on first mount so the admin
  // Dashboard funnel records quiz-entry (was quiz_start=0). Fire-and-forget per V2 F2
  // (never blocks; window.sendFunnelEvent swallows errors).
  useEffectQ(() => {
    if (typeof window.sendFunnelEvent === 'function') {
      window.sendFunnelEvent('quiz_start', { page: 'quiz' });
    }
  }, []);

  if (!current) return null;

  // ── Codex MED4 fix: useCohortTransitions hook (no stale closure)
  // Fires after recordAnswer flushes; produces correct cohort labels for microcopy.
  useCohortTransitions(useCallbackQ((t) => {
    let msg = null;
    if (t.genderChanged && t.ageChanged) {
      msg = 'Got it. We’ll tailor this to people like you.';
    } else if (t.genderChanged) {
      msg = t.gender === 'f' ? 'Got it. Here’s what works for women.'
          : t.gender === 'm' ? 'Got it. Here’s what works for men.'
          : null;
    } else if (t.ageChanged) {
      msg = 'Got it. Adjusting how we explain things for your age range.';
    }
    if (msg) {
      setTransitionMsg(msg);
      clearTimeout(transitionMsgTimer.current);
      transitionMsgTimer.current = setTimeout(() => setTransitionMsg(null), 2600);
    }
  }, []));

  useEffectQ(() => () => clearTimeout(transitionMsgTimer.current), []);

  function handleAnswer(value) {
    setAnswers(prev => ({ ...prev, [current.id]: value }));

    const opts = current.options ?? [];
    let weights = null, meta = {};
    if (current.type === 'single') {
      const chosen = opts.find(o => o.key === value);
      weights = chosen?.weights;
      meta = { ...(chosen?.meta ?? {}) };
      if (chosen?.locks?.goal) { meta.locksGoal = true; meta.goal = chosen.locks.goal; }
    } else if (current.type === 'multi') {
      const chosen = opts.filter(o => value.includes(o.key) && o.weights);
      if (chosen.length) {
        const combine = (key) => {
          const acc = {};
          chosen.forEach(c => Object.entries(c.weights[key] || {}).forEach(([k, v]) => acc[k] = (acc[k] ?? 0) + v));
          Object.keys(acc).forEach(k => acc[k] = acc[k] / chosen.length || 1);
          return Object.keys(acc).length ? acc : null;
        };
        weights = { gender: combine('gender'), age: combine('age') };
      }
    }
    cohort.recordAnswer(current.id, weights, meta);

    setTransitionPhase('leaving');
    setTimeout(() => {
      if (isLast) {
        // cont.14 A.3.a (Sub-C §2.3): fire `quiz_complete` BEFORE onComplete so the
        // emit isn't lost when the parent unmounts Quiz on completion. Fire-and-forget.
        if (typeof window.sendFunnelEvent === 'function') {
          window.sendFunnelEvent('quiz_complete', { page: 'quiz' });
        }
        onComplete({ answers: { ...answers, [current.id]: value }, cohort: cohort.resolved, cohortKey: cohort.cohortKey });
      } else {
        setIdx(i => i + 1);
        setTransitionPhase('entering');
        setTimeout(() => setTransitionPhase('idle'), 360);
      }
    }, 220);
  }

  return (
    <div className="cohort-shift" style={{
      minHeight: '100vh', background: 'var(--brand-bg)', color: 'var(--brand-text)',
      display: 'flex', flexDirection: 'column',
    }}>
      <QuizHeader onExit={onExit} idx={idx} total={questions.length} progress={progress} />
      <QuizStageBanner currentId={current.id} />

      <div style={{
        flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'flex-start',
        padding: 'clamp(20px, 4vh, 44px) var(--safe-padding) clamp(40px, 8vh, 80px)',
      }}>
        <div style={{ width: '100%', maxWidth: 720, position: 'relative' }}>
          {transitionMsg && (
            <div style={{
              position: 'absolute', top: -56, left: '50%', transform: 'translateX(-50%)',
              background: 'var(--cohort-accent)', color: 'white',
              padding: '8px 14px', borderRadius: 999,
              fontSize: 13, fontWeight: 500,
              boxShadow: 'var(--shadow-md)',
              animation: 'fade-in-up 320ms ease-out both',
              whiteSpace: 'nowrap',
              maxWidth: '92vw',
              overflow: 'hidden', textOverflow: 'ellipsis',
              zIndex: 5,
            }}>{transitionMsg}</div>
          )}
          <div style={{
            opacity: transitionPhase === 'leaving' ? 0 : 1,
            transform: transitionPhase === 'leaving' ? 'translateY(-8px)' : 'translateY(0)',
            transition: 'opacity 220ms var(--easing-out), transform 220ms var(--easing-out)',
          }}>
            {current.type === 'lead' ? (
              <LeadCaptureCard
                cohortKey={cohort.cohortKey}
                onSubmit={(lead) => { setAnswers(a => ({ ...a, lead })); handleAnswer(lead); }}
                onSkip={() => { setIdx(i => i + 1); }}
              />
            ) : (
              <QuestionCard
                key={current.id}
                question={current}
                answer={answers[current.id]}
                onAnswer={handleAnswer}
                stepLabel={`Q${idx + 1} of ${questions.length}`}
                showVariantTags={showVariantTags}
              />
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// QUIZ STAGE BANNER — 5-stage progress indicator (per NN-10)
// ─────────────────────────────────────────────────────────────────────────────
const STAGE_MAP = {
  goal:           { stage: 0, label: 'Goal' },
  lead_capture:   { stage: 2, label: 'Health' },
  lifestyle:      { stage: 1, label: 'Preliminary' },
  success:        { stage: 1, label: 'Preliminary' },
  history:        { stage: 2, label: 'Health' },
  tech:           { stage: 2, label: 'Health' },
  health_concerns:{ stage: 2, label: 'Health' },
  age:            { stage: 3, label: 'Details' },
  gender_confirm: { stage: 3, label: 'Details' },
  tried_before:   { stage: 3, label: 'Details' },
  medical:        { stage: 4, label: 'Eligibility' },
  commit:         { stage: 4, label: 'Eligibility' },
};
const STAGE_LABELS = ['Goal', 'Preliminary', 'Health', 'Details', 'Eligibility'];

function QuizStageBanner({ currentId }) {
  const current = STAGE_MAP[currentId]?.stage ?? 0;
  return (
    <div className="cohort-shift" style={{
      borderBottom: '1px solid var(--brand-border)',
      background: 'var(--brand-bg-elev)',
      padding: '18px var(--safe-padding)',
    }}>
      <div className="stage-track">
        {STAGE_LABELS.map((label, i) => {
          const cls = i < current ? 'past' : i === current ? 'current' : 'future';
          return (
            <div key={i} className={`stage-cell ${cls}`}>
              <div className="stage-dot">{i + 1}</div>
              <div className="stage-lbl">{label}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function QuizHeader({ onExit, idx, total, progress }) {
  return (
    <div className="cohort-shift" style={{
      position: 'sticky', top: 0, zIndex: 30,
      borderBottom: '1px solid var(--brand-border)',
      background: 'color-mix(in srgb, var(--brand-bg) 92%, transparent)',
      backdropFilter: 'blur(12px)',
    }}>
      <div style={{
        maxWidth: 960, margin: '0 auto', padding: '12px var(--safe-padding)',
        display: 'flex', alignItems: 'center', gap: 14,
      }}>
        <ZeraLogo size={18} />
        <div style={{ flex: 1 }}>
          <ProgressBar value={idx + 1} max={total + 1} />
        </div>
        <span className="mono" style={{ fontSize: 11.5, color: 'var(--brand-text-muted)', whiteSpace: 'nowrap' }}>
          Q{String(idx + 1).padStart(2, '0')} / {String(total).padStart(2, '0')}
        </span>
        <button onClick={onExit} aria-label="Exit quiz" style={{
          background: 'transparent', border: '1px solid var(--brand-border)',
          width: 32, height: 32, borderRadius: 999, color: 'var(--brand-text-muted)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          cursor: 'pointer', flexShrink: 0,
        }}>
          <Icon kind="x" size={14} />
        </button>
      </div>
    </div>
  );
}

function QuestionCard({ question, answer, onAnswer, stepLabel, showVariantTags }) {
  const [multiVal, setMultiVal] = useStateQ(question.type === 'multi' ? (answer ?? []) : null);
  const [expandWhy, setExpandWhy] = useStateQ(false);
  const isMobile = useMedia('(max-width: 768px)');
  useEffectQ(() => { if (question.type === 'multi') setMultiVal(answer ?? []); }, [question.id]);

  // Mobile: always 1-col. Desktop: 2-col for ≤4 options, 1-col for more.
  const gridCols = isMobile ? '1fr' :
                   (question.options && question.options.length > 4) ? '1fr' : 'repeat(2, 1fr)';

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, justifyContent: 'space-between' }}>
        <span className="eyebrow" style={{ fontSize: 12 }}>{stepLabel} · {(STAGE_MAP[question.id]?.label || 'Your answers').toUpperCase()}</span>
        {showVariantTags && <VariantTag id={`q_${question.id}`} />}
      </div>
      <div>
        <h2 style={{ fontSize: 'clamp(24px, 3.4vw, 38px)' }}>{question.title}</h2>
        {question.sub && (
          <p style={{ marginTop: 12, fontSize: 'clamp(14px, 1.4vw, 16px)', color: 'var(--brand-text-muted)' }}>
            {question.sub}
          </p>
        )}
      </div>

      {question.type === 'single' && (
        <div style={{ display: 'grid', gridTemplateColumns: gridCols, gap: 10 }}>
          {question.options.map((opt) => (
            <OptionPill
              key={opt.key} label={opt.label}
              selected={answer === opt.key}
              onSelect={() => onAnswer(opt.key)}
            />
          ))}
        </div>
      )}
      {question.type === 'multi' && (
        <>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 10 }}>
            {question.options.map((opt) => {
              const selected = multiVal.includes(opt.key);
              return (
                <OptionPill
                  key={opt.key} label={opt.label}
                  selected={selected} multi
                  onSelect={() => {
                    let next;
                    if (opt.key === 'none') next = selected ? [] : ['none'];
                    else next = selected ? multiVal.filter(k => k !== opt.key) : [...multiVal.filter(k => k !== 'none'), opt.key];
                    setMultiVal(next);
                  }}
                />
              );
            })}
          </div>
          <Button size="lg" fullWidth pulse onClick={() => onAnswer(multiVal)} disabled={multiVal.length === 0}>
            Continue <Icon kind="arrow" size={16} />
          </Button>
        </>
      )}

      {question.why && (
        <div className="cohort-shift" style={{ borderTop: '1px solid var(--brand-border)', paddingTop: 12 }}>
          <button onClick={() => setExpandWhy(v => !v)} style={{
            display: 'inline-flex', alignItems: 'center', gap: 8,
            background: 'transparent', border: 'none', padding: 0,
            color: 'var(--brand-text-muted)', cursor: 'pointer', fontSize: 13,
            minHeight: 32,
          }}>
            <span style={{ transition: 'transform 200ms', display: 'inline-flex',
                           transform: expandWhy ? 'rotate(90deg)' : 'rotate(0deg)' }}>
              <Icon kind="chev" size={12} />
            </span>
            Why we’re asking
          </button>
          {expandWhy && (
            <p style={{
              marginTop: 8, fontSize: 13.5, color: 'var(--brand-text-muted)',
              maxWidth: 560, lineHeight: 1.55,
              animation: 'fade-in-up 240ms ease-out both',
            }}>{question.why}</p>
          )}
        </div>
      )}
    </div>
  );
}

function OptionPill({ label, selected, onSelect, multi = false }) {
  const [hover, setHover] = useStateQ(false);
  return (
    <button
      onClick={onSelect}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      className="cohort-shift"
      style={{
        textAlign: 'left',
        padding: '16px 18px',
        minHeight: 'calc(var(--touch-target-min) + 12px)',
        background: selected ? 'var(--cohort-accent-soft)' : (hover ? 'var(--brand-bg-sunken)' : 'var(--brand-bg-elev)'),
        color: selected ? 'var(--cohort-accent-ink)' : 'var(--brand-text)',
        border: `${selected ? '1.5px' : '1px'} solid ${selected ? 'var(--cohort-accent)' : 'var(--brand-border)'}`,
        borderRadius: 'var(--radius-button)',
        fontSize: 'clamp(16px, 1.5vw, 18px)', fontWeight: selected ? 580 : 480,
        cursor: 'pointer',
        display: 'flex', alignItems: 'center', gap: 12,
        transition: `transform 80ms ease-out, background var(--transition-ms) var(--easing-out), border-color var(--transition-ms) var(--easing-out)`,
      }}
      onMouseDown={e => e.currentTarget.style.transform = 'scale(0.985)'}
      onMouseUp={e => e.currentTarget.style.transform = 'scale(1)'}
    >
      <span style={{
        flexShrink: 0,
        width: multi ? 20 : 18, height: multi ? 20 : 18,
        borderRadius: multi ? 5 : 999,
        border: `1.5px solid ${selected ? 'var(--cohort-accent)' : 'var(--brand-border-strong)'}`,
        background: selected ? 'var(--cohort-accent)' : 'transparent',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        color: 'white',
        transition: 'background 200ms, border-color 200ms',
      }}>
        {selected && <Icon kind="check" size={11} strokeWidth={2.6} />}
      </span>
      <span style={{ flex: 1, minWidth: 0 }}>{label}</span>
    </button>
  );
}

function LeadCaptureCard({ onSubmit, onSkip, cohortKey }) {
  const [email, setEmail] = useStateQ('');
  const [name, setName] = useStateQ('');
  const [hp, setHp] = useStateQ('');
  const [consentMarketing, setConsentMarketing] = useStateQ(true);
  const elapsed = useFormMountTs();
  const valid = /\S+@\S+\.\S+/.test(email);

  async function handleSubmit() {
    if (!valid) return;
    // Fire-and-forget per brief: "Don't block the UX thread on the POST".
    // Local dev may surface the request in the operator API log.
    submitLead({
      email,
      firstName: name || undefined,
      cohortKey,
      hp,
      t0_ms: elapsed(),
      consent_marketing: consentMarketing,
      consent_data_use: true, // taking the quiz implies functional data use
    }).catch(() => { /* swallow — proceed regardless */ });
    onSubmit({ name, email });
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
      <span className="eyebrow" style={{ fontSize: 10.5 }}>SAVE YOUR PROGRESS · OPTIONAL</span>
      <h2 style={{ fontSize: 'clamp(24px, 3.4vw, 38px)' }}>Want a copy of your protocol when you’re done?</h2>
      <p style={{ fontSize: 'clamp(14px, 1.4vw, 16px)', color: 'var(--brand-text-muted)', maxWidth: 540 }}>
        We’ll email you the summary. No spam — only your protocol updates + safety notices. Unsubscribe in one click.
      </p>
      <Card padding={22} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <Input label="First name (optional)" value={name} onChange={setName} placeholder="Alex" />
        <Input label="Email" value={email} onChange={setEmail} placeholder="you@example.com" type="email" />
        <HoneypotField value={hp} onChange={setHp} name="company_name" />
        <label style={{ display: 'flex', alignItems: 'flex-start', gap: 8, fontSize: 13, color: 'var(--brand-text-muted)', marginTop: 4 }}>
          <input
            type="checkbox"
            checked={consentMarketing}
            onChange={(e) => setConsentMarketing(e.target.checked)}
            style={{ marginTop: 3, accentColor: 'var(--cohort-accent)' }}
          />
          <span>Email me my results + occasional safety notices. Single-opt-in · CAN-SPAM compliant.</span>
        </label>
        <div className="lead-actions" style={{ display: 'flex', gap: 10, marginTop: 4 }}>
          <style>{`
            @media (max-width: 480px) {
              .lead-actions { flex-direction: column-reverse; }
              .lead-actions > * { width: 100%; }
            }
          `}</style>
          <Button variant="secondary" onClick={onSkip}>Skip for now</Button>
          <Button onClick={handleSubmit} disabled={!valid} fullWidth pulse>
            Save my progress <Icon kind="arrow" size={16} />
          </Button>
        </div>
      </Card>
      <p style={{ fontSize: 13.5, color: 'var(--brand-text-soft)' }}>
        Email is never sold or used for ads. Unsubscribe in one click.
      </p>
    </div>
  );
}

function Input({ label, value, onChange, placeholder, type = 'text' }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <span style={{ fontSize: 12, color: 'var(--brand-text-muted)', fontWeight: 500 }}>{label}</span>
      <input
        type={type} value={value}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        className="cohort-shift"
        style={{
          padding: '14px 14px', fontSize: 16,
          background: 'var(--brand-bg)', color: 'var(--brand-text)',
          border: '1px solid var(--brand-border)',
          borderRadius: 'var(--radius-input)', outline: 'none',
          fontFamily: 'inherit',
          minHeight: 'var(--touch-target-min)',
        }}
        onFocus={(e) => e.target.style.borderColor = 'var(--cohort-accent)'}
        onBlur={(e) => e.target.style.borderColor = 'var(--brand-border)'}
      />
    </label>
  );
}

Object.assign(window, { Quiz });
