// Desert booking flow — branching: returning vs new client.
// Returning: 1 step → fast-track to Square.
// New: full intake — service, current/desired length, inspiration tags, photo upload, contact.

const { useState, useEffect, useRef, useMemo } = React;

const SERVICE_OPTIONS = [
  { id: 'lived-in', label: 'Lived-In Color', sub: 'Soft, grown-out balayage', icon: '✦' },
  { id: 'blonding', label: 'Soft Blonding', sub: 'Hand-painted highlights', icon: '☼' },
  { id: 'pixie', label: 'Pixie / Cut', sub: 'Short to long, shaped', icon: '✂' },
  { id: 'refresh', label: 'Color Refresh', sub: 'Glaze + tone-up', icon: '⟳' },
  { id: 'correction', label: 'Color Correction', sub: 'Re-do, lift, fix', icon: '◈' },
  { id: 'bridal', label: 'Bridal / Event', sub: 'Up-do or styling', icon: '◉' },
];

const LENGTHS = [
  { id: 'pixie', label: 'Pixie', viz: 18 },
  { id: 'short', label: 'Short / Bob', viz: 36 },
  { id: 'mid', label: 'Shoulder', viz: 60 },
  { id: 'long', label: 'Long', viz: 90 },
  { id: 'verylong', label: 'Very long', viz: 120 },
];

const VIBES = [
  'Sun-kissed', 'Bright blonde', 'Honey', 'Caramel', 'Espresso',
  'Copper', 'Rooty', 'Money-piece', 'Soft contrast', 'Lived-in',
  'Cool tone', 'Warm tone', 'Low maintenance', 'Bold change',
];

const SQUARE_URL = 'https://book.squareup.com/appointments/mdmbjuycc1qgg2/location/LM3X7DAVNJ86M/services';

// ── Booking flow root ──────────────────────────────────────────────────
function BookingFlow({ palette, fonts }) {
  const [step, setStep] = useState(0);
  const [direction, setDirection] = useState(1);
  const [data, setData] = useState({
    returning: null,
    service: null,
    currentLength: null,
    desiredLength: null,
    vibes: [],
    photos: [],
    source: null,
    sourceDetail: '',
    name: '',
    phone: '',
    note: '',
  });

  // Branching path. step indices and totalSteps depend on returning value.
  // returning === true:  [returning] → [returning_handoff]
  // returning === false: [returning] → [service] → [length] → [vibe] → [photos] → [source] → [contact] → [done]
  const isReturning = data.returning === true;
  const totalSteps = isReturning ? 2 : 8;

  const [submitting, setSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState('');

  const update = (k, v) => setData(d => ({ ...d, [k]: v }));
  const toggleVibe = (v) => setData(d => ({
    ...d, vibes: d.vibes.includes(v) ? d.vibes.filter(x => x !== v) : [...d.vibes, v],
  }));
  const back = () => { setDirection(-1); setStep(s => Math.max(s - 1, 0)); };
  const next = async () => {
    if (!isReturning && step === 6) {
      setSubmitting(true);
      setSubmitError('');
      try {
        const res = await fetch('/api/booking', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            returning: data.returning,
            service: data.service,
            currentLength: data.currentLength,
            desiredLength: data.desiredLength,
            vibes: data.vibes,
            photos: data.photos.map(p => p.name || 'photo').slice(0, 10),
            source: data.source,
            sourceDetail: data.sourceDetail,
            name: data.name,
            phone: data.phone,
            email: data.email,
            notes: data.note,
          }),
        });
        if (!res.ok) throw new Error(`Submit failed (${res.status})`);
      } catch (e) {
        setSubmitError(e.message || 'Could not send your request. Please call (833) 352-1692.');
        setSubmitting(false);
        return;
      }
      setSubmitting(false);
    }
    setDirection(1);
    setStep(s => s + 1);
  };

  const canProceed = useMemo(() => {
    if (step === 0) return data.returning !== null;
    if (isReturning) return true;
    if (step === 1) return !!data.service;
    if (step === 2) return !!data.currentLength && !!data.desiredLength;
    if (step === 3) return data.vibes.length > 0;
    if (step === 4) return true; // photos optional
    if (step === 5) return !!data.source; // source required (it's a tap-to-pick)
    if (step === 6) return data.name.trim().length > 1 && data.phone.trim().length >= 7;
    return true;
  }, [step, data, isReturning]);

  const isLastInputStep = isReturning ? step === 0 : step === 6;
  const showFooter = step < totalSteps - 1;

  const C = palette;
  const FF = fonts;

  return (
    <div style={{
      position: 'relative', background: C.cream, borderRadius: 32, overflow: 'hidden',
      border: `1px solid ${C.terra}22`,
      boxShadow: `0 40px 100px -30px ${C.terra}55, 0 4px 12px rgba(0,0,0,0.04)`,
      maxWidth: 920, margin: '0 auto',
    }}>
      <BookingBackdrop step={step} total={totalSteps} C={C} />
      <BookingHeader step={step} total={totalSteps} C={C} FF={FF} />

      <div style={{ position: 'relative', minHeight: 580 }}>
        <StepShell active={step === 0} direction={direction}>
          <ReturningStep data={data} update={update} C={C} FF={FF} onPick={(v) => { update('returning', v); setTimeout(() => { setDirection(1); setStep(1); }, 380); }} />
        </StepShell>

        {/* Returning fast-track */}
        {isReturning && (
          <StepShell active={step === 1} direction={direction}>
            <ReturningHandoff C={C} FF={FF} />
          </StepShell>
        )}

        {/* New client path */}
        {!isReturning && data.returning === false && <>
          <StepShell active={step === 1} direction={direction}>
            <ServiceStep data={data} update={update} C={C} FF={FF} />
          </StepShell>
          <StepShell active={step === 2} direction={direction}>
            <LengthStep data={data} update={update} C={C} FF={FF} />
          </StepShell>
          <StepShell active={step === 3} direction={direction}>
            <VibeStep data={data} toggleVibe={toggleVibe} C={C} FF={FF} />
          </StepShell>
          <StepShell active={step === 4} direction={direction}>
            <PhotoStep data={data} update={update} C={C} FF={FF} />
          </StepShell>
          <StepShell active={step === 5} direction={direction}>
            <SourceStep data={data} update={update} C={C} FF={FF} />
          </StepShell>
          <StepShell active={step === 6} direction={direction}>
            <ContactStep data={data} update={update} C={C} FF={FF} />
          </StepShell>
          <StepShell active={step === 7} direction={direction}>
            <DoneStep data={data} C={C} FF={FF} />
          </StepShell>
        </>}
      </div>

      {showFooter && step > 0 && (
        <FooterControls step={step} total={totalSteps} canProceed={canProceed && !submitting} onBack={back} onNext={next} isLast={isLastInputStep} submitting={submitting} submitError={submitError} C={C} FF={FF} />
      )}
    </div>
  );
}

