// bottleneck-audit.jsx — multi-step interactive audit modal
// Entry: clicking any .js-audit button opens it.
//   data-preselect="receptionist,proposals" → skip to wedge step, those pre-checked
//   data-source="..."                       → tracks entry point (for copy)
//
// Steps:
//   0  Symptoms picker
//   1  Wedge picker (with live price + Ads/CRM suggestion)
//   2  Contact form
//   3  Success
//
// Persisted via window.BottleneckAudit.

(function () {
  const { useState, useEffect, useRef, useMemo } = React;

  // Translation helper — falls back to provided string if i18n not loaded.
  function T(key, fallback, vars) {
    if (typeof window.t === 'function') {
      const v = window.t(key, vars);
      if (v !== key) return v;
    }
    if (vars && typeof fallback === 'string') {
      let s = fallback;
      for (const k in vars) s = s.replace('{' + k + '}', vars[k]);
      return s;
    }
    return fallback;
  }

  // ────────────────────────────────────────────────────────────────────
  // Data
  // ────────────────────────────────────────────────────────────────────
  const WEDGES = [
    { id: 'receptionist', name: 'AI Receptionist',       price: 290, bottle: 'Missed calls' },
    { id: 'proposals',    name: 'Proposals & contracts', price: 190, bottle: '3-day quote' },
    { id: 'seo',          name: 'SEO + AEO website',     price: 390, bottle: '$0 organic' },
    { id: 'gbp',          name: 'Google Business Profile', price: 190, bottle: 'Off the map' },
    { id: 'ads',          name: 'Ads + funnel',          price: 490, bottle: 'Cash burn', spendNote: '+ spend' },
    { id: 'crm',          name: 'Industry CRM',          price: 190, bottle: '5-tool chaos' },
    { id: 'comms',        name: 'Comms center',          price: 190, bottle: 'Inbox chaos' },
    { id: 'social',       name: 'Social autopilot',      price: 290, bottle: 'Silent online' },
    { id: 'app',          name: 'Branded crew app',      price: 390, bottle: 'Crew chaos' },
  ];
  const FULL_STACK_PRICE = 1290;

  const SYMPTOMS = [
    { id: 'voicemail',  label: 'Calls go to voicemail',        wedges: ['receptionist'] },
    { id: 'slow_quote', label: 'Quotes take 3 days to send',   wedges: ['proposals'] },
    { id: 'invisible',  label: 'Invisible on Google / ChatGPT', wedges: ['seo'] },
    { id: 'no_map',     label: 'Not in the local 3-pack',      wedges: ['gbp'] },
    { id: 'burn_ads',   label: 'Ads burn cash, no funnel',     wedges: ['ads', 'crm'] },
    { id: 'five_tools', label: 'My business runs on 5 tools',  wedges: ['crm'] },
    { id: 'inbox',      label: 'Inbox is a war zone',          wedges: ['comms'] },
    { id: 'silent',     label: 'Silent on social',             wedges: ['social'] },
    { id: 'crew',       label: 'Crews are disorganized',       wedges: ['app'] },
  ];

  // Bundle discount logic:
  //   1 wedge:        no discount
  //   2 wedges:       save $40
  //   3 wedges:       save $80
  //   4 wedges:       save $140
  //   5-6 wedges:     save $260
  //   7-8 wedges:     save $580
  //   9 (full stack): flat $1,290 (save vs sum)
  function priceFor(selected) {
    const ids = [...selected];
    const sum = ids.reduce((acc, id) => acc + (WEDGES.find(w => w.id === id)?.price || 0), 0);
    if (ids.length === 0) return { sum, discount: 0, total: 0, isStack: false };
    if (ids.length === 9) return { sum, discount: sum - FULL_STACK_PRICE, total: FULL_STACK_PRICE, isStack: true };
    const tier =
      ids.length >= 7 ? 580 :
      ids.length >= 5 ? 260 :
      ids.length >= 4 ? 140 :
      ids.length >= 3 ? 80 :
      ids.length >= 2 ? 40 : 0;
    const discount = Math.min(tier, sum * 0.5);
    return { sum, discount, total: sum - discount, isStack: false };
  }

  // ────────────────────────────────────────────────────────────────────
  // Inline styles (scoped to the modal)
  // ────────────────────────────────────────────────────────────────────
  const auditStyles = {
    overlay: {
      position: 'fixed', inset: 0,
      background: 'rgba(27,24,20,0.6)',
      backdropFilter: 'blur(10px)',
      WebkitBackdropFilter: 'blur(10px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: '24px',
      zIndex: 1000,
      animation: 'auditFadeIn 0.2s ease',
    },
    modal: {
      background: 'var(--cream)',
      borderRadius: 24,
      width: '100%', maxWidth: 760,
      maxHeight: 'calc(100vh - 48px)',
      overflow: 'hidden',
      display: 'flex', flexDirection: 'column',
      boxShadow: '0 40px 100px rgba(0,0,0,0.4)',
      border: '1px solid var(--border)',
      animation: 'auditPopIn 0.32s cubic-bezier(0.2, 0.8, 0.3, 1)',
    },
    head: {
      padding: '24px 32px 18px',
      background: 'var(--ink)',
      color: 'var(--cream-3)',
      borderBottom: '1px solid rgba(255,255,255,0.08)',
      position: 'relative',
    },
    eyebrow: {
      fontSize: 11,
      fontWeight: 800,
      letterSpacing: '0.12em',
      textTransform: 'uppercase',
      color: 'var(--gold-soft)',
      marginBottom: 8,
    },
    title: {
      fontFamily: 'var(--serif)',
      fontStyle: 'italic',
      fontSize: 34,
      margin: 0,
      lineHeight: 1.05,
      letterSpacing: '-0.01em',
    },
    titleEm: { fontStyle: 'normal', color: 'var(--gold)' },
    close: {
      position: 'absolute',
      top: 18, right: 18,
      width: 32, height: 32,
      borderRadius: '50%',
      background: 'rgba(255,255,255,0.08)',
      color: 'var(--cream-3)',
      display: 'grid', placeItems: 'center',
      cursor: 'pointer',
      fontSize: 16,
      border: '1px solid rgba(255,255,255,0.12)',
      transition: 'background 0.15s',
    },
    steps: {
      display: 'flex',
      gap: 6,
      marginTop: 16,
    },
    stepDot: {
      flex: 1, height: 3, borderRadius: 2,
      background: 'rgba(255,255,255,0.12)',
      transition: 'background 0.3s',
    },
    stepDotActive: { background: 'var(--gold)' },
    body: {
      padding: '28px 32px 32px',
      overflowY: 'auto',
      flex: 1,
    },
    footBar: {
      padding: '16px 32px',
      borderTop: '1px solid var(--border)',
      background: '#fff',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      gap: 14,
    },
    footPrice: {
      display: 'flex', flexDirection: 'column',
      lineHeight: 1.1,
    },
    footTotalLabel: {
      fontSize: 11, fontWeight: 700,
      letterSpacing: '0.08em', textTransform: 'uppercase',
      color: 'var(--ink-3)',
    },
    footTotal: {
      fontFamily: 'var(--serif)', fontStyle: 'italic',
      fontSize: 26, color: 'var(--ink)',
      letterSpacing: '-0.005em',
    },
    footStrike: {
      textDecoration: 'line-through',
      color: 'var(--ink-3)',
      fontSize: 14, marginRight: 8, fontStyle: 'normal',
    },
    footActions: { display: 'flex', gap: 10 },
    btnGhost: {
      background: 'transparent',
      color: 'var(--ink-2)',
      border: '1px solid var(--border)',
      borderRadius: 999,
      padding: '12px 20px',
      fontSize: 14, fontWeight: 600,
      cursor: 'pointer',
      fontFamily: 'inherit',
      transition: 'all 0.15s',
    },
    btnPrimary: {
      background: 'var(--ink)',
      color: 'var(--cream-3)',
      border: 'none',
      borderRadius: 999,
      padding: '12px 22px',
      fontSize: 14, fontWeight: 700,
      cursor: 'pointer',
      fontFamily: 'inherit',
      transition: 'all 0.15s',
    },
    btnPrimaryDisabled: {
      background: 'var(--border)',
      color: 'var(--ink-3)',
      cursor: 'not-allowed',
    },
  };

  // ────────────────────────────────────────────────────────────────────
  // Sub-components
  // ────────────────────────────────────────────────────────────────────
  function StepDots({ step, totalSteps }) {
    const labels = ['Symptoms', 'Wedges', 'Details', 'Done'];
    return (
      <div style={{ display: 'flex', gap: 4, marginTop: 18, alignItems: 'center' }}>
        {Array.from({ length: totalSteps }).map((_, i) => {
          const done = i < step || step === totalSteps - 1;
          const active = i === step;
          return (
            <React.Fragment key={i}>
              <div style={{
                display: 'flex', alignItems: 'center', gap: 6,
                opacity: done || active ? 1 : 0.45,
                transition: 'opacity 0.3s',
              }}>
                <div style={{
                  width: 18, height: 18, borderRadius: '50%',
                  background: done ? 'var(--gold)' : active ? 'transparent' : 'transparent',
                  border: `1.5px solid ${done || active ? 'var(--gold)' : 'rgba(255,255,255,0.25)'}`,
                  color: done ? 'var(--ink)' : active ? 'var(--gold)' : 'rgba(255,255,255,0.4)',
                  display: 'grid', placeItems: 'center',
                  fontSize: 10, fontWeight: 800,
                  transition: 'all 0.3s',
                }}>
                  {done ? '✓' : i + 1}
                </div>
                <span style={{
                  fontSize: 11, fontWeight: 700,
                  letterSpacing: '0.04em',
                  color: done || active ? 'var(--gold-soft)' : 'rgba(255,255,255,0.4)',
                  textTransform: 'uppercase',
                }}>{labels[i]}</span>
              </div>
              {i < totalSteps - 1 && (
                <div style={{
                  flex: 1, height: 1.5,
                  background: i < step ? 'var(--gold)' : 'rgba(255,255,255,0.12)',
                  transition: 'background 0.4s',
                  margin: '0 4px',
                }}/>
              )}
            </React.Fragment>
          );
        })}
      </div>
    );
  }

  function SymptomStep({ selected, onToggle }) {
    return (
      <div>
        <p style={{ margin: '0 0 24px', color: 'var(--ink-2)', fontSize: 16, lineHeight: 1.5 }}>
          Tap every symptom you're feeling right now. We'll recommend the wedges that fix them.
        </p>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
          {SYMPTOMS.map(s => {
            const on = selected.has(s.id);
            return (
              <button
                key={s.id}
                type="button"
                onClick={() => onToggle(s.id)}
                style={{
                  background: on ? 'var(--ink)' : '#fff',
                  color: on ? 'var(--cream-3)' : 'var(--ink)',
                  border: `1px solid ${on ? 'var(--ink)' : 'var(--border)'}`,
                  borderRadius: 999,
                  padding: '12px 18px',
                  fontSize: 14.5, fontWeight: 500,
                  cursor: 'pointer',
                  fontFamily: 'inherit',
                  transition: 'all 0.15s',
                  display: 'inline-flex', alignItems: 'center', gap: 8,
                }}
              >
                <span style={{
                  width: 16, height: 16, borderRadius: '50%',
                  background: on ? 'var(--gold)' : 'var(--red-bg)',
                  color: on ? 'var(--ink)' : 'var(--red)',
                  display: 'inline-grid', placeItems: 'center',
                  fontSize: 10, fontWeight: 800,
                }}>{on ? '✓' : '!'}</span>
                {s.label}
              </button>
            );
          })}
        </div>
      </div>
    );
  }

  function WedgeStep({ selectedWedges, onToggle, symptoms, price }) {
    // Smart suggestion: if Ads is on but CRM isn't, prompt
    const showAdsCrmHint = selectedWedges.has('ads') && !selectedWedges.has('crm');

    const recommended = useMemo(() => {
      const ids = new Set();
      SYMPTOMS.forEach(s => {
        if (symptoms.has(s.id)) s.wedges.forEach(w => ids.add(w));
      });
      return ids;
    }, [symptoms]);

    return (
      <div>
        <p style={{ margin: '0 0 20px', color: 'var(--ink-2)', fontSize: 16, lineHeight: 1.5 }}>
          {symptoms.size > 0
            ? <>Based on what hurts, we'd start with <strong style={{color:'var(--ink)'}}>{recommended.size} wedge{recommended.size === 1 ? '' : 's'}</strong>. Add or remove anything.</>
            : <>Pick the wedges you want. Bundle discount kicks in at 2+.</>}
        </p>

        <div style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
          gap: 10,
        }}>
          {WEDGES.map(w => {
            const on = selectedWedges.has(w.id);
            const isRec = recommended.has(w.id) && !on;
            return (
              <button
                key={w.id}
                type="button"
                onClick={() => onToggle(w.id)}
                style={{
                  position: 'relative',
                  textAlign: 'left',
                  background: on ? 'var(--gold-bg)' : '#fff',
                  border: `1.5px solid ${on ? 'var(--gold)' : isRec ? 'var(--gold-soft)' : 'var(--border)'}`,
                  borderRadius: 14,
                  padding: '14px 14px 12px',
                  cursor: 'pointer',
                  fontFamily: 'inherit',
                  transition: 'all 0.15s',
                  outline: 'none',
                }}
              >
                <div style={{
                  display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start',
                  gap: 8, marginBottom: 8,
                }}>
                  <div style={{
                    width: 22, height: 22, borderRadius: 6,
                    background: on ? 'var(--gold)' : '#fff',
                    border: `1.5px solid ${on ? 'var(--gold)' : 'var(--border)'}`,
                    display: 'grid', placeItems: 'center',
                    color: 'var(--ink)',
                    fontSize: 12, fontWeight: 800,
                    flexShrink: 0,
                  }}>{on ? '✓' : ''}</div>
                  {isRec && (
                    <span style={{
                      fontSize: 9.5, fontWeight: 800, letterSpacing: '0.08em',
                      textTransform: 'uppercase', color: 'var(--gold-dk)',
                    }}>★ Recommended</span>
                  )}
                </div>
                <div style={{
                  fontFamily: 'var(--serif)', fontStyle: 'italic',
                  fontSize: 18, lineHeight: 1.15, color: 'var(--ink)',
                  marginBottom: 6,
                }}>{w.name}</div>
                <div style={{
                  fontSize: 11, color: 'var(--ink-3)', fontWeight: 600,
                  letterSpacing: '0.04em', textTransform: 'uppercase',
                  marginBottom: 8,
                }}>{w.bottle}</div>
                <div style={{
                  fontSize: 13, color: 'var(--ink-2)',
                  fontFamily: 'var(--sans)',
                }}>
                  <span style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 18, color: 'var(--ink)' }}>
                    ${w.price}
                  </span>
                  <span style={{ marginLeft: 4 }}>/ mo {w.spendNote || ''}</span>
                </div>
              </button>
            );
          })}
        </div>

        {showAdsCrmHint && (
          <div style={{
            marginTop: 16,
            display: 'flex', alignItems: 'center', gap: 12,
            background: 'var(--ink)', color: 'var(--cream-3)',
            padding: '14px 18px', borderRadius: 14,
            border: '1px solid var(--gold)',
          }}>
            <div style={{
              width: 30, height: 30, borderRadius: '50%',
              background: 'var(--gold)', color: 'var(--ink)',
              display: 'grid', placeItems: 'center',
              fontFamily: 'var(--serif)', fontStyle: 'italic',
              fontSize: 16, flexShrink: 0,
            }}>!</div>
            <div style={{ fontSize: 13, lineHeight: 1.45 }}>
              <strong style={{ color: 'var(--gold-soft)' }}>Heads up:</strong> Ads without a CRM burns money faster. Want to add the CRM ($190 / mo) so leads have somewhere to land?
              <button
                type="button"
                onClick={() => onToggle('crm')}
                style={{
                  marginLeft: 8,
                  background: 'var(--gold)', color: 'var(--ink)',
                  border: 'none', borderRadius: 999,
                  padding: '4px 12px', fontSize: 12, fontWeight: 700,
                  cursor: 'pointer', fontFamily: 'inherit',
                }}
              >+ Add CRM</button>
            </div>
          </div>
        )}

        {price.isStack && (
          <div style={{
            marginTop: 16,
            background: 'var(--gold-bg)',
            border: '1px solid var(--gold)',
            borderRadius: 14,
            padding: '14px 18px',
            fontSize: 14, color: 'var(--ink)',
            fontWeight: 600,
            display: 'flex', alignItems: 'center', gap: 10,
          }}>
            <span style={{
              fontFamily: 'var(--serif)', fontStyle: 'italic',
              fontSize: 22, color: 'var(--gold-dk)',
            }}>★</span>
            <span>You picked the <strong style={{color:'var(--gold-dk)'}}>full stack</strong>. Bundle price: <strong>${FULL_STACK_PRICE.toLocaleString()}/mo</strong> — saves you ${price.discount.toLocaleString()}/mo.</span>
          </div>
        )}
      </div>
    );
  }

  // Shared input styles (no nested components → no remount on each keystroke)
  const inputBase = {
    width: '100%',
    background: '#fff',
    border: '1px solid var(--border)',
    borderRadius: 10,
    padding: '12px 14px',
    fontSize: 15, color: 'var(--ink)',
    fontFamily: 'var(--sans)',
    transition: 'border-color 0.15s, box-shadow 0.15s',
    boxSizing: 'border-box',
    outline: 'none',
  };
  const labelBase = {
    display: 'block',
    fontSize: 11, fontWeight: 700, letterSpacing: '0.06em',
    textTransform: 'uppercase',
    color: 'var(--ink-2)',
    marginBottom: 6,
  };
  function inputStyle(err) {
    return {
      ...inputBase,
      border: `1px solid ${err ? 'var(--red)' : 'var(--border)'}`,
    };
  }
  function labelStyle(err) {
    return { ...labelBase, color: err ? 'var(--red)' : 'var(--ink-2)' };
  }
  function errMsg(text) {
    if (!text) return null;
    return <div style={{ fontSize: 11.5, color: 'var(--red)', fontWeight: 600, marginTop: 4 }}>{text}</div>;
  }

  // Generate next 3 weekday slots (10am + 2pm each)
  function nextSlots() {
    const slots = [];
    const now = new Date();
    let d = new Date(now);
    while (slots.length < 6) {
      d.setDate(d.getDate() + 1);
      const dow = d.getDay();
      if (dow === 0 || dow === 6) continue; // skip weekends
      slots.push({ id: d.toISOString().slice(0,10) + '-10', date: new Date(d), hour: 10, label: '10:00 AM' });
      slots.push({ id: d.toISOString().slice(0,10) + '-14', date: new Date(d), hour: 14, label: '2:00 PM' });
    }
    return slots.slice(0, 6);
  }
  function formatSlotLabel(slot) {
    if (!slot) return null;
    const d = slot.date;
    const days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
    const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    return `${days[d.getDay()]} ${months[d.getMonth()]} ${d.getDate()} at ${slot.label}`;
  }

  function ContactStep({ form, errors, onChange }) {
    const slots = React.useMemo(() => nextSlots(), []);
    return (
      <div>
        <p style={{ margin: '0 0 16px', color: 'var(--ink-2)', fontSize: 16, lineHeight: 1.5 }}>
          Pick a slot for your free 30-min audit call (optional), then drop your details below.
        </p>
        <div style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(3, 1fr)',
          gap: 8,
          marginBottom: 22,
        }}>
          {slots.map(s => {
            const on = form.slotId === s.id;
            return (
              <button
                key={s.id}
                type="button"
                onClick={() => onChange('slotId', on ? '' : s.id)}
                style={{
                  background: on ? 'var(--ink)' : '#fff',
                  color: on ? 'var(--cream-3)' : 'var(--ink)',
                  border: `1.5px solid ${on ? 'var(--ink)' : 'var(--border)'}`,
                  borderRadius: 10,
                  padding: '10px 12px',
                  fontSize: 13,
                  fontWeight: 600,
                  cursor: 'pointer',
                  fontFamily: 'inherit',
                  textAlign: 'left',
                  transition: 'all 0.15s',
                  outline: 'none',
                }}
              >
                <div style={{
                  fontSize: 10.5, fontWeight: 800, letterSpacing: '0.06em',
                  textTransform: 'uppercase',
                  color: on ? 'var(--gold)' : 'var(--ink-3)',
                  marginBottom: 3,
                }}>{['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][s.date.getDay()]} {['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'][s.date.getMonth()]} {s.date.getDate()}</div>
                <div style={{ fontSize: 14, fontWeight: 700 }}>{s.label}</div>
              </button>
            );
          })}
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
          <div style={{ marginBottom: 14 }}>
            <label style={labelStyle(errors.name)}>Your name</label>
            <input
              type="text"
              value={form.name || ''}
              onChange={(e) => onChange('name', e.target.value)}
              placeholder="Marco Salazar"
              autoComplete="name"
              style={inputStyle(errors.name)}
              onFocus={(e) => e.currentTarget.style.borderColor = 'var(--gold)'}
              onBlur={(e) => e.currentTarget.style.borderColor = errors.name ? 'var(--red)' : 'var(--border)'}
            />
            {errMsg(errors.name)}
          </div>
          <div style={{ marginBottom: 14 }}>
            <label style={labelStyle(errors.business)}>Business</label>
            <input
              type="text"
              value={form.business || ''}
              onChange={(e) => onChange('business', e.target.value)}
              placeholder="Bayshore Plumbing"
              autoComplete="organization"
              style={inputStyle(errors.business)}
              onFocus={(e) => e.currentTarget.style.borderColor = 'var(--gold)'}
              onBlur={(e) => e.currentTarget.style.borderColor = errors.business ? 'var(--red)' : 'var(--border)'}
            />
            {errMsg(errors.business)}
          </div>
        </div>
        <div style={{ marginBottom: 14 }}>
          <label style={labelStyle(errors.email)}>Email</label>
          <input
            type="email"
            value={form.email || ''}
            onChange={(e) => onChange('email', e.target.value)}
            placeholder="you@yourbusiness.com"
            autoComplete="email"
            style={inputStyle(errors.email)}
            onFocus={(e) => e.currentTarget.style.borderColor = 'var(--gold)'}
            onBlur={(e) => e.currentTarget.style.borderColor = errors.email ? 'var(--red)' : 'var(--border)'}
          />
          {errMsg(errors.email)}
        </div>
        <div style={{ marginBottom: 14 }}>
          <label style={labelStyle(errors.phone)}>Phone (for the audit text)</label>
          <input
            type="tel"
            value={form.phone || ''}
            onChange={(e) => onChange('phone', e.target.value)}
            placeholder="(555) 123-4567"
            autoComplete="tel"
            inputMode="tel"
            style={inputStyle(errors.phone)}
            onFocus={(e) => e.currentTarget.style.borderColor = 'var(--gold)'}
            onBlur={(e) => e.currentTarget.style.borderColor = errors.phone ? 'var(--red)' : 'var(--border)'}
          />
          {errMsg(errors.phone)}
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
          <div style={{ marginBottom: 14 }}>
            <label style={labelStyle(errors.trade)}>Trade</label>
            <select
              value={form.trade || ''}
              onChange={(e) => onChange('trade', e.target.value)}
              style={{ ...inputStyle(errors.trade), cursor: 'pointer' }}
            >
              <option value="">Pick one…</option>
              <option value="plumbing">Plumbing</option>
              <option value="hvac">HVAC</option>
              <option value="roofing">Roofing</option>
              <option value="electrical">Electrical</option>
              <option value="landscaping">Landscaping</option>
              <option value="pest">Pest control</option>
              <option value="other">Other</option>
            </select>
            {errMsg(errors.trade)}
          </div>
          <div style={{ marginBottom: 14 }}>
            <label style={labelStyle(errors.revenue)}>Monthly revenue</label>
            <select
              value={form.revenue || ''}
              onChange={(e) => onChange('revenue', e.target.value)}
              style={{ ...inputStyle(errors.revenue), cursor: 'pointer' }}
            >
              <option value="">Pick a range…</option>
              <option value="under-40">Under $40k / mo</option>
              <option value="40-100">$40k – $100k / mo</option>
              <option value="100-300">$100k – $300k / mo</option>
              <option value="300-plus">$300k+ / mo</option>
            </select>
            {errMsg(errors.revenue)}
          </div>
        </div>
        <div style={{ marginTop: 8, fontSize: 12, color: 'var(--ink-3)', lineHeight: 1.5 }}>
          No credit card. No spam. We answer humans, not bots.
        </div>
      </div>
    );
  }

  function SuccessStep({ name, selectedWedges, price, slotLabel }) {
    const list = WEDGES.filter(w => selectedWedges.has(w.id));
    const confettiBits = [
      { c: 'var(--gold)',    x: '-80px', y: '120px', r: '320deg', d: '0s'   },
      { c: 'var(--gold-dk)', x: '70px',  y: '110px', r: '-240deg',d: '0.05s' },
      { c: '#1F8A5B',        x: '-40px', y: '140px', r: '180deg', d: '0.1s'  },
      { c: '#C84B3C',        x: '50px',  y: '130px', r: '-300deg',d: '0.15s' },
      { c: 'var(--gold)',    x: '-110px',y: '90px',  r: '420deg', d: '0.2s'  },
      { c: 'var(--gold-dk)', x: '100px', y: '95px',  r: '-360deg',d: '0.25s' },
      { c: '#1F8A5B',        x: '-20px', y: '150px', r: '240deg', d: '0.3s'  },
      { c: 'var(--gold)',    x: '30px',  y: '160px', r: '-180deg',d: '0.35s' },
    ];
    return (
      <div style={{ textAlign: 'center', padding: '8px 0 4px', position: 'relative' }}>
        {/* Confetti */}
        <div style={{
          position: 'absolute', top: 24, left: '50%',
          transform: 'translateX(-50%)',
          width: 1, height: 1, pointerEvents: 'none',
        }}>
          {confettiBits.map((b, i) => (
            <span key={i} style={{
              position: 'absolute', left: 0, top: 0,
              width: 8, height: 8,
              background: b.c,
              borderRadius: i % 2 ? '50%' : '2px',
              animation: `auditConfetti 1.2s ${b.d} cubic-bezier(0.2, 0.6, 0.3, 1) forwards`,
              '--cx': b.x, '--cy': b.y, '--cr': b.r,
            }}/>
          ))}
        </div>
        <div style={{
          width: 72, height: 72, borderRadius: '50%',
          background: 'var(--gold-bg)', color: 'var(--gold-dk)',
          display: 'grid', placeItems: 'center',
          margin: '0 auto 22px',
          fontSize: 36, fontWeight: 800,
          border: '3px solid var(--gold-soft)',
          animation: 'auditPopIn 0.5s cubic-bezier(0.2, 0.8, 0.3, 1), auditPulse 1.6s 0.5s ease-out',
          position: 'relative', zIndex: 2,
        }}>✓</div>
        <h3 style={{
          fontFamily: 'var(--serif)', fontStyle: 'italic',
          fontSize: 36, lineHeight: 1.05, margin: '0 0 10px',
          letterSpacing: '-0.01em',
        }}>
          You're in, <span style={{ color: 'var(--gold-dk)' }}>{(name || 'friend').split(' ')[0]}</span>.
        </h3>
        <p style={{
          fontSize: 16, color: 'var(--ink-2)', lineHeight: 1.5,
          margin: '0 auto 24px', maxWidth: 460,
        }}>
          {slotLabel
            ? <>We'll see you on <strong style={{color:'var(--ink)'}}>{slotLabel}</strong>. Marco will text you a confirmation within 2 business hours.</>
            : <>Marco from FastFix will text you within 2 business hours to schedule your audit. Here's what's queued up:</>}
        </p>

        {list.length > 0 && (
          <div style={{
            background: '#fff',
            border: '2px solid var(--gold)',
            borderRadius: 16,
            padding: 20,
            margin: '0 auto 22px',
            maxWidth: 460,
            textAlign: 'left',
          }}>
            <div style={{
              fontSize: 11, fontWeight: 800, letterSpacing: '0.08em',
              textTransform: 'uppercase', color: 'var(--gold-dk)',
              marginBottom: 12,
            }}>Your selection</div>
            {list.map(w => (
              <div key={w.id} style={{
                display: 'flex', justifyContent: 'space-between',
                padding: '6px 0',
                fontSize: 14, color: 'var(--ink-2)',
                borderBottom: '1px solid var(--border-soft)',
              }}>
                <span>{w.name}</span>
                <span style={{ color: 'var(--ink)', fontWeight: 600 }}>${w.price}</span>
              </div>
            ))}
            <div style={{
              marginTop: 14, paddingTop: 12,
              borderTop: '2px solid var(--ink)',
              display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
            }}>
              <span style={{
                fontSize: 11, fontWeight: 800, letterSpacing: '0.08em',
                textTransform: 'uppercase', color: 'var(--ink-3)',
              }}>{price.isStack ? 'Full stack' : list.length >= 2 ? 'Bundle' : 'Total'}</span>
              <span>
                {price.discount > 0 && (
                  <span style={{
                    textDecoration: 'line-through',
                    color: 'var(--ink-3)', fontSize: 14, marginRight: 8,
                  }}>${price.sum.toLocaleString()}</span>
                )}
                <span style={{
                  fontFamily: 'var(--serif)', fontStyle: 'italic',
                  fontSize: 28, color: 'var(--ink)',
                }}>${price.total.toLocaleString()}</span>
                <span style={{ color: 'var(--ink-3)', fontSize: 13, marginLeft: 4 }}>/ mo</span>
              </span>
            </div>
            {price.discount > 0 && (
              <div style={{
                marginTop: 10, padding: '6px 12px',
                background: 'var(--gold-bg)', color: 'var(--gold-dk)',
                borderRadius: 999, display: 'inline-block',
                fontSize: 12, fontWeight: 800, letterSpacing: '0.05em',
              }}>
                ★ Saving ${price.discount.toLocaleString()} / mo with bundle
              </div>
            )}
          </div>
        )}

        <div style={{
          fontSize: 13, color: 'var(--ink-3)',
          background: 'var(--cream-2)',
          padding: '12px 18px',
          borderRadius: 12,
          maxWidth: 460, margin: '0 auto',
          textAlign: 'left',
          lineHeight: 1.55,
        }}>
          <div style={{ fontWeight: 700, color: 'var(--ink-2)', marginBottom: 6 }}>What happens next</div>
          <div>1. Marco texts you within 2 business hours.</div>
          <div>2. 30-min audit call — we rank your top 3 blockers.</div>
          <div>3. Your first wedge live in 7–14 days. No contract.</div>
        </div>
      </div>
    );
  }

  // ────────────────────────────────────────────────────────────────────
  // Main component
  // ────────────────────────────────────────────────────────────────────
  function BottleneckAudit() {
    const [isOpen, setIsOpen] = useState(false);
    const [step, setStep] = useState(0);          // 0=symptoms, 1=wedges, 2=contact, 3=success
    const [symptoms, setSymptoms] = useState(() => new Set());
    const [wedges, setWedges] = useState(() => new Set());
    const [form, setForm] = useState({});
    const [errors, setErrors] = useState({});
    const [source, setSource] = useState('hero');
    // Re-render on language change
    const [, setLangVer] = useState(0);
    useEffect(() => {
      const onLang = () => setLangVer(v => v + 1);
      window.addEventListener('langchange', onLang);
      return () => window.removeEventListener('langchange', onLang);
    }, []);

    const price = useMemo(() => priceFor(wedges), [wedges]);

    // ─── Open / close ────────────────────────────────────────
    const open = (opts = {}) => {
      const { preselect, source: src } = opts;
      // Reset
      setSymptoms(new Set());
      setForm({});
      setErrors({});
      setSource(src || 'hero');

      if (preselect && preselect.length > 0) {
        setWedges(new Set(preselect));
        setStep(1); // skip symptoms — they already chose
      } else {
        setWedges(new Set());
        setStep(0);
      }
      setIsOpen(true);
      document.body.style.overflow = 'hidden';
    };
    const close = () => {
      setIsOpen(false);
      document.body.style.overflow = '';
    };

    // ─── Listen for .js-audit clicks ─────────────────────────
    useEffect(() => {
      const handler = (e) => {
        const btn = e.target.closest('.js-audit');
        if (!btn) return;
        e.preventDefault();
        const preselectAttr = btn.getAttribute('data-preselect');
        const srcAttr = btn.getAttribute('data-source');
        const preselect = preselectAttr ? preselectAttr.split(',').map(s => s.trim()).filter(Boolean) : [];
        open({ preselect, source: srcAttr });
      };
      document.addEventListener('click', handler);
      const escHandler = (e) => {
        if (e.key === 'Escape') close();
      };
      document.addEventListener('keydown', escHandler);
      return () => {
        document.removeEventListener('click', handler);
        document.removeEventListener('keydown', escHandler);
      };
    }, []);

    // ─── Toggle helpers ──────────────────────────────────────
    const toggleSymptom = (id) => {
      const next = new Set(symptoms);
      next.has(id) ? next.delete(id) : next.add(id);
      setSymptoms(next);
    };
    const toggleWedge = (id) => {
      const next = new Set(wedges);
      next.has(id) ? next.delete(id) : next.add(id);
      setWedges(next);
    };
    const handleChange = (name, value) => {
      let v = value;
      if (name === 'phone') {
        const digits = value.replace(/\D/g, '').slice(0, 10);
        v = digits.length > 6 ? `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`
          : digits.length > 3 ? `(${digits.slice(0,3)}) ${digits.slice(3)}`
          : digits.length > 0 ? `(${digits}` : '';
      }
      setForm({ ...form, [name]: v });
      if (errors[name]) {
        const next = { ...errors };
        delete next[name];
        setErrors(next);
      }
    };

    // ─── Validation ──────────────────────────────────────────
    const validateContact = () => {
      const errs = {};
      if (!form.name || form.name.trim().length < 2) errs.name = 'Tell us who you are.';
      if (!form.business || form.business.trim().length < 2) errs.business = 'We need your business name.';
      if (!form.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) errs.email = 'Use a real email.';
      if (!form.phone || form.phone.replace(/\D/g, '').length < 10) errs.phone = 'A real phone, please.';
      if (!form.trade) errs.trade = 'Pick your trade.';
      if (!form.revenue) errs.revenue = 'Pick a range.';
      setErrors(errs);
      return Object.keys(errs).length === 0;
    };

    // ─── Step config ─────────────────────────────────────────
    const STEPS = [
      {
        eyebrow: T('m.step', 'Step', {}) + ' 1 ' + T('m.of', 'of') + ' 4 · ' + T('m.s0.label', 'Symptoms'),
        title: <span dangerouslySetInnerHTML={{__html: T('m.s0.title', "Where does it <em style='font-style:normal;color:#A88431'>hurt</em>?")}}/>,
        canNext: symptoms.size > 0,
        nextLabel: symptoms.size > 0
          ? T('m.s0.cta', 'See {n} recommended →', { n: recommendedFor(symptoms).size })
          : T('m.s0.cta.zero', 'Pick at least one →'),
        onNext: () => {
          setWedges(recommendedFor(symptoms));
          setStep(1);
        },
        skip: {
          label: T('m.s0.skip', 'Skip — show me all 9 wedges'),
          onClick: () => { setWedges(new Set()); setStep(1); },
        },
      },
      {
        eyebrow: T('m.step', 'Step', {}) + ' 2 ' + T('m.of', 'of') + ' 4 · ' + T('m.s1.label', 'Wedges'),
        title: <span dangerouslySetInnerHTML={{__html: T('m.s1.title', "Your <em style='font-style:normal;color:#A88431'>stack</em>.")}}/>,
        canNext: wedges.size > 0,
        nextLabel: wedges.size > 0
          ? T('m.s1.cta', 'Continue with {n} wedge{s} →', { n: wedges.size, s: wedges.size === 1 ? '' : 's' })
          : T('m.s1.cta.zero', 'Pick at least one →'),
        onNext: () => setStep(2),
      },
      {
        eyebrow: T('m.step', 'Step', {}) + ' 3 ' + T('m.of', 'of') + ' 4 · ' + T('m.s2.label', 'Details'),
        title: <span dangerouslySetInnerHTML={{__html: T('m.s2.title', "Quick <em style='font-style:normal;color:#A88431'>details</em>.")}}/>,
        canNext: true,
        nextLabel: T('m.s2.cta', 'Request my audit →'),
        onNext: () => {
          if (validateContact()) {
            setStep(3);
          }
        },
      },
      {
        eyebrow: T('m.s3.label', 'Done'),
        title: <span dangerouslySetInnerHTML={{__html: T('m.s3.title', "Audit <em style='font-style:normal;color:#A88431'>requested</em>.")}}/>,
        canNext: false,
      },
    ];

    const cur = STEPS[step];

    if (!isOpen) return null;

    return (
      <>
        <style>{`
          @keyframes auditFadeIn { from { opacity: 0; } to { opacity: 1; } }
          @keyframes auditPopIn {
            from { opacity: 0; transform: translateY(20px) scale(0.97); }
            to   { opacity: 1; transform: translateY(0) scale(1); }
          }
          @keyframes auditSlideIn {
            from { opacity: 0; transform: translateX(16px); }
            to   { opacity: 1; transform: translateX(0); }
          }
          @keyframes auditConfetti {
            0%   { transform: translate(0, 0) rotate(0) scale(0.6); opacity: 0; }
            10%  { opacity: 1; }
            100% { transform: translate(var(--cx, 0), var(--cy, 120px)) rotate(var(--cr, 360deg)) scale(1); opacity: 0; }
          }
          @keyframes auditPulse {
            0%   { box-shadow: 0 0 0 0 rgba(199,162,74,0.6); }
            70%  { box-shadow: 0 0 0 14px rgba(199,162,74,0); }
            100% { box-shadow: 0 0 0 0 rgba(199,162,74,0); }
          }
        `}</style>
        <div
          style={auditStyles.overlay}
          onClick={(e) => { if (e.target === e.currentTarget) close(); }}
        >
          <div style={auditStyles.modal} role="dialog" aria-modal="true">
            <div style={auditStyles.head}>
              <div style={auditStyles.eyebrow}>{cur.eyebrow}</div>
              <h2 style={auditStyles.title}>{cur.title}</h2>
              <button
                style={auditStyles.close}
                onClick={close}
                aria-label="Close"
                onMouseOver={(e) => e.currentTarget.style.background = 'rgba(255,255,255,0.18)'}
                onMouseOut={(e) => e.currentTarget.style.background = 'rgba(255,255,255,0.08)'}
              >✕</button>
              <StepDots step={step} totalSteps={4} />
            </div>

            <div style={auditStyles.body}>
              <div key={step} style={{ animation: 'auditSlideIn 0.36s cubic-bezier(0.2, 0.8, 0.3, 1)' }}>
                {step === 0 && <SymptomStep selected={symptoms} onToggle={toggleSymptom} />}
                {step === 1 && <WedgeStep selectedWedges={wedges} onToggle={toggleWedge} symptoms={symptoms} price={price} />}
                {step === 2 && <ContactStep form={form} errors={errors} onChange={handleChange} />}
                {step === 3 && <SuccessStep name={form.name} selectedWedges={wedges} price={price} slotLabel={formatSlotLabel(nextSlots().find(s => s.id === form.slotId))} />}
              </div>
            </div>

            {step < 3 && (
              <div style={auditStyles.footBar}>
                <div style={auditStyles.footPrice}>
                  {step >= 1 && wedges.size > 0 ? (
                    <>
                      <span style={auditStyles.footTotalLabel}>
                        {price.isStack ? 'Full stack' : wedges.size >= 2 ? `Bundle · ${wedges.size} wedges` : '1 wedge'}
                      </span>
                      <span style={auditStyles.footTotal}>
                        {price.discount > 0 && (
                          <span style={auditStyles.footStrike}>${price.sum.toLocaleString()}</span>
                        )}
                        ${price.total.toLocaleString()}
                        <span style={{ fontSize: 13, color: 'var(--ink-3)', marginLeft: 6, fontStyle: 'normal' }}>/ mo</span>
                      </span>
                    </>
                  ) : (
                    <>
                      <span style={auditStyles.footTotalLabel}>14 days free</span>
                      <span style={{ fontSize: 14, color: 'var(--ink-2)' }}>No card. Cancel anytime.</span>
                    </>
                  )}
                </div>
                <div style={auditStyles.footActions}>
                  {step > 0 && (
                    <button
                      style={auditStyles.btnGhost}
                      onClick={() => setStep(step - 1)}
                    >← Back</button>
                  )}
                  {step === 0 && cur.skip && (
                    <button
                      style={auditStyles.btnGhost}
                      onClick={cur.skip.onClick}
                    >{cur.skip.label}</button>
                  )}
                  <button
                    style={{
                      ...auditStyles.btnPrimary,
                      ...(cur.canNext ? {} : auditStyles.btnPrimaryDisabled),
                    }}
                    disabled={!cur.canNext}
                    onClick={cur.onNext}
                  >{cur.nextLabel}</button>
                </div>
              </div>
            )}
            {step === 3 && (
              <div style={auditStyles.footBar}>
                <div style={{
                  fontSize: 13, color: 'var(--ink-3)',
                }}>You'll hear from us within 2 business hours.</div>
                <button
                  style={auditStyles.btnPrimary}
                  onClick={close}
                >Got it</button>
              </div>
            )}
          </div>
        </div>
      </>
    );
  }

  // Helper used at top level
  function recommendedFor(symptoms) {
    const ids = new Set();
    SYMPTOMS.forEach(s => {
      if (symptoms.has(s.id)) s.wedges.forEach(w => ids.add(w));
    });
    return ids;
  }

  // Export
  Object.assign(window, { BottleneckAudit });
})();
