// ============================
// LELUSA — Customizer + Quote Pages
// customizer-quote.jsx
// ============================

// ─── Customizer Preview SVG ─────────────────────────────────────
function CustomizerPreview({ deco, selections }) {
  const { t } = window.ReactI18next.useTranslation();
  const mainColor = React.useMemo(() => {
    const opt = (deco.options || []).find(o => o.type === 'color');
    if (!opt) return '#D4A8B8';
    const selId = selections[opt.id];
    const choice = (opt.choices || []).find(c => c.id === selId) || opt.choices?.[0];
    return choice?.color || '#D4A8B8';
  }, [deco, selections]);

  const uid = `prev-${deco.id}`;
  const c2 = '#A8BAB8';
  return (
    <div style={{ position: 'relative', width: '100%', borderRadius: '24px', overflow: 'hidden', border: '1px solid var(--border)', background: 'var(--card)' }}>
      <svg viewBox="0 0 560 460" xmlns="http://www.w3.org/2000/svg" style={{ width: '100%', display: 'block' }}>
        <defs>
          <pattern id={uid} x="0" y="0" width="30" height="30" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
            <rect width="30" height="30" fill="#FAF8F5" />
            <rect width="3" height="30" fill={`${mainColor}15`} />
          </pattern>
          <filter id={`shadow-${deco.id}`}>
            <feDropShadow dx="0" dy="4" stdDeviation="8" floodColor={mainColor} floodOpacity="0.18" />
          </filter>
        </defs>
        <rect width="560" height="460" fill={`url(#${uid})`} />
        {/* Soft glow */}
        <ellipse cx="280" cy="230" rx="190" ry="200" fill={mainColor} opacity="0.08" />
        {/* Backdrop arch */}
        <rect x="158" y="60" width="244" height="310" rx="122" fill={mainColor} opacity="0.13" filter={`url(#shadow-${deco.id})`} />
        <rect x="170" y="72" width="220" height="286" rx="110" fill="none" stroke={mainColor} strokeWidth="1.5" opacity="0.25" />
        {/* Balloon arch — 9 balloons */}
        {[
          [168,288,20,mainColor,0.82],[162,255,18,c2,0.72],[163,222,17,mainColor,0.75],
          [172,192,19,c2,0.72],[190,168,20,mainColor,0.78],[210,152,17,c2,0.70],
          [280,140,22,mainColor,0.88],
          [350,152,17,c2,0.70],[370,168,20,mainColor,0.78],
          [388,192,19,c2,0.72],[397,222,17,mainColor,0.75],[398,255,18,c2,0.72],[392,288,20,mainColor,0.82],
        ].map(([cx,cy,r,fill,op],i) => (
          <circle key={i} cx={cx} cy={cy} r={r} fill={fill} opacity={op} />
        ))}
        {/* String lines */}
        {[[168,308],[392,308],[280,162]].map(([cx,cy],i) => (
          <line key={i} x1={cx} y1={cy} x2={cx + (i===2?0:i===0?8:-8)} y2={cy + 28}
            stroke={mainColor} strokeWidth="1" opacity="0.3" />
        ))}
        {/* Table */}
        <rect x="120" y="355" width="320" height="18" rx="7" fill={mainColor} opacity="0.55" />
        <rect x="158" y="373" width="7" height="52" rx="3.5" fill={mainColor} opacity="0.3" />
        <rect x="395" y="373" width="7" height="52" rx="3.5" fill={mainColor} opacity="0.3" />
        {/* Table cloth suggestion */}
        <rect x="120" y="355" width="320" height="6" rx="3" fill={c2} opacity="0.4" />
        {/* Centerpiece flower */}
        {[0,60,120,180,240,300].map((deg,i) => {
          const rad = deg * Math.PI / 180;
          return <circle key={'petal'+i} cx={280+Math.cos(rad)*17} cy={240+Math.sin(rad)*17} r={13} fill={mainColor} opacity="0.45" />;
        })}
        <circle cx="280" cy="240" r="11" fill={mainColor} opacity="0.78" />
        <circle cx="280" cy="240" r="5" fill="#fff" opacity="0.5" />
        {/* Floating leaves suggestion */}
        <ellipse cx="140" cy="310" rx="16" ry="8" fill={c2} opacity="0.4" transform="rotate(-30,140,310)" />
        <ellipse cx="420" cy="315" rx="16" ry="8" fill={c2} opacity="0.35" transform="rotate(30,420,315)" />
        {/* Small detail dots */}
        {[[108,200,5],[452,220,4],[95,340,5],[468,350,4],[200,100,4],[360,100,4]].map(([x,y,r],i) => (
          <circle key={'dot'+i} cx={x} cy={y} r={r} fill={i%2===0?mainColor:c2} opacity="0.3" />
        ))}
        {/* Label */}
        <text x="280" y="438" textAnchor="middle" fill={mainColor} opacity="0.55"
          fontSize="13" fontFamily="'DM Sans', sans-serif" fontWeight="500">{deco.name}</text>
      </svg>
      {/* Color indicator */}
      <div style={{ position: 'absolute', bottom: '12px', right: '12px', display: 'flex', alignItems: 'center', gap: '6px', background: 'rgba(255,255,255,0.9)', borderRadius: '999px', padding: '5px 12px', backdropFilter: 'blur(6px)', border: '1px solid var(--border)' }}>
        <div style={{ width: '12px', height: '12px', borderRadius: '50%', background: mainColor, border: '1.5px solid rgba(0,0,0,0.08)' }} />
        <span style={{ fontSize: '11px', color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif" }}>{t('customizer_preview')}</span>
      </div>
    </div>
  );
}

// ─── Customizer Page ─────────────────────────────────────────────
function CustomizerPage() {
  const { t } = window.ReactI18next.useTranslation();
  const { navigate, pageData } = React.useContext(window.AppContext);
  const { designs, catalogCategories } = window.LelusaStore.usePublicBusinessData();
  const categoryLabelBySlug = Object.fromEntries(window.LelusaStore.getCatalogCategories(catalogCategories, 'design').map(item => [item.slug, item.name]));
  const sourceDesigns = designs || [];
  const deco = sourceDesigns.find(d => String(d.id) === String(pageData.decoId)) || sourceDesigns[0];
  const isMobileCust = window.LelusaGestures.useIsMobile();
  const [optionsOpen, setOptionsOpen] = React.useState(false);

  if (!deco) {
    return (
      <div className="lel-has-bottomnav" style={{ minHeight: '100vh', background: 'var(--bg)' }}>
        <NavBar />
        <div style={{ maxWidth: '720px', margin: '0 auto', padding: '80px 24px', textAlign: 'center' }}>
          <h1 style={{ margin: '0 0 10px', fontFamily: "'Cormorant Garamond', serif", fontSize: '32px', color: 'var(--text)' }}>{t('customizer_no_designs_title')}</h1>
          <p style={{ margin: '0 0 24px', color: 'var(--muted)', lineHeight: 1.6 }}>{t('customizer_no_designs_desc')}</p>
          <Btn onClick={() => navigate('quote-form')}>{t('customizer_request_custom')}</Btn>
        </div>
        <Footer />
      </div>
    );
  }

  // Build initial selections
  const initSelections = React.useMemo(() => {
    const sel = {};
    (deco.options || []).forEach(opt => { if (opt.choices?.[0]) sel[opt.id] = opt.choices[0].id; });
    return sel;
  }, [deco.id]);

  const [selections, setSelections] = React.useState(initSelections);
  const [extras, setExtras] = React.useState([]);
  const [animateTotal, setAnimateTotal] = React.useState(false);

  const total = React.useMemo(() => {
    let t = deco.price;
    (deco.options || []).forEach(opt => {
      const selId = selections[opt.id];
      const choice = (opt.choices || []).find(c => c.id === selId);
      if (choice) t += choice.price || 0;
    });
    extras.forEach(eid => {
      const ex = (deco.extras || []).find(e => e.id === eid);
      if (ex) t += ex.price;
    });
    return t;
  }, [deco, selections, extras]);

  // Animate total on change
  const prevTotal = React.useRef(total);
  React.useEffect(() => {
    if (prevTotal.current !== total) {
      setAnimateTotal(true);
      const t = setTimeout(() => setAnimateTotal(false), 400);
      prevTotal.current = total;
      return () => clearTimeout(t);
    }
  }, [total]);

  const handleSelect = (optId, choiceId) => setSelections(s => ({ ...s, [optId]: choiceId }));
  const toggleExtra = (eid) => setExtras(prev => prev.includes(eid) ? prev.filter(e => e !== eid) : [...prev, eid]);

  const handleQuote = () => {
    navigate('quote-form', { decoId: deco.id, selections, extras, total });
  };

  const optionsPanel = (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
      {/* Options */}
      {(deco.options || []).map(opt => (
        <div key={opt.id} style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '20px', padding: '22px' }}>
          <h3 style={{ margin: '0 0 14px', fontSize: '15px', fontWeight: 600, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>
            {opt.name}
          </h3>
          {opt.type === 'color' ? (
            <div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
              {(opt.choices || []).map(ch => {
                const active = selections[opt.id] === ch.id;
                return (
                  <button key={ch.id} onClick={() => handleSelect(opt.id, ch.id)}
                    title={ch.label}
                    style={{
                      display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '6px',
                      background: 'none', border: 'none', cursor: 'pointer', padding: '4px',
                    }}>
                    <div style={{
                      width: '44px', height: '44px', borderRadius: '50%', background: ch.color,
                      border: active ? `3px solid var(--primary)` : '3px solid transparent',
                      boxShadow: active ? '0 0 0 2px var(--bg), 0 0 0 4px var(--primary)' : '0 2px 8px rgba(58,42,32,0.12)',
                      transition: 'all 0.2s',
                    }} />
                    <span style={{ fontSize: '11px', color: active ? 'var(--primary)' : 'var(--muted)', fontWeight: active ? 600 : 400, fontFamily: "'DM Sans', sans-serif", lineHeight: 1.2, textAlign: 'center', maxWidth: '52px' }}>{ch.label}</span>
                    {ch.price > 0 && <span style={{ fontSize: '10px', color: 'var(--muted)' }}>+${ch.price}</span>}
                  </button>
                );
              })}
            </div>
          ) : (
            <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
              {(opt.choices || []).map(ch => {
                const active = selections[opt.id] === ch.id;
                return (
                  <label key={ch.id} style={{ display: 'flex', alignItems: 'center', gap: '12px', cursor: 'pointer', padding: '12px 14px', borderRadius: '12px', background: active ? 'var(--accent-light)' : 'transparent', border: `1.5px solid ${active ? 'var(--primary)' : 'var(--border)'}`, transition: 'all 0.15s' }}>
                    <input type="radio" name={opt.id} checked={active} onChange={() => handleSelect(opt.id, ch.id)} style={{ accentColor: 'var(--primary)' }} />
                    <span style={{ flex: 1, fontSize: '14px', color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", fontWeight: active ? 500 : 400 }}>{ch.label}</span>
                    {ch.price > 0 ? (
                      <span style={{ fontSize: '13px', color: 'var(--primary)', fontWeight: 600 }}>+${ch.price}</span>
                    ) : (
                      <span style={{ fontSize: '12px', color: 'var(--muted)' }}>{t('customizer_included')}</span>
                    )}
                  </label>
                );
              })}
            </div>
          )}
        </div>
      ))}
      {/* Extras */}
      <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '20px', padding: '22px' }}>
        <h3 style={{ margin: '0 0 14px', fontSize: '15px', fontWeight: 600, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif'" }}>{t('customizer_optional_extras')}</h3>
        <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
          {(deco.extras || []).map(ex => {
            const active = extras.includes(ex.id);
            return (
              <label key={ex.id} onClick={() => toggleExtra(ex.id)}
                style={{ display: 'flex', alignItems: 'center', gap: '12px', cursor: 'pointer', padding: '12px 14px', borderRadius: '12px', background: active ? 'var(--accent-light)' : 'transparent', border: `1.5px solid ${active ? 'var(--primary)' : 'var(--border)'}`, transition: 'all 0.2s' }}>
                <div style={{ width: '20px', height: '20px', borderRadius: '6px', border: `2px solid ${active ? 'var(--primary)' : 'var(--border)'}`, background: active ? 'var(--primary)' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, transition: 'all 0.15s' }}>
                  {active && <Icon name="check" size={11} color="#fff" />}
                </div>
                <span style={{ flex: 1, fontSize: '14px', color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", fontWeight: active ? 500 : 400 }}>{ex.name}</span>
                <span style={{ fontSize: '14px', color: 'var(--primary)', fontWeight: 600 }}>+${ex.price}</span>
              </label>
            );
          })}
        </div>
      </div>
      {/* Total + CTA */}
      <div style={{ background: 'var(--text)', borderRadius: '20px', padding: '24px', position: 'sticky', bottom: '20px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '6px' }}>
          <span style={{ fontSize: '14px', color: 'rgba(250,240,232,0.65)', fontFamily: "'DM Sans', sans-serif" }}>{t('customizer_total_estimated')}</span>
          <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '36px', fontWeight: 700, color: 'var(--bg)', transition: 'transform 0.3s, color 0.3s', transform: animateTotal ? 'scale(1.08)' : 'scale(1)', }}>
            ${total.toLocaleString()}
          </div>
        </div>
        <p style={{ margin: '0 0 18px', fontSize: '11px', color: 'rgba(250,240,232,0.45)', lineHeight: 1.5 }}>
          {t('customizer_price_note')}
        </p>
        <Btn variant="secondary" onClick={handleQuote} style={{ width: '100%', background: 'var(--bg)', color: 'var(--text)', justifyContent: 'center' }}>
          <Icon name="fileText" size={16} color="var(--text)" />
          {t('customizer_request_quote')}
        </Btn>
      </div>
    </div>
  );

  return (
    <div className="lel-has-bottomnav" style={{ minHeight: '100vh', background: 'var(--bg)' }}>
      <NavBar />
      <div style={{ maxWidth: '1200px', margin: '0 auto', padding: '36px 24px 80px' }}>
        {/* Header */}
        <div style={{ marginBottom: '32px' }}>
          <button onClick={() => navigate('deco-detail', { decoId: deco.id })}
            style={{ background: 'none', border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '6px', color: 'var(--muted)', fontSize: '13px', fontFamily: "'DM Sans', sans-serif", marginBottom: '12px', padding: 0 }}>
            <Icon name="arrowLeft" size={14} color="var(--muted)" /> {t('customizer_back')}
          </button>
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', flexWrap: 'wrap', gap: '12px' }}>
            <div>
              <Badge>{categoryLabelBySlug[deco.category] || CATEGORY_LABELS[deco.category] || deco.category}</Badge>
              <h1 style={{ margin: '10px 0 0', fontFamily: "'Cormorant Garamond', serif", fontSize: '32px', fontWeight: 600, color: 'var(--text)' }}>{t('customizer_personalize', { name: deco.name })}</h1>
            </div>
          </div>
        </div>
        {/* Main two-column layout */}
        <div style={{ display: 'grid', gridTemplateColumns: '1.1fr 1fr', gap: '32px', alignItems: 'flex-start' }} className="customizer-grid">
          {/* LEFT: Preview */}
          <div style={{ position: 'sticky', top: '88px' }}>
            <CustomizerPreview deco={deco} selections={selections} />
            <div style={{ marginTop: '14px', display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
              {(deco.includes || []).slice(0, 3).map(inc => (
                <div key={inc} style={{ display: 'flex', alignItems: 'center', gap: '5px', fontSize: '12px', color: 'var(--muted)', background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '999px', padding: '4px 12px' }}>
                  <Icon name="check" size={11} color="var(--primary)" />{inc}
                </div>
              ))}
              {(deco.includes || []).length > 3 && (
                <div style={{ fontSize: '12px', color: 'var(--muted)', background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '999px', padding: '4px 12px' }}>{t('customizer_more_included', { count: deco.includes.length - 3 })}</div>
              )}
            </div>
          </div>
          {/* RIGHT: Options panel */}
          {isMobileCust ? (
            <>
              <button type="button" onClick={() => setOptionsOpen(true)}
                style={{ width: '100%', padding: '14px', borderRadius: '999px', border: 'none', background: 'var(--primary)', color: '#fff', fontFamily: "'DM Sans', sans-serif", fontWeight: 700, fontSize: '15px', cursor: 'pointer', boxShadow: '0 8px 24px rgba(196,137,154,0.35)' }}>
                {t('customizer_customize_options')}
              </button>
              <BottomSheet open={optionsOpen} onClose={() => setOptionsOpen(false)} title={t('customizer_options')}>
                {optionsPanel}
              </BottomSheet>
            </>
          ) : optionsPanel}
        </div>
      </div>
      <Footer />
    </div>
  );
}

// ─── Quote Form Page ─────────────────────────────────────────────
function getQuoteSelectionLabels(deco, selections = {}, extras = []) {
  const selectedOptionLabels = (deco.options || []).map(opt => {
    const choice = (opt.choices || []).find(ch => String(ch.id) === String(selections[opt.id]));
    if (!choice) return null;
    const price = Number(choice.price || 0);
    return `${opt.name}: ${choice.label}${price ? ` (+$${price.toLocaleString()})` : ''}`;
  }).filter(Boolean);

  const selectedExtraLabels = (deco.extras || []).filter(ex => extras.some(id => String(id) === String(ex.id))).map(ex => (
    `${ex.name}${Number(ex.price || 0) ? ` (+$${Number(ex.price || 0).toLocaleString()})` : ''}`
  ));

  return { selectedOptionLabels, selectedExtraLabels };
}

function readBookingDraft(draftId) {
  if (!draftId) return {};
  try {
    const raw = sessionStorage.getItem(`lelusa.bookingDraft.${draftId}`);
    return raw ? JSON.parse(raw) : {};
  } catch (error) {
    return {};
  }
}

function QuoteField({ label, error, children }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>
      <label style={{ fontSize: '13px', fontWeight: 500, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{label}</label>
      {children}
      {error && <span style={{ fontSize: '12px', color: '#E07070' }}>{error}</span>}
    </div>
  );
}

function DragDropImageZone({ images, onChange, max = 5 }) {
  const { t } = window.ReactI18next.useTranslation();
  const fileInputRef = React.useRef(null);
  const [dragging, setDragging] = React.useState(false);
  const [limitMsg, setLimitMsg] = React.useState('');

  const processFiles = (files) => {
    const remaining = max - images.length;
    if (remaining <= 0) {
      setLimitMsg(t('quote_image_max', { max }));
      return;
    }
    const toRead = Array.from(files).slice(0, remaining);
    if (Array.from(files).length > remaining) {
      setLimitMsg(t('quote_image_partial', { count: remaining, max }));
    } else {
      setLimitMsg('');
    }
    toRead.forEach(file => {
      if (!file.type.startsWith('image/')) return;
      const reader = new FileReader();
      reader.onload = () => {
        onChange(prev => [...prev, reader.result]);
      };
      reader.readAsDataURL(file);
    });
  };

  const onDrop = (e) => {
    e.preventDefault();
    setDragging(false);
    processFiles(e.dataTransfer.files);
  };

  const onFileInput = (e) => {
    processFiles(e.target.files);
    e.target.value = '';
  };

  const removeImage = (index) => {
    onChange(prev => prev.filter((_, i) => i !== index));
    setLimitMsg('');
  };

  return (
    <div>
      <div
        onClick={() => fileInputRef.current?.click()}
        onDragOver={e => { e.preventDefault(); setDragging(true); }}
        onDragLeave={() => setDragging(false)}
        onDrop={onDrop}
        style={{
          border: `2px dashed ${dragging ? 'var(--primary)' : 'var(--border)'}`,
          borderRadius: '18px',
          padding: '32px 24px',
          textAlign: 'center',
          cursor: 'pointer',
          background: dragging ? 'var(--accent-light)' : 'var(--bg-soft)',
          transition: 'all 0.2s',
          userSelect: 'none',
        }}
      >
        <div style={{ marginBottom: '10px' }}>
          <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="var(--muted)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" style={{ display: 'block', margin: '0 auto' }}>
            <path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/>
            <polyline points="17 8 12 3 7 8"/>
            <line x1="12" y1="3" x2="12" y2="15"/>
          </svg>
        </div>
        <p style={{ margin: 0, fontSize: '14px', color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", fontWeight: 500 }}>
          {t('quote_image_drag')}
        </p>
        <p style={{ margin: '4px 0 0', fontSize: '12px', color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif" }}>
          {t('quote_image_tap', { count: images.length, max })}
        </p>
        <input
          ref={fileInputRef}
          type="file"
          accept="image/*"
          multiple
          onChange={onFileInput}
          style={{ display: 'none' }}
        />
      </div>
      {limitMsg && (
        <p style={{ margin: '8px 0 0', fontSize: '12px', color: '#C88A1A', fontFamily: "'DM Sans', sans-serif" }}>{limitMsg}</p>
      )}
      {images.length > 0 && (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(80px, 1fr))', gap: '8px', marginTop: '14px' }}>
          {images.map((src, i) => (
            <div key={i} style={{ position: 'relative', borderRadius: '10px', overflow: 'hidden', aspectRatio: '1', background: 'var(--bg-soft)' }}>
              <img src={src} alt={`ref-${i}`} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
              <button
                type="button"
                onClick={(e) => { e.stopPropagation(); removeImage(i); }}
                style={{
                  position: 'absolute', top: '4px', right: '4px',
                  width: '20px', height: '20px', borderRadius: '50%',
                  background: 'rgba(58,42,32,0.7)', border: 'none', cursor: 'pointer',
                  display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff',
                  fontSize: '12px', fontWeight: 700, lineHeight: 1,
                }}
              >✕</button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function DesignSummaryCard({ deco, total, extras, selectionLabels, isMobile }) {
  const { t } = window.ReactI18next.useTranslation();
  const [collapsed, setCollapsed] = React.useState(true);

  if (!isMobile) return null;

  return (
    <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '16px', overflow: 'hidden', marginBottom: '16px' }}>
      <button
        type="button"
        onClick={() => setCollapsed(c => !c)}
        style={{
          width: '100%', background: 'none', border: 'none', cursor: 'pointer',
          display: 'flex', alignItems: 'center', gap: '12px', padding: '12px 16px',
          touchAction: 'manipulation',
        }}
      >
        {deco.image ? (
          <img src={deco.image} alt={deco.name} style={{ width: '56px', height: '44px', objectFit: 'cover', borderRadius: '8px', flexShrink: 0 }} />
        ) : (
          <div style={{ width: '56px', height: '44px', borderRadius: '8px', background: 'var(--accent-light)', flexShrink: 0 }} />
        )}
        <div style={{ flex: 1, textAlign: 'left' }}>
          <div style={{ fontSize: '13px', fontWeight: 600, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>{deco.name}</div>
          <div style={{ fontSize: '12px', color: 'var(--primary)', fontWeight: 700, fontFamily: "'DM Sans', sans-serif" }}>
            {total ? `$${Number(total).toLocaleString()}` : t('quote_summary_to_define')}
          </div>
        </div>
        <svg width="16" height="16" viewBox="0 0 16 16" fill="none" style={{ transition: 'transform 0.2s', transform: collapsed ? 'rotate(0deg)' : 'rotate(180deg)', flexShrink: 0 }}>
          <path d="M4 6L8 10L12 6" stroke="var(--muted)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
      </button>
      {!collapsed && (
        <div style={{ padding: '0 16px 14px', borderTop: '1px solid var(--border)' }}>
          {selectionLabels.selectedOptionLabels.map(label => (
            <div key={label} style={{ fontSize: '12px', color: 'var(--muted)', padding: '6px 0', borderBottom: '1px solid var(--border)', lineHeight: 1.4 }}>{label}</div>
          ))}
          {selectionLabels.selectedExtraLabels.length > 0 && (
            <div style={{ marginTop: '8px', display: 'flex', flexWrap: 'wrap', gap: '6px' }}>
              {selectionLabels.selectedExtraLabels.map(label => (
                <span key={label} style={{ fontSize: '11px', color: 'var(--primary)', background: 'var(--accent-light)', borderRadius: '999px', padding: '3px 8px' }}>{label}</span>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function StepProgressBar({ step, steps }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', marginBottom: '28px' }}>
      {steps.map((label, i) => {
        const n = i + 1;
        const done = n < step;
        const active = n === step;
        return (
          <div key={n} style={{ display: 'contents' }}>
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '6px', flexShrink: 0 }}>
              <div style={{
                width: '32px', height: '32px', borderRadius: '50%',
                background: done || active ? 'var(--primary)' : 'transparent',
                border: `2px solid ${done || active ? 'var(--primary)' : 'var(--border)'}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                transition: 'all 0.2s',
              }}>
                {done
                  ? <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2.5 7L5.5 10L11.5 4" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
                  : <span style={{ fontSize: '12px', fontWeight: 700, color: active ? '#fff' : 'var(--muted)', fontFamily: "'DM Sans', sans-serif" }}>{n}</span>
                }
              </div>
              <span style={{ fontSize: '10px', color: active ? 'var(--primary)' : 'var(--muted)', fontWeight: active ? 700 : 400, fontFamily: "'DM Sans', sans-serif", letterSpacing: '0.03em' }}>
                {label}
              </span>
            </div>
            {i < steps.length - 1 && (
              <div style={{ flex: 1, height: '2px', background: n < step ? 'var(--primary)' : 'var(--border)', margin: '0 6px', marginBottom: '18px', transition: 'background 0.3s' }} />
            )}
          </div>
        );
      })}
    </div>
  );
}

// Elige la clave i18n del texto de confirmación según la preferencia
// de contacto que eligió el cliente.
function contactSentKey(preference) {
  const p = (preference || '').toLowerCase();
  if (p.includes('correo') || p.includes('email')) return 'quote_sent_contact_email';
  if (p.includes('whatsapp')) return 'quote_sent_contact_whatsapp';
  if (p.includes('mensaje') || p.includes('sms')) return 'quote_sent_contact_sms';
  return 'quote_sent_contact_call';
}

function QuoteFormPage() {
  const { t } = window.ReactI18next.useTranslation();
  const { navigate, pageData } = React.useContext(window.AppContext);
  const { designs, desserts, catalogCategories } = window.LelusaStore.usePublicBusinessData();
  const categoryLabelBySlug = Object.fromEntries(window.LelusaStore.getCatalogCategories(catalogCategories, 'design').map(item => [item.slug, item.name]));
  const sourceDesigns = designs || [];
  const hasRequestedDesign = pageData.decoId !== undefined && pageData.decoId !== null && String(pageData.decoId) !== '';
  const savedDeco = hasRequestedDesign ? sourceDesigns.find(d => String(d.id) === String(pageData.decoId)) : null;
  const isDessertsOnly = pageData.dessertsOnly === 'true';
  const deco = savedDeco || {
    id: null,
    name: isDessertsOnly ? t('quote_desserts_only_design_name') : t('quote_custom_design_name'),
    category: isDessertsOnly ? 'postres' : 'personalizado',
    price: 0,
    description: isDessertsOnly ? t('quote_desserts_only_design_desc') : t('quote_custom_design_desc'),
    image: '',
    includes: isDessertsOnly
      ? [t('quote_desserts_only_include_1'), t('quote_desserts_only_include_2'), t('quote_desserts_only_include_3')]
      : [t('quote_custom_include_1'), t('quote_custom_include_2'), t('quote_custom_include_3')],
    tags: [],
    options: [],
    extras: [],
  };
  const isCustomBooking = !savedDeco && !isDessertsOnly;

  const bookingDraft = React.useMemo(() => readBookingDraft(pageData.bookingDraftId), [pageData.bookingDraftId]);
  const decorationTotal = pageData.total || bookingDraft.total || deco.price;
  const extras = pageData.extras || bookingDraft.extras || [];
  const selections = pageData.selections || bookingDraft.selections || {};
  const inspirationImages = Array.isArray(pageData.inspirationImages)
    ? pageData.inspirationImages
    : (Array.isArray(bookingDraft.inspirationImages) ? bookingDraft.inspirationImages : []);
  const selectionLabels = React.useMemo(() => {
    const computed = getQuoteSelectionLabels(deco, selections, extras);
    return {
      selectedOptionLabels: computed.selectedOptionLabels.length ? computed.selectedOptionLabels : (bookingDraft.selectedOptionLabels || []),
      selectedExtraLabels: computed.selectedExtraLabels.length ? computed.selectedExtraLabels : (bookingDraft.selectedExtraLabels || []),
    };
  }, [deco, selections, extras, bookingDraft]);
  const todayInput = new Date().toISOString().slice(0, 10);

  const [form, setForm] = React.useState({
    name: pageData.name || '',
    phone: pageData.phone || '',
    email: pageData.email || '',
    contactPreference: pageData.contactPreference || 'Llamada',
    eventDate: pageData.eventDate || '',
    eventTime: pageData.eventTime || '',
    eventPlace: pageData.eventPlace || '',
    guests: pageData.guests || '',
    setupWindow: '',
    theme: pageData.theme || '',
    colors: pageData.colors || '',
    focus: pageData.focus || '',
    mustHave: pageData.mustHave || '',
    budgetRange: pageData.budgetRange || '',
    customBrief: pageData.customBrief || '',
    wantsDesserts: isDessertsOnly || pageData.wantsDesserts === 'true',
    dessertItems: [],
    dessertCustom: '',
    dessertSetup: '',
    dessertNotes: pageData.dessertNotes || '',
    notes: pageData.notes || '',
    inspirationImages: inspirationImages,
  });
  const [submitted, setSubmitted] = React.useState(false);
  const [submittedQuote, setSubmittedQuote] = React.useState(null);
  const [errors, setErrors] = React.useState({});
  const [submitError, setSubmitError] = React.useState('');
  const [step, setStep] = React.useState(1);
  const [isMobile, setIsMobile] = React.useState(window.innerWidth < 768);
  const dessertTotal = React.useMemo(() => (form.dessertItems || []).reduce((sum, item) => (
    sum + (Number(item.dozens || 1) * Number(item.pricePerDozen || 0))
  ), 0), [form.dessertItems]);
  const total = isDessertsOnly ? dessertTotal : decorationTotal;

  React.useEffect(() => {
    const onResize = () => setIsMobile(window.innerWidth < 768);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  const set = (key, val) => {
    setForm(f => ({ ...f, [key]: val }));
    setErrors(e => ({ ...e, [key]: '' }));
  };
  const activeDesserts = React.useMemo(() => (desserts || []).filter(item => item.status !== 'paused'), [desserts]);
  const wizardSteps = React.useMemo(() => {
    if (isDessertsOnly) {
      return [
        { id: 'contact', label: t('quote_step_contact'), title: t('quote_step_title_contact') },
        { id: 'event', label: t('quote_step_event'), title: t('quote_step_title_event') },
        { id: 'desserts', label: t('quote_step_desserts'), title: t('quote_step_title_desserts') },
        { id: 'inspiration', label: t('quote_step_inspiration'), title: t('quote_step_title_inspiration') },
      ];
    }
    return form.wantsDesserts
      ? [
      { id: 'contact', label: t('quote_step_contact'), title: t('quote_step_title_contact') },
      { id: 'event', label: t('quote_step_event'), title: t('quote_step_title_event') },
      { id: 'desserts', label: t('quote_step_desserts'), title: t('quote_step_title_desserts') },
      { id: 'decoration', label: t('quote_step_decoration'), title: t('quote_step_title_decoration') },
      { id: 'inspiration', label: t('quote_step_inspiration'), title: t('quote_step_title_inspiration') },
    ]
    : [
      { id: 'contact', label: t('quote_step_contact'), title: t('quote_step_title_contact') },
      { id: 'event', label: t('quote_step_event'), title: t('quote_step_title_event') },
      { id: 'decoration', label: t('quote_step_decoration'), title: t('quote_step_title_decoration') },
      { id: 'inspiration', label: t('quote_step_inspiration'), title: t('quote_step_title_inspiration') },
    ];
  }, [form.wantsDesserts, isDessertsOnly, t]);
  const currentStep = wizardSteps[step - 1] || wizardSteps[0];

  React.useEffect(() => {
    if (step > wizardSteps.length) setStep(wizardSteps.length);
  }, [step, wizardSteps.length]);

  const updateDessertItem = (dessert, patch = {}) => {
    setForm(f => {
      const current = f.dessertItems || [];
      const exists = current.some(item => String(item.id) === String(dessert.id));
      const base = exists
        ? current.map(item => String(item.id) === String(dessert.id) ? { ...item, ...patch } : item)
        : [...current, {
          id: dessert.id,
          name: dessert.name,
          category: dessert.category,
          dozens: 1,
          notes: '',
          pricePerDozen: Number(dessert.pricePerDozen || 0),
          ...patch,
        }];
      return { ...f, dessertItems: base };
    });
    setErrors(e => ({ ...e, desserts: '' }));
  };

  const removeDessertItem = (dessertId) => {
    setForm(f => ({ ...f, dessertItems: (f.dessertItems || []).filter(item => String(item.id) !== String(dessertId)) }));
  };

  const validateStep = (s) => {
    const e = {};
    if (s === 1) {
      if (!form.name.trim()) e.name = t('quote_err_name');
      if (!form.phone.trim()) e.phone = t('quote_err_phone');
      if (!form.email.trim() || !form.email.includes('@')) e.email = t('quote_err_email');
    }
    if (s === 2) {
      if (!form.eventDate) e.eventDate = t('quote_err_date');
      if (!form.eventTime) e.eventTime = t('quote_err_time');
      if (!form.eventPlace.trim()) e.eventPlace = t('quote_err_place');
    }
    const stepId = wizardSteps[s - 1]?.id;
    if (stepId === 'desserts' && form.wantsDesserts) {
      const hasSelection = (form.dessertItems || []).length > 0;
      const hasCustom = form.dessertCustom.trim() || form.dessertNotes.trim();
      if (!hasSelection && !hasCustom) e.desserts = t('quote_err_desserts');
    }
    if (stepId === 'decoration') {
      if (!form.focus.trim()) e.focus = t('quote_err_focus');
    }
    return e;
  };

  const nextStep = () => {
    const e = validateStep(step);
    if (Object.keys(e).length) {
      setErrors(e);
      window.scrollTo({ top: 0, behavior: 'smooth' });
      return;
    }
    setErrors({});
    setStep(s => Math.min(s + 1, wizardSteps.length));
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const prevStep = () => {
    setErrors({});
    setStep(s => Math.max(s - 1, 1));
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const validate = () => {
    const e = {};
    if (!form.name.trim()) e.name = t('quote_err_name');
    if (!form.phone.trim()) e.phone = t('quote_err_phone');
    if (!form.email.trim() || !form.email.includes('@')) e.email = t('quote_err_email');
    if (!form.eventDate) e.eventDate = t('quote_err_date');
    if (!form.eventTime) e.eventTime = t('quote_err_time');
    if (!form.eventPlace.trim()) e.eventPlace = t('quote_err_place');
    if (!isDessertsOnly && !form.focus.trim()) e.focus = t('quote_err_focus');
    if (form.wantsDesserts && !(form.dessertItems || []).length && !form.dessertCustom.trim() && !form.dessertNotes.trim()) {
      e.desserts = t('quote_err_desserts');
    }
    return e;
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    window.LelusaGestures.haptic(12);
    const err = validate();
    if (Object.keys(err).length) { setErrors(err); return; }
    setSubmitError('');
    const quote = window.LelusaStore.addQuote({
      language: window.LelusaI18n?.language || localStorage.getItem('lelusa_lang') || 'en',
      clientName: form.name.trim(),
      phone: form.phone.trim(),
      email: form.email.trim(),
      contactPreference: form.contactPreference,
      eventDate: form.eventDate,
      eventTime: form.eventTime,
      eventPlace: form.eventPlace.trim(),
      eventType: isDessertsOnly ? t('quote_desserts_only_event_type') : (categoryLabelBySlug[deco.category] || CATEGORY_LABELS[deco.category] || deco.category || 'Decoración personalizada'),
      designId: isCustomBooking || isDessertsOnly ? null : deco.id,
      designName: deco.name,
      selectedOptions: selections,
      selectedExtras: extras,
      selectedOptionLabels: selectionLabels.selectedOptionLabels,
      selectedExtraLabels: selectionLabels.selectedExtraLabels,
      basePrice: isDessertsOnly ? 0 : Number(deco.price || 0),
      extrasPrice: isDessertsOnly ? total : Math.max(0, total - Number(deco.price || 0)),
      total,
      notes: form.notes.trim(),
      wantsDesserts: Boolean(form.wantsDesserts || isDessertsOnly),
      dessertRequest: form.wantsDesserts ? {
        notes: [
          form.dessertNotes.trim(),
          form.dessertCustom.trim() ? `${t('quote_desserts_custom_label')}: ${form.dessertCustom.trim()}` : '',
          form.dessertSetup.trim() ? `${t('quote_desserts_setup_label')}: ${form.dessertSetup.trim()}` : '',
        ].filter(Boolean).join('\n') || 'Cliente interesado en servicio de postres.',
        custom: form.dessertCustom.trim(),
        setup: form.dessertSetup.trim(),
        items: (form.dessertItems || []).map(item => ({
          id: item.id,
          name: item.name,
          category: item.category,
          dozens: Number(item.dozens || 1),
          notes: item.notes || '',
          pricePerDozen: Number(item.pricePerDozen || 0),
        })),
      } : null,
      guests: Number(form.guests) || 0,
      setupWindow: form.setupWindow,
      decorationDetails: {
        theme: form.theme.trim(),
        colors: form.colors.trim(),
        focus: isDessertsOnly ? t('quote_desserts_only_focus') : form.focus.trim(),
        mustHave: form.mustHave.trim(),
        budgetRange: form.budgetRange,
        customBrief: form.customBrief.trim(),
        inspirationImages: form.inspirationImages,
      },
    });
    if (!quote) {
      setSubmitError(t('quote_save_error'));
      return;
    }
    if (pageData.bookingDraftId) {
      sessionStorage.removeItem(`lelusa.bookingDraft.${pageData.bookingDraftId}`);
    }
    setSubmittedQuote(quote);
    setSubmitted(true);
  };

  const inputStyle = (err) => ({
    padding: '12px 16px', background: 'var(--card)', border: `1.5px solid ${err ? '#E07070' : 'var(--border)'}`,
    borderRadius: '12px', fontFamily: "'DM Sans', sans-serif", fontSize: '16px',
    color: 'var(--text)', outline: 'none', width: '100%', boxSizing: 'border-box',
    transition: 'border-color 0.2s',
  });

  const stepContacto = (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '18px' }}>
      <QuoteField label={t('quote_field_name')} error={errors.name}>
        <input value={form.name} onChange={e => set('name', e.target.value)} placeholder={t('quote_field_name_ph')} style={inputStyle(errors.name)} />
      </QuoteField>
      <QuoteField label={t('quote_field_phone')} error={errors.phone}>
        <input value={form.phone} onChange={e => set('phone', e.target.value)} placeholder={t('quote_field_phone_ph')} style={inputStyle(errors.phone)} />
      </QuoteField>
      <QuoteField label={t('quote_field_email')} error={errors.email}>
        <input type="email" value={form.email} onChange={e => set('email', e.target.value)} placeholder={t('quote_field_email_ph')} style={inputStyle(errors.email)} />
      </QuoteField>
      <QuoteField label={t('quote_field_contact_pref')}>
        <select aria-label={t('quote_field_contact_pref')} value={form.contactPreference} onChange={e => set('contactPreference', e.target.value)} style={inputStyle()}>
          <option value="Correo electrónico">{t('quote_contact_email')}</option>
          <option value="Llamada">{t('quote_contact_call')}</option>
          <option value="WhatsApp">{t('quote_contact_whatsapp')}</option>
          <option value="Mensaje">{t('quote_contact_sms')}</option>
        </select>
      </QuoteField>
    </div>
  );

  const stepEvento = (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '18px' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
        <QuoteField label={t('quote_field_event_date')} error={errors.eventDate}>
          <input type="date" title={t('quote_field_event_date')} value={form.eventDate} onChange={e => set('eventDate', e.target.value)} min={todayInput} style={inputStyle(errors.eventDate)} />
        </QuoteField>
        <QuoteField label={t('quote_field_event_time')} error={errors.eventTime}>
          <input type="time" title={t('quote_field_event_time')} value={form.eventTime} onChange={e => set('eventTime', e.target.value)} style={inputStyle(errors.eventTime)} />
        </QuoteField>
      </div>
      <QuoteField label={t('quote_field_event_place')} error={errors.eventPlace}>
        <input value={form.eventPlace} onChange={e => set('eventPlace', e.target.value)} placeholder={t('quote_field_event_place_ph')} style={inputStyle(errors.eventPlace)} />
      </QuoteField>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
        <QuoteField label={t('quote_field_guests')}>
          <input type="number" value={form.guests} onChange={e => set('guests', e.target.value)} placeholder={t('quote_field_guests_ph')} min="1" style={inputStyle()} />
        </QuoteField>
        <QuoteField label={t('quote_field_setup_window')}>
          <input value={form.setupWindow} onChange={e => set('setupWindow', e.target.value)} placeholder={t('quote_field_setup_window_ph')} style={inputStyle()} />
        </QuoteField>
      </div>
      {isDessertsOnly ? (
        <div style={{ border: '1px solid var(--border)', borderRadius: '14px', padding: '14px', background: 'var(--accent-light)' }}>
          <strong style={{ display: 'block', fontSize: '14px', color: 'var(--text)' }}>{t('quote_desserts_title')}</strong>
          <span style={{ display: 'block', fontSize: '12px', color: 'var(--muted)', lineHeight: 1.5, marginTop: '3px' }}>{t('quote_desserts_only_notice')}</span>
        </div>
      ) : (
        <div style={{ border: '1px solid var(--border)', borderRadius: '14px', padding: '14px', background: form.wantsDesserts ? 'var(--accent-light)' : 'var(--card)' }}>
          <label style={{ display: 'flex', alignItems: 'flex-start', gap: '10px', cursor: 'pointer' }}>
            <input type="checkbox" checked={form.wantsDesserts} onChange={e => {
              set('wantsDesserts', e.target.checked);
              if (e.target.checked) setStep(3);
            }} style={{ marginTop: '3px', accentColor: 'var(--primary)' }} />
            <span>
              <strong style={{ display: 'block', fontSize: '14px', color: 'var(--text)' }}>{t('quote_desserts_title')}</strong>
              <span style={{ display: 'block', fontSize: '12px', color: 'var(--muted)', lineHeight: 1.5, marginTop: '3px' }}>{t('quote_desserts_desc')}</span>
            </span>
          </label>
          {form.wantsDesserts && (
            <div style={{ marginTop: 12, borderTop: '1px solid var(--border)', paddingTop: 12, color: 'var(--primary)', fontSize: 12, fontWeight: 800 }}>
              {t('quote_desserts_next_step')}
            </div>
          )}
        </div>
      )}
    </div>
  );

  const stepPostres = (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '18px' }}>
      <div style={{ background: 'var(--accent-light)', border: '1px solid var(--border)', borderRadius: 14, padding: 14 }}>
        <strong style={{ display: 'block', color: 'var(--text)', fontSize: 14 }}>{t('quote_desserts_choose_title')}</strong>
        <span style={{ display: 'block', color: 'var(--muted)', fontSize: 12, lineHeight: 1.5, marginTop: 4 }}>{t('quote_desserts_choose_desc')}</span>
      </div>

      {errors.desserts && <div style={{ padding: '10px 12px', borderRadius: 12, background: '#FFE0E0', color: '#C83A3A', fontSize: 13 }}>{errors.desserts}</div>}

      <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : 'repeat(2, minmax(0, 1fr))', gap: 12 }}>
        {activeDesserts.length ? activeDesserts.map(dessert => {
          const selected = (form.dessertItems || []).find(item => String(item.id) === String(dessert.id));
          return (
            <div key={dessert.id} style={{ border: `1.5px solid ${selected ? 'var(--primary)' : 'var(--border)'}`, borderRadius: 16, padding: 14, background: selected ? 'var(--accent-light)' : 'var(--card)' }}>
              <label style={{ display: 'flex', gap: 10, alignItems: 'flex-start', cursor: 'pointer' }}>
                <input type="checkbox" checked={Boolean(selected)} onChange={e => e.target.checked ? updateDessertItem(dessert) : removeDessertItem(dessert.id)} style={{ marginTop: 3, accentColor: 'var(--primary)' }} />
                <span style={{ minWidth: 0 }}>
                  <strong style={{ display: 'block', color: 'var(--text)', fontSize: 14 }}>{dessert.name}</strong>
                  <span style={{ display: 'block', color: 'var(--muted)', fontSize: 12, lineHeight: 1.45, marginTop: 3 }}>
                    {dessert.category} · ${Number(dessert.pricePerDozen || 0).toLocaleString()} / {t('quote_desserts_dozen_short')}
                  </span>
                </span>
              </label>
              {selected && (
                <div style={{ display: 'grid', gap: 10, marginTop: 12 }}>
                  <QuoteField label={t('quote_desserts_quantity')}>
                    <input type="number" min="1" value={selected.dozens || 1} onChange={e => updateDessertItem(dessert, { dozens: e.target.value })} style={inputStyle()} />
                  </QuoteField>
                  <QuoteField label={t('quote_desserts_item_notes')}>
                    <input value={selected.notes || ''} onChange={e => updateDessertItem(dessert, { notes: e.target.value })} placeholder={t('quote_desserts_item_notes_ph')} style={inputStyle()} />
                  </QuoteField>
                </div>
              )}
            </div>
          );
        }) : (
          <div style={{ border: '1px dashed var(--border)', borderRadius: 14, padding: 16, color: 'var(--muted)', fontSize: 13 }}>{t('quote_desserts_catalog_empty')}</div>
        )}
      </div>

      <QuoteField label={t('quote_desserts_custom_label')}>
        <textarea value={form.dessertCustom} onChange={e => set('dessertCustom', e.target.value)} placeholder={t('quote_desserts_custom_ph')} rows={3} style={{ ...inputStyle(), resize: 'vertical', fontFamily: "'DM Sans', sans-serif" }} />
      </QuoteField>
      <QuoteField label={t('quote_desserts_setup_label')}>
        <input value={form.dessertSetup} onChange={e => set('dessertSetup', e.target.value)} placeholder={t('quote_desserts_setup_ph')} style={inputStyle()} />
      </QuoteField>
      <QuoteField label={t('quote_desserts_notes_label')}>
        <textarea value={form.dessertNotes} onChange={e => set('dessertNotes', e.target.value)} placeholder={t('quote_desserts_ph')} rows={3} style={{ ...inputStyle(), resize: 'vertical', fontFamily: "'DM Sans', sans-serif" }} />
      </QuoteField>
    </div>
  );

  const stepDecoracion = (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '18px' }}>
      <QuoteField label={t('quote_field_focus')} error={errors.focus}>
        <select aria-label={t('quote_field_focus')} value={form.focus} onChange={e => set('focus', e.target.value)} style={inputStyle(errors.focus)}>
          <option value="">{t('quote_focus_select')}</option>
          <option value="Mesa principal">{t('quote_focus_main_table')}</option>
          <option value="Backdrop / pared de fotos">{t('quote_focus_backdrop')}</option>
          <option value="Mesa de dulces">{t('quote_focus_dessert_table')}</option>
          <option value="Entrada del evento">{t('quote_focus_entrance')}</option>
          <option value="Todo el montaje">{t('quote_focus_all')}</option>
        </select>
      </QuoteField>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
        <QuoteField label={t('quote_field_theme')}>
          <input value={form.theme} onChange={e => set('theme', e.target.value)} placeholder={t('quote_field_theme_ph')} style={inputStyle()} />
        </QuoteField>
        <QuoteField label={t('quote_field_colors')}>
          <input value={form.colors} onChange={e => set('colors', e.target.value)} placeholder={t('quote_field_colors_ph')} style={inputStyle()} />
        </QuoteField>
      </div>
      {isCustomBooking && (
        <QuoteField label={t('quote_field_custom_brief')}>
          <textarea value={form.customBrief} onChange={e => set('customBrief', e.target.value)} placeholder={t('quote_field_custom_brief_ph')} rows={3} style={{ ...inputStyle(), resize: 'vertical', fontFamily: "'DM Sans', sans-serif" }} />
        </QuoteField>
      )}
      <QuoteField label={t('quote_field_must_have')}>
        <input value={form.mustHave} onChange={e => set('mustHave', e.target.value)} placeholder={t('quote_field_must_have_ph')} style={inputStyle()} />
      </QuoteField>
      <QuoteField label={t('quote_field_budget')}>
        <select aria-label={t('quote_field_budget')} value={form.budgetRange} onChange={e => set('budgetRange', e.target.value)} style={inputStyle()}>
          <option value="">{t('quote_budget_none')}</option>
          <option value="Menos de $500">{t('quote_budget_under_500')}</option>
          <option value="$500 - $900">{t('quote_budget_500_900')}</option>
          <option value="$900 - $1,500">{t('quote_budget_900_1500')}</option>
          <option value="Más de $1,500">{t('quote_budget_over_1500')}</option>
        </select>
      </QuoteField>
      <QuoteField label={t('quote_field_notes')}>
        <textarea value={form.notes} onChange={e => set('notes', e.target.value)} placeholder={t('quote_field_notes_ph')} rows={3} style={{ ...inputStyle(), resize: 'vertical', fontFamily: "'DM Sans', sans-serif" }} />
      </QuoteField>
      <div style={{ background: 'var(--accent-light)', borderRadius: '14px', padding: '14px 18px', display: 'flex', gap: '10px', alignItems: 'flex-start' }}>
        <Icon name="sparkles" size={16} color="var(--primary)" style={{ marginTop: '1px', flexShrink: 0 }} />
        <p style={{ margin: 0, fontSize: '13px', color: 'var(--muted)', lineHeight: 1.6 }}>{t('quote_price_estimate_note')}</p>
      </div>
    </div>
  );

  const stepInspiracion = (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '18px' }}>
      <div>
        <p style={{ margin: '0 0 16px', fontSize: '14px', color: 'var(--muted)', lineHeight: 1.6 }}>
          {t('quote_inspiration_desc')}
        </p>
        <DragDropImageZone
          images={form.inspirationImages}
          onChange={updater => set('inspirationImages', typeof updater === 'function' ? updater(form.inspirationImages) : updater)}
        />
      </div>
    </div>
  );

  if (submitted) {
    return (
      <div className="lel-has-bottomnav" style={{ minHeight: '100vh', background: 'var(--bg)' }}>
        <NavBar />
        <div style={{ maxWidth: '560px', margin: '0 auto', padding: '80px 24px', textAlign: 'center' }}>
          <div style={{ width: '80px', height: '80px', borderRadius: '50%', background: 'var(--accent-light)', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 24px' }}>
            <Icon name="check" size={36} color="var(--primary)" />
          </div>
          <h1 style={{ margin: '0 0 14px', fontFamily: "'Cormorant Garamond', serif", fontSize: '36px', fontWeight: 600, color: 'var(--text)' }}>{t('quote_sent_title')}</h1>
          <p style={{ margin: '0 0 10px', fontSize: '15px', color: 'var(--muted)', lineHeight: 1.7 }}>{t('quote_sent_thanks', { name: form.name, design: deco.name })}</p>
          <p style={{ margin: '0 0 36px', fontSize: '14px', color: 'var(--muted)', lineHeight: 1.7 }}>{t(contactSentKey(form.contactPreference), { phone: form.phone })}</p>
          <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '20px', padding: '24px', marginBottom: '32px', textAlign: 'left' }}>
            <div style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '13px', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--muted)', marginBottom: '14px' }}>{t('quote_sent_summary')}</div>
            {[
              [t('quote_summary_design'), deco.name],
              [t('quote_summary_folio'), submittedQuote?.id],
              [t('quote_summary_event_date'), form.eventDate],
              [t('quote_summary_time'), form.eventTime],
              [t('quote_summary_place'), form.eventPlace],
              [t('quote_summary_area'), form.focus],
              [t('quote_summary_total'), `$${total.toLocaleString()}`],
            ].filter(([, value]) => value).map(([label, value]) => (
              <div key={label} style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 0', borderBottom: '1px solid var(--border)', fontSize: '14px' }}>
                <span style={{ color: 'var(--muted)' }}>{label}</span>
                <span style={{ color: 'var(--text)', fontWeight: 500 }}>{value}</span>
              </div>
            ))}
          </div>
          <div style={{ display: 'flex', gap: '12px', justifyContent: 'center', flexWrap: 'wrap' }}>
            <Btn onClick={() => navigate('home')}>{t('quote_back_home')}</Btn>
            <Btn variant="ghost" onClick={() => navigate('catalog')}>{t('quote_see_more')}</Btn>
          </div>
        </div>
        <Footer />
      </div>
    );
  }


  const wizardNav = (
    <div style={{
      display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '12px',
      ...(isMobile ? {
        position: 'sticky', bottom: 0, background: 'var(--bg)',
        padding: '14px 20px', paddingBottom: 'calc(14px + env(safe-area-inset-bottom, 0px))',
        borderTop: '1px solid var(--border)', marginTop: '20px',
        marginLeft: '-20px', marginRight: '-20px',
      } : { marginTop: '28px' }),
    }}>
      {step > 1 ? (
        <button type="button" onClick={prevStep} style={{ background: 'none', border: '1px solid var(--border)', borderRadius: '12px', padding: '10px 20px', cursor: 'pointer', fontSize: '14px', color: 'var(--text)', fontFamily: "'DM Sans', sans-serif", fontWeight: 500, touchAction: 'manipulation' }}>
          {t('quote_nav_previous')}
        </button>
      ) : <div />}
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: '6px' }}>
        {step < wizardSteps.length ? (
          <Btn type="button" onClick={nextStep} style={{ touchAction: 'manipulation' }}>
            {t('quote_nav_next')}
          </Btn>
        ) : (
          <>
            <Btn type="button" onClick={handleSubmit} style={{ touchAction: 'manipulation' }}>
              <Icon name="fileText" size={16} color="#fff" />
              {t('quote_nav_submit')}
            </Btn>
            <button type="button" onClick={handleSubmit} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: '12px', color: 'var(--muted)', fontFamily: "'DM Sans', sans-serif", textDecoration: 'underline', touchAction: 'manipulation' }}>
              {t('quote_nav_skip_submit')}
            </button>
          </>
        )}
      </div>
    </div>
  );

  return (
    <div className="lel-has-bottomnav" style={{ minHeight: '100vh', background: 'var(--bg)' }}>
      <NavBar />
      <div style={{ maxWidth: '900px', margin: '0 auto', padding: isMobile ? '20px 20px 80px' : '40px 24px 80px' }}>
        <button onClick={() => (isCustomBooking || isDessertsOnly) ? navigate('home') : navigate('customizer', { decoId: deco.id })}
          style={{ background: 'none', border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: '6px', color: 'var(--muted)', fontSize: '13px', fontFamily: "'DM Sans', sans-serif", marginBottom: '20px', padding: 0, touchAction: 'manipulation' }}>
          <Icon name="arrowLeft" size={14} color="var(--muted)" /> {(isCustomBooking || isDessertsOnly) ? t('quote_back_home_link') : t('quote_back_customizer')}
        </button>

        <DesignSummaryCard
          deco={deco}
          total={total}
          extras={extras}
          selectionLabels={selectionLabels}
          isMobile={isMobile}
        />

        <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 360px', gap: isMobile ? '0' : '32px', alignItems: 'flex-start' }}>
          <div>
            <Badge>{t('quote_badge')}</Badge>
            <h1 style={{ margin: '14px 0 6px', fontFamily: "'Cormorant Garamond', serif", fontSize: isMobile ? '26px' : '32px', fontWeight: 600, color: 'var(--text)' }}>{t('quote_form_title')}</h1>
            <p style={{ margin: '0 0 24px', fontSize: '14px', color: 'var(--muted)' }}>{t('quote_form_subtitle')}</p>

            <StepProgressBar step={step} steps={wizardSteps.map(item => item.label)} />

            <div style={{ marginBottom: '8px' }}>
              <h2 style={{ margin: '0 0 4px', fontSize: '17px', fontWeight: 700, color: 'var(--text)', fontFamily: "'DM Sans', sans-serif" }}>
                {currentStep.title}
              </h2>
              <div style={{ height: '2px', width: '40px', background: 'var(--primary)', borderRadius: '2px' }} />
            </div>

            <div style={{ marginTop: '20px' }}>
              {currentStep.id === 'contact' && stepContacto}
              {currentStep.id === 'event' && stepEvento}
              {currentStep.id === 'desserts' && stepPostres}
              {currentStep.id === 'decoration' && stepDecoracion}
              {currentStep.id === 'inspiration' && stepInspiracion}
            </div>

            {submitError && <div style={{ marginTop: '12px', padding: '12px 14px', borderRadius: '12px', background: '#FFE0E0', color: '#C83A3A', fontSize: '13px' }}>{submitError}</div>}

            {wizardNav}
          </div>

          {!isMobile && (
            <div style={{ position: 'sticky', top: '88px' }}>
              <div style={{ background: 'var(--card)', border: '1px solid var(--border)', borderRadius: '24px', overflow: 'hidden' }}>
                <div style={{ aspectRatio: '4/3', overflow: 'hidden' }}>
                  {deco.image ? (
                    <img src={deco.image} alt={deco.name} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
                  ) : (
                    <DecoPlaceholder category={deco.category} />
                  )}
                </div>
                <div style={{ padding: '22px' }}>
                  <Badge>{categoryLabelBySlug[deco.category] || CATEGORY_LABELS[deco.category] || t('quote_card_category_custom')}</Badge>
                  <h3 style={{ margin: '10px 0 8px', fontFamily: "'Cormorant Garamond', serif", fontSize: '22px', fontWeight: 600, color: 'var(--text)' }}>{deco.name}</h3>
                  <div style={{ borderTop: '1px solid var(--border)', paddingTop: '14px', marginTop: '14px' }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '8px', fontSize: '14px' }}>
                      <span style={{ color: 'var(--muted)' }}>{t('quote_card_base_price')}</span>
                      <span style={{ color: 'var(--text)', fontWeight: 500 }}>{Number(deco.price || 0) ? `$${Number(deco.price || 0).toLocaleString()}` : t('quote_summary_to_define')}</span>
                    </div>
                    {extras.length > 0 && (
                      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '8px', fontSize: '14px' }}>
                        <span style={{ color: 'var(--muted)' }}>{t('quote_card_extras', { count: extras.length })}</span>
                        <span style={{ color: 'var(--text)', fontWeight: 500 }}>+${(total - deco.price).toLocaleString()}</span>
                      </div>
                    )}
                    {selectionLabels.selectedOptionLabels.length > 0 && (
                      <div style={{ marginTop: '12px', display: 'flex', flexDirection: 'column', gap: '6px' }}>
                        {selectionLabels.selectedOptionLabels.map(label => (
                          <div key={label} style={{ fontSize: '12px', color: 'var(--muted)', lineHeight: 1.4 }}>{label}</div>
                        ))}
                      </div>
                    )}
                    {selectionLabels.selectedExtraLabels.length > 0 && (
                      <div style={{ marginTop: '8px', display: 'flex', flexWrap: 'wrap', gap: '6px' }}>
                        {selectionLabels.selectedExtraLabels.map(label => (
                          <span key={label} style={{ fontSize: '11px', color: 'var(--primary)', background: 'var(--accent-light)', borderRadius: '999px', padding: '3px 8px' }}>{label}</span>
                        ))}
                      </div>
                    )}
                    <div style={{ marginTop: '16px', paddingTop: '14px', borderTop: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                      <span style={{ fontSize: '14px', color: 'var(--muted)' }}>{t('quote_card_total')}</span>
                      <span style={{ fontFamily: "'Cormorant Garamond', serif", fontSize: '28px', fontWeight: 700, color: 'var(--text)' }}>${total.toLocaleString()}</span>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>
      </div>
      <Footer />
    </div>
  );
}

// ─── Export ──────────────────────────────────────────────────────
Object.assign(window, { CustomizerPage, QuoteFormPage });