// ── Footer controls ────────────────────────────────────────────────────
function FooterControls({ step, total, canProceed, onBack, onNext, isLast, submitting, submitError, C, FF }) {
  return (
    <div style={{
      padding: '20px 40px 32px',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      borderTop: `1px solid ${C.terra}22`, position: 'relative', zIndex: 2,
      background: 'rgba(244,232,220,.5)', backdropFilter: 'blur(8px)',
      flexWrap: 'wrap', gap: 12,
    }}>
      {submitError && (
        <div style={{
          flexBasis: '100%', order: -1, color: C.rust,
          fontFamily: FF.mono, fontSize: 11, letterSpacing: '0.08em',
        }}>{submitError}</div>
      )}
      <button onClick={onBack} style={{
        background: 'transparent', border: 'none',
        fontFamily: FF.mono, fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase',
        color: C.ink, cursor: 'pointer', padding: '12px 0',
      }}>← Back</button>

      <div style={{ display: 'flex', gap: 8 }}>
        {Array.from({length: total - 1}).map((_, i) => (
          <div key={i} style={{
            width: i === step ? 24 : 6, height: 6, borderRadius: 999,
            background: i <= step ? C.terra : C.terra + '33',
            transition: 'all .4s cubic-bezier(.2,.7,.3,1)',
          }} />
        ))}
      </div>

      <button onClick={onNext} disabled={!canProceed} style={{
        background: canProceed ? C.ink : C.terra + '33',
        color: canProceed ? C.cream : C.ink + '55',
        border: 'none', borderRadius: 999, padding: '14px 28px',
        fontFamily: FF.body, fontSize: 13, fontWeight: 500, letterSpacing: '0.04em',
        cursor: canProceed ? 'pointer' : 'default', transition: 'all .25s',
        boxShadow: canProceed ? `0 8px 24px -8px ${C.ink}66` : 'none',
      }}
      onMouseEnter={(e) => { if (canProceed) e.currentTarget.style.transform = 'translateY(-2px)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; }}>
        {submitting ? 'Sending…' : isLast ? 'Send request →' : 'Continue →'}
      </button>
    </div>
  );
}

// ── Backdrop ───────────────────────────────────────────────────────────
function BookingBackdrop({ step, total, C }) {
  const t = step / Math.max(total - 1, 1);
  const grad = `radial-gradient(circle at ${20 + t * 60}% ${30 + t * 40}%, ${C.sun}66 0%, transparent 55%), radial-gradient(circle at ${80 - t * 60}% ${70 - t * 40}%, ${C.terra}22 0%, transparent 60%)`;
  return (
    <div style={{
      position: 'absolute', inset: 0, background: grad,
      transition: 'background .9s ease-in-out', pointerEvents: 'none',
    }} />
  );
}

// ── Header ─────────────────────────────────────────────────────────────
function BookingHeader({ step, total, C, FF }) {
  const pct = step / Math.max(total - 1, 1);
  const r = 18;
  const c = 2 * Math.PI * r;
  return (
    <div style={{
      position: 'relative', zIndex: 2, padding: '24px 32px 8px',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    }}>
      <div style={{ fontFamily: FF.mono, fontSize: 11, letterSpacing: '0.24em', textTransform: 'uppercase', color: C.rust }}>
        ✦ Reserve your visit
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <span style={{ fontFamily: FF.mono, fontSize: 11, letterSpacing: '0.18em', color: C.ink + 'aa' }}>
          {String(step + 1).padStart(2, '0')} / {String(total).padStart(2, '0')}
        </span>
        <svg width={48} height={48} viewBox="0 0 48 48" style={{ transform: 'rotate(-90deg)' }}>
          <circle cx={24} cy={24} r={r} fill="none" stroke={C.terra + '33'} strokeWidth={2} />
          <circle cx={24} cy={24} r={r} fill="none" stroke={C.terra} strokeWidth={2}
            strokeLinecap="round" strokeDasharray={c} strokeDashoffset={c * (1 - pct)}
            style={{ transition: 'stroke-dashoffset .6s cubic-bezier(.2,.7,.3,1)' }} />
        </svg>
      </div>
    </div>
  );
}

// ── Step shell ─────────────────────────────────────────────────────────
function StepShell({ active, direction, children }) {
  const [render, setRender] = useState(active);
  useEffect(() => {
    if (active) setRender(true);
    else { const t = setTimeout(() => setRender(false), 700); return () => clearTimeout(t); }
  }, [active]);
  if (!render && !active) return null;
  return (
    <div style={{
      position: active ? 'relative' : 'absolute', inset: 0,
      padding: '12px 40px 32px',
      opacity: active ? 1 : 0,
      transform: `translateX(${active ? 0 : direction * 24}px)`,
      filter: active ? 'blur(0px)' : 'blur(6px)',
      transition: 'opacity .55s cubic-bezier(.2,.7,.3,1), transform .65s cubic-bezier(.2,.7,.3,1), filter .55s',
      pointerEvents: active ? 'auto' : 'none',
    }}>
      {children}
    </div>
  );
}

// ── STEP 0: Returning or new ──────────────────────────────────────────
function ReturningStep({ data, update, C, FF, onPick }) {
  const opts = [
    { v: true, title: 'Welcome back', sub: 'I’ll send you straight to the calendar.', emoji: '☼' },
    { v: false, title: 'First time', sub: 'Let’s talk through your hair first.', emoji: '✦' },
  ];
  return (
    <div>
      <h3 style={{ fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 56, lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink }}>
        Have we met<br/>
        <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>before?</span>
      </h3>
      <p style={{ fontFamily: FF.body, fontSize: 14, color: C.ink + 'aa', marginTop: 12, marginBottom: 28 }}>
        Either way is good — just pointing you in the right direction.
      </p>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
        {opts.map((o, i) => {
          const selected = data.returning === o.v;
          return (
            <button key={String(o.v)} onClick={() => onPick(o.v)} style={{
              textAlign: 'left', cursor: 'pointer',
              background: selected ? C.terra : C.cream,
              color: selected ? C.cream : C.ink,
              border: `1px solid ${selected ? C.terra : C.terra + '33'}`,
              borderRadius: 24, padding: '32px 28px',
              transition: 'all .35s cubic-bezier(.2,.7,.3,1)',
              transform: selected ? 'translateY(-3px) scale(1.01)' : 'translateY(0)',
              boxShadow: selected ? `0 24px 48px -16px ${C.terra}aa` : 'none',
              minHeight: 240,
              animation: `bookFadeUp .5s cubic-bezier(.2,.7,.3,1) ${i * 0.08}s both`,
            }}>
              <div style={{ fontFamily: FF.display, fontSize: 36, marginBottom: 16, color: selected ? C.sun : C.terra }}>{o.emoji}</div>
              <div style={{ fontFamily: FF.display, fontSize: 32, fontStyle: 'italic', fontWeight: 400, lineHeight: 1.05 }}>{o.title}</div>
              <div style={{ fontFamily: FF.body, fontSize: 14, marginTop: 12, opacity: 0.85, lineHeight: 1.5 }}>{o.sub}</div>
              <div style={{ marginTop: 24, fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', opacity: selected ? 0.9 : 0.5 }}>
                {o.v ? 'Book on Square →' : 'Quick intake →'}
              </div>
            </button>
          );
        })}
      </div>
      <style>{`@keyframes bookFadeUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }`}</style>
    </div>
  );
}

// ── Returning handoff to Square ────────────────────────────────────────
function ReturningHandoff({ C, FF }) {
  const [redirecting, setRedirecting] = useState(false);
  return (
    <div style={{ textAlign: 'center', paddingTop: 60, paddingBottom: 60 }}>
      <div style={{
        width: 96, height: 96, borderRadius: '50%', background: C.terra,
        margin: '0 auto 32px', display: 'flex', alignItems: 'center', justifyContent: 'center',
        animation: 'pop .6s cubic-bezier(.2,.9,.3,1.4) both',
        boxShadow: `0 24px 60px -16px ${C.terra}aa`,
      }}>
        <span style={{ fontFamily: FF.display, fontSize: 48, color: C.cream }}>☼</span>
      </div>

      <h3 style={{
        fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 64,
        lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink,
        animation: 'bookFadeUp .6s cubic-bezier(.2,.7,.3,1) .35s both',
      }}>
        Welcome back, <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>friend.</span>
      </h3>

      <p style={{
        fontFamily: FF.display, fontSize: 19, fontStyle: 'italic',
        color: C.ink + 'cc', marginTop: 16, marginBottom: 36, maxWidth: 480, marginLeft: 'auto', marginRight: 'auto',
        animation: 'bookFadeUp .6s cubic-bezier(.2,.7,.3,1) .5s both',
      }}>
        Your formula is on file. Pick a day on the calendar and I’ll see you soon.
      </p>

      <a href={SQUARE_URL} target="_blank" rel="noreferrer"
        onClick={() => setRedirecting(true)}
        style={{
          display: 'inline-flex', alignItems: 'center', gap: 12,
          background: C.ink, color: C.cream, textDecoration: 'none',
          padding: '20px 36px', borderRadius: 999,
          fontFamily: FF.body, fontSize: 14, letterSpacing: '0.06em', fontWeight: 500,
          boxShadow: `0 16px 40px -12px ${C.ink}aa`,
          animation: 'bookFadeUp .6s cubic-bezier(.2,.7,.3,1) .65s both',
          transition: 'transform .25s',
        }}
        onMouseEnter={(e) => e.currentTarget.style.transform = 'translateY(-2px)'}
        onMouseLeave={(e) => e.currentTarget.style.transform = 'translateY(0)'}>
        Open Square calendar →
      </a>

      <div style={{
        marginTop: 32, fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.2em',
        textTransform: 'uppercase', color: C.rust,
        animation: 'bookFadeUp .6s cubic-bezier(.2,.7,.3,1) .8s both',
      }}>
        Desert Lounge Salon · 75 N 100 E · Wed & Fri 9–5
      </div>

      <style>{`
        @keyframes pop { 0% { transform: scale(0); } 60% { transform: scale(1.1); } 100% { transform: scale(1); } }
        @keyframes bookFadeUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
      `}</style>
    </div>
  );
}

// ── STEP 1 (new): Service ─────────────────────────────────────────────
function ServiceStep({ data, update, C, FF }) {
  return (
    <div>
      <h3 style={{ fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 56, lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink }}>
        What brings you<br/>
        <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>in?</span>
      </h3>
      <p style={{ fontFamily: FF.body, fontSize: 14, color: C.ink + 'aa', marginTop: 12, marginBottom: 28 }}>
        Pick the closest fit — we’ll narrow it down at consult.
      </p>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
        {SERVICE_OPTIONS.map((o, i) => {
          const selected = data.service === o.id;
          return (
            <button key={o.id} onClick={() => update('service', o.id)} style={{
              textAlign: 'left', cursor: 'pointer',
              background: selected ? C.ink : C.cream,
              color: selected ? C.cream : C.ink,
              border: `1px solid ${selected ? C.ink : C.terra + '33'}`,
              borderRadius: 18, padding: '20px 18px',
              transition: 'all .3s cubic-bezier(.2,.7,.3,1)',
              transform: selected ? 'translateY(-2px)' : 'translateY(0)',
              boxShadow: selected ? `0 16px 32px -12px ${C.ink}88` : 'none',
              animation: `bookFadeUp .5s cubic-bezier(.2,.7,.3,1) ${i * 0.05}s both`,
            }}>
              <div style={{ fontFamily: FF.display, fontSize: 22, marginBottom: 6, color: selected ? C.sun : C.terra }}>{o.icon}</div>
              <div style={{ fontFamily: FF.display, fontSize: 19, fontStyle: 'italic', fontWeight: 400 }}>{o.label}</div>
              <div style={{ fontFamily: FF.body, fontSize: 12, marginTop: 4, opacity: 0.7 }}>{o.sub}</div>
            </button>
          );
        })}
      </div>
    </div>
  );
}

// ── STEP 2 (new): Length — current + desired ───────────────────────────
function LengthStep({ data, update, C, FF }) {
  return (
    <div>
      <h3 style={{ fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 48, lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink }}>
        Where are we starting,<br/>
        <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>where do you want to go?</span>
      </h3>
      <p style={{ fontFamily: FF.body, fontSize: 14, color: C.ink + 'aa', marginTop: 12, marginBottom: 24 }}>
        Approximate is fine.
      </p>

      <LengthRow label="Current length" value={data.currentLength} onPick={(v) => update('currentLength', v)} C={C} FF={FF} />
      <div style={{ height: 20 }} />
      <LengthRow label="Goal length" value={data.desiredLength} onPick={(v) => update('desiredLength', v)} C={C} FF={FF} />
    </div>
  );
}

function LengthRow({ label, value, onPick, C, FF }) {
  return (
    <div>
      <div style={{ fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', color: C.rust, marginBottom: 12 }}>{label}</div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 10 }}>
        {LENGTHS.map((l, i) => {
          const selected = value === l.id;
          return (
            <button key={l.id} onClick={() => onPick(l.id)} style={{
              cursor: 'pointer',
              background: selected ? C.ink : C.cream,
              color: selected ? C.cream : C.ink,
              border: `1px solid ${selected ? C.ink : C.terra + '33'}`,
              borderRadius: 14, padding: '14px 10px 12px',
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8,
              transition: 'all .25s',
              animation: `bookFadeUp .4s cubic-bezier(.2,.7,.3,1) ${i * 0.04}s both`,
            }}>
              {/* simple silhouette */}
              <svg width={36} height={l.viz} viewBox={`0 0 36 ${l.viz}`} style={{ display: 'block' }}>
                <ellipse cx={18} cy={11} rx={9} ry={9} fill={selected ? C.sun : C.terra + '88'} />
                <path d={`M 9 18 Q 4 ${l.viz - 6} 6 ${l.viz - 2} L 30 ${l.viz - 2} Q 32 ${l.viz - 6} 27 18 Z`} fill={selected ? C.sun : C.terra + '88'} />
              </svg>
              <span style={{ fontFamily: FF.display, fontStyle: 'italic', fontSize: 14 }}>{l.label}</span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

// ── STEP 3 (new): Vibe / inspiration tags ──────────────────────────────
function VibeStep({ data, toggleVibe, C, FF }) {
  return (
    <div>
      <h3 style={{ fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 56, lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink }}>
        Pick the words<br/>
        <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>that feel right.</span>
      </h3>
      <p style={{ fontFamily: FF.body, fontSize: 14, color: C.ink + 'aa', marginTop: 12, marginBottom: 24 }}>
        Tap as many as resonate — three or four is plenty.
      </p>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
        {VIBES.map((v, i) => {
          const selected = data.vibes.includes(v);
          return (
            <button key={v} onClick={() => toggleVibe(v)} style={{
              cursor: 'pointer',
              background: selected ? C.terra : 'transparent',
              color: selected ? C.cream : C.ink,
              border: `1px solid ${selected ? C.terra : C.terra + '55'}`,
              borderRadius: 999, padding: '12px 20px',
              fontFamily: FF.display, fontStyle: 'italic', fontSize: 17,
              transition: 'all .25s',
              transform: selected ? 'scale(1.04)' : 'scale(1)',
              boxShadow: selected ? `0 8px 20px -8px ${C.terra}aa` : 'none',
              animation: `bookFadeUp .4s cubic-bezier(.2,.7,.3,1) ${i * 0.025}s both`,
            }}>
              {selected && <span style={{ marginRight: 6 }}>✓</span>}
              {v}
            </button>
          );
        })}
      </div>

      <div style={{
        marginTop: 32, padding: '16px 20px', background: C.cream + '99',
        borderRadius: 16, border: `1px dashed ${C.terra}44`,
        fontFamily: FF.body, fontSize: 12, color: C.ink + 'aa',
      }}>
        <span style={{ fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', color: C.rust, marginRight: 8 }}>Selected</span>
        {data.vibes.length === 0 ? <em style={{ opacity: 0.5 }}>nothing yet</em> : data.vibes.join(' · ')}
      </div>
    </div>
  );
}

// ── STEP 4 (new): Photo upload ─────────────────────────────────────────
function PhotoStep({ data, update, C, FF }) {
  const inputRef = useRef(null);
  const [drag, setDrag] = useState(false);

  const handleFiles = (files) => {
    const arr = Array.from(files).slice(0, 8);
    const previews = arr.map(f => ({
      name: f.name,
      url: URL.createObjectURL(f),
    }));
    update('photos', [...data.photos, ...previews].slice(0, 8));
  };

  return (
    <div>
      <h3 style={{ fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 56, lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink }}>
        Show me your<br/>
        <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>inspiration.</span>
      </h3>
      <p style={{ fontFamily: FF.body, fontSize: 14, color: C.ink + 'aa', marginTop: 12, marginBottom: 24 }}>
        Pinterest screenshots, saved Instagrams, anything that’s caught your eye. Optional — you can also send these later.
      </p>

      <div
        onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
        onDragLeave={() => setDrag(false)}
        onDrop={(e) => { e.preventDefault(); setDrag(false); handleFiles(e.dataTransfer.files); }}
        onClick={() => inputRef.current?.click()}
        style={{
          background: drag ? C.sun + '66' : C.cream + '99',
          border: `2px dashed ${drag ? C.terra : C.terra + '55'}`,
          borderRadius: 24, padding: '40px 20px',
          textAlign: 'center', cursor: 'pointer',
          transition: 'all .25s',
          transform: drag ? 'scale(1.01)' : 'scale(1)',
        }}>
        <div style={{ fontSize: 36, marginBottom: 12 }}>📎</div>
        <div style={{ fontFamily: FF.display, fontSize: 22, fontStyle: 'italic' }}>
          Drop reference photos here
        </div>
        <div style={{ fontFamily: FF.body, fontSize: 13, color: C.ink + 'aa', marginTop: 6 }}>
          or click to browse · up to 8 images
        </div>
        <input
          ref={inputRef} type="file" multiple accept="image/*"
          style={{ display: 'none' }}
          onChange={(e) => handleFiles(e.target.files)}
        />
      </div>

      {data.photos.length > 0 && (
        <div style={{ marginTop: 20, display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10 }}>
          {data.photos.map((p, i) => (
            <div key={i} style={{
              position: 'relative', aspectRatio: '1', borderRadius: 12, overflow: 'hidden',
              animation: `bookFadeUp .35s cubic-bezier(.2,.7,.3,1) ${i * 0.05}s both`,
              boxShadow: `0 6px 16px -8px ${C.ink}55`,
            }}>
              <img src={p.url} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
              <button onClick={(e) => { e.stopPropagation(); update('photos', data.photos.filter((_, j) => j !== i)); }} style={{
                position: 'absolute', top: 6, right: 6,
                width: 24, height: 24, borderRadius: '50%', background: C.ink, color: C.cream,
                border: 'none', cursor: 'pointer', fontSize: 14, lineHeight: 1,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>×</button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── STEP 5 (new): Contact ─────────────────────────────────────────────
function ContactStep({ data, update, C, FF }) {
  return (
    <div>
      <h3 style={{ fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 56, lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink }}>
        Almost there<br/>
        <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>—</span>
      </h3>
      <p style={{ fontFamily: FF.body, fontSize: 14, color: C.ink + 'aa', marginTop: 12, marginBottom: 28 }}>
        I’ll be in touch within 24 hours to confirm a time.
      </p>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
        <FloatField label="Your name" value={data.name} onChange={v => update('name', v)} C={C} FF={FF} />
        <FloatField label="Phone number" value={data.phone} onChange={v => update('phone', v)} C={C} FF={FF} />
      </div>
      <div style={{ marginTop: 16 }}>
        <FloatField label="Anything you want me to know? (optional)" value={data.note} onChange={v => update('note', v)} C={C} FF={FF} multiline />
      </div>
    </div>
  );
}

function FloatField({ label, value, onChange, C, FF, multiline }) {
  const [focus, setFocus] = useState(false);
  const active = focus || value.length > 0;
  const Tag = multiline ? 'textarea' : 'input';
  return (
    <label style={{ position: 'relative', display: 'block', cursor: 'text' }}>
      <span style={{
        position: 'absolute', left: 18,
        top: active ? 8 : (multiline ? 22 : 18),
        fontSize: active ? 10 : 14,
        fontFamily: active ? FF.mono : FF.body,
        letterSpacing: active ? '0.18em' : '0em',
        textTransform: active ? 'uppercase' : 'none',
        color: active ? C.terra : C.ink + '88',
        transition: 'all .25s cubic-bezier(.2,.7,.3,1)',
        pointerEvents: 'none',
      }}>{label}</span>
      <Tag
        value={value}
        onChange={(e) => onChange(e.target.value)}
        onFocus={() => setFocus(true)}
        onBlur={() => setFocus(false)}
        rows={multiline ? 3 : undefined}
        style={{
          width: '100%', background: C.cream,
          border: `1px solid ${focus ? C.terra : C.terra + '33'}`,
          borderRadius: multiline ? 16 : 999,
          padding: multiline ? '24px 18px 12px' : '22px 18px 8px',
          fontFamily: FF.display, fontSize: 18, color: C.ink,
          outline: 'none', resize: multiline ? 'none' : undefined,
          transition: 'border-color .25s, background .25s',
        }}
      />
    </label>
  );
}

// ── STEP 5 (new): How did you find me? ────────────────────────────────
const SOURCE_OPTIONS = [
  { id: 'instagram',  label: 'Instagram',                   sub: '@harleeshowalter',           glyph: '◐' },
  { id: 'pinterest',  label: 'Pinterest',                    sub: 'Pinned somewhere lovely',     glyph: '◓' },
  { id: 'google',     label: 'Google search',                sub: 'Old-fashioned and reliable',  glyph: '◑' },
  { id: 'ai',         label: 'An AI assistant',              sub: 'ChatGPT, Claude, Gemini…',    glyph: '✦' },
  { id: 'referral',   label: 'A friend told me',             sub: 'Word of mouth — the best.',   glyph: '✿' },
  { id: 'walked-by',  label: 'I walked by the studio',       sub: 'Hi, neighbor.',               glyph: '◌' },
  { id: 'other',      label: 'Somewhere else',               sub: 'Tell me where ↓',             glyph: '∗' },
];

const AI_OPTIONS = ['ChatGPT', 'Claude', 'Gemini', 'Perplexity', 'Copilot', 'Other / not sure'];

function SourceStep({ data, update, C, FF }) {
  const isAI = data.source === 'ai';
  const isOther = data.source === 'other';
  return (
    <div>
      <h3 style={{ fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 56, lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink }}>
        Last little thing —<br/>
        <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>how&rsquo;d you find me?</span>
      </h3>
      <p style={{ fontFamily: FF.body, fontSize: 14, color: C.ink + 'aa', marginTop: 12, marginBottom: 28 }}>
        Just curious. It helps me know where to spend my afternoons.
      </p>

      <div style={{
        display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 12,
      }}>
        {SOURCE_OPTIONS.map((opt, i) => {
          const selected = data.source === opt.id;
          return (
            <button key={opt.id} onClick={() => update('source', opt.id)} style={{
              cursor: 'pointer', textAlign: 'left',
              padding: '18px 20px', borderRadius: 16,
              background: selected ? C.terra : C.cream,
              color: selected ? C.cream : C.ink,
              border: `1px solid ${selected ? C.terra : C.terra + '33'}`,
              boxShadow: selected ? `0 12px 28px -12px ${C.terra}99` : 'none',
              transition: 'all .25s',
              transform: selected ? 'translateY(-2px)' : 'translateY(0)',
              animation: `bookFadeUp .4s cubic-bezier(.2,.7,.3,1) ${i * 0.04}s both`,
              display: 'flex', alignItems: 'center', gap: 14,
            }}>
              <span style={{
                width: 36, height: 36, flexShrink: 0,
                borderRadius: '50%',
                background: selected ? C.cream + '22' : C.sand,
                color: selected ? C.cream : C.terra,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: FF.display, fontSize: 18,
              }}>{opt.glyph}</span>
              <div>
                <div style={{
                  fontFamily: FF.display, fontStyle: 'italic',
                  fontSize: 19, fontWeight: 500, lineHeight: 1.1,
                }}>{opt.label}</div>
                <div style={{
                  fontFamily: FF.body, fontSize: 12, marginTop: 4,
                  opacity: selected ? 0.8 : 0.55, lineHeight: 1.3,
                }}>{opt.sub}</div>
              </div>
            </button>
          );
        })}
      </div>

      {/* AI follow-up */}
      {isAI && (
        <div style={{
          marginTop: 24, padding: '20px 22px',
          background: `linear-gradient(135deg, ${C.sand} 0%, ${C.cream} 100%)`,
          borderRadius: 18, border: `1px solid ${C.terra}44`,
          animation: 'bookFadeUp .35s cubic-bezier(.2,.7,.3,1)',
        }}>
          <div style={{
            fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.22em',
            textTransform: 'uppercase', color: C.rust, marginBottom: 12,
          }}>
            ✦ Which one?
          </div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {AI_OPTIONS.map((ai, i) => {
              const picked = data.sourceDetail === ai;
              return (
                <button key={ai} onClick={() => update('sourceDetail', ai)} style={{
                  cursor: 'pointer',
                  background: picked ? C.ink : 'transparent',
                  color: picked ? C.cream : C.ink,
                  border: `1px solid ${picked ? C.ink : C.ink + '44'}`,
                  borderRadius: 999, padding: '10px 18px',
                  fontFamily: FF.display, fontStyle: 'italic', fontSize: 15,
                  fontWeight: picked ? 600 : 400,
                  transition: 'all .2s',
                }}>
                  {picked && <span style={{ marginRight: 6 }}>✓</span>}
                  {ai}
                </button>
              );
            })}
          </div>
          <div style={{
            marginTop: 16, fontFamily: FF.display, fontStyle: 'italic',
            fontSize: 14, color: C.ink + 'aa', lineHeight: 1.5,
          }}>
            That&rsquo;s genuinely fascinating — thank you for telling me.
          </div>
        </div>
      )}

      {/* Other text input */}
      {isOther && (
        <div style={{
          marginTop: 24, padding: '20px 22px',
          background: C.cream, borderRadius: 18,
          border: `1px solid ${C.terra}44`,
          animation: 'bookFadeUp .35s cubic-bezier(.2,.7,.3,1)',
        }}>
          <div style={{
            fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.22em',
            textTransform: 'uppercase', color: C.rust, marginBottom: 12,
          }}>Where?</div>
          <input
            type="text"
            value={data.sourceDetail}
            onChange={(e) => update('sourceDetail', e.target.value)}
            placeholder="A magazine, a podcast, a billboard…"
            style={{
              width: '100%', padding: '12px 16px',
              fontFamily: FF.display, fontStyle: 'italic', fontSize: 17,
              background: 'transparent', border: 'none',
              borderBottom: `1px solid ${C.terra}55`,
              color: C.ink, outline: 'none',
            }}
          />
        </div>
      )}
    </div>
  );
}

// ── STEP 7 (new): Done ────────────────────────────────────────────────
function DoneStep({ data, C, FF }) {
  const service = SERVICE_OPTIONS.find(s => s.id === data.service);
  const cur = LENGTHS.find(l => l.id === data.currentLength);
  const goal = LENGTHS.find(l => l.id === data.desiredLength);

  return (
    <div style={{ textAlign: 'center', paddingTop: 40, paddingBottom: 40 }}>
      <div style={{
        width: 96, height: 96, borderRadius: '50%', background: C.terra,
        margin: '0 auto 32px', display: 'flex', alignItems: 'center', justifyContent: 'center',
        animation: 'pop .6s cubic-bezier(.2,.9,.3,1.4) both',
        boxShadow: `0 24px 60px -16px ${C.terra}aa`,
      }}>
        <svg width="44" height="44" viewBox="0 0 44 44" style={{ overflow: 'visible' }}>
          <path d="M 8 22 L 19 33 L 36 12" fill="none" stroke={C.cream} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"
            strokeDasharray="60" strokeDashoffset="60"
            style={{ animation: 'draw .5s ease-out .35s forwards' }} />
        </svg>
      </div>

      <h3 style={{
        fontFamily: FF.display, fontStyle: 'italic', fontWeight: 300, fontSize: 56,
        lineHeight: 1, margin: 0, letterSpacing: '-0.03em', color: C.ink,
        animation: 'bookFadeUp .6s cubic-bezier(.2,.7,.3,1) .5s both',
      }}>
        You’re in,{' '}
        <span style={{ fontWeight: 600, fontStyle: 'normal', color: C.terra }}>
          {data.name.split(' ')[0] || 'friend'}.
        </span>
      </h3>

      <p style={{
        fontFamily: FF.display, fontSize: 17, fontStyle: 'italic',
        color: C.ink + 'cc', marginTop: 14, marginBottom: 28,
        animation: 'bookFadeUp .6s cubic-bezier(.2,.7,.3,1) .65s both',
      }}>
        I’ll text you within 24 hours.
      </p>

      <div style={{
        maxWidth: 500, margin: '0 auto',
        background: C.cream, borderRadius: 20, padding: '24px 28px',
        textAlign: 'left', border: `1px solid ${C.terra}33`,
        animation: 'bookFadeUp .6s cubic-bezier(.2,.7,.3,1) .8s both',
        position: 'relative',
      }}>
        <div style={{ position: 'absolute', left: -8, top: '50%', transform: 'translateY(-50%)', width: 16, height: 16, borderRadius: '50%', background: C.sun }} />
        <div style={{ position: 'absolute', right: -8, top: '50%', transform: 'translateY(-50%)', width: 16, height: 16, borderRadius: '50%', background: C.sun }} />

        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', paddingBottom: 12, borderBottom: `1px dashed ${C.terra}66` }}>
          <span style={{ fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.24em', textTransform: 'uppercase', color: C.rust }}>Request №</span>
          <span style={{ fontFamily: FF.mono, fontSize: 11, letterSpacing: '0.16em', color: C.ink }}>HS-{Math.floor(Math.random()*9000+1000)}</span>
        </div>

        <Row k="Service" v={service ? service.label : '—'} C={C} FF={FF} />
        <Row k="Length" v={`${cur?.label || '—'} → ${goal?.label || '—'}`} C={C} FF={FF} />
        {data.vibes.length > 0 && <Row k="Vibe" v={data.vibes.join(', ')} C={C} FF={FF} multiline />}
        <Row k="Photos" v={data.photos.length === 0 ? 'None — will text later' : `${data.photos.length} attached`} C={C} FF={FF} />
        <Row k="Contact" v={data.phone} C={C} FF={FF} />

        <div style={{
          marginTop: 12, paddingTop: 12, borderTop: `1px dashed ${C.terra}66`,
          fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', textAlign: 'center', color: C.rust,
        }}>
          Desert Lounge Salon · 75 N 100 E · St. George, UT
        </div>
      </div>
    </div>
  );
}

function Row({ k, v, C, FF, multiline }) {
  return (
    <div style={{
      display: 'flex', justifyContent: 'space-between', alignItems: multiline ? 'flex-start' : 'baseline',
      padding: '10px 0', borderBottom: `1px solid ${C.terra}22`,
    }}>
      <span style={{ fontFamily: FF.mono, fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', color: C.rust, flexShrink: 0, marginRight: 16 }}>{k}</span>
      <span style={{ fontFamily: FF.display, fontSize: 15, fontStyle: 'italic', color: C.ink, textAlign: 'right' }}>{v}</span>
    </div>
  );
}

window.BookingFlow = BookingFlow;
