/* GarageWiz — Door Configurator + live price rail */
(function () {
  const e = React.createElement;
  const { useState } = React;
  const Icon = window.Icon, Btn = window.Btn, Badge = window.Badge, Toggle = window.Toggle,
        OptionTile = window.OptionTile, Segmented = window.Segmented, DoorPreview = window.DoorPreview;

  const STEPS = ['Door Width', 'Door Height', 'Panel Style', 'Door Model', 'Windows', 'Opener', 'Add-ons'];

  /* ---------------- Live price rail ---------------- */
  function PriceRail({ config, result, onPresent }) {
    const app = window.useApp();
    const special = config.width && !(GW.widths.find(w => w.ft === config.width) || {}).std;
    const setQty = (n) => app.setConfig(Object.assign({}, config, { qty: Math.max(1, n) }));
    const qty = result.qty || 1;
    const qBtn = (label, on, dis) => e('button', { onClick: on, disabled: dis, style: { border: '1.5px solid var(--line-2)', background: '#fff', borderRadius: 9, width: 34, height: 34, display: 'grid', placeItems: 'center', cursor: dis ? 'not-allowed' : 'pointer', color: 'var(--ink)', fontWeight: 700, fontSize: 18, opacity: dis ? .4 : 1 } }, label);
    return e('div', { className: 'price-rail-inner', style: { display: 'flex', flexDirection: 'column', gap: 18 } },
      e(DoorPreview, { config, result }),

      special ? e('div', { style: { display: 'flex', gap: 10, alignItems: 'flex-start', background: 'var(--warn-bg)', border: '1px solid #F0D49A', borderRadius: 12, padding: '11px 13px' } },
        e(Icon, { name: 'truck', size: 20, style: { color: '#9A5B07', flexShrink: 0, marginTop: 1 } }),
        e('div', { style: { fontSize: 12.5, color: '#7A4A07', lineHeight: 1.45 } }, e('strong', null, 'Special Order — 3–4 wk lead time. '), 'Built to size by the factory.'),
      ) : null,

      // Big price
      e('div', { style: { background: 'linear-gradient(165deg, var(--teal) 0%, var(--teal-800) 100%)', color: '#fff', borderRadius: 'var(--r-lg)', padding: '22px 22px 20px', position: 'relative', overflow: 'hidden' } },
        e('div', { style: { position: 'absolute', right: -20, top: -20, width: 120, height: 120, borderRadius: 999, background: 'rgba(0,177,237,.3)' } }),
        e('div', { className: 'eyebrow', style: { color: 'var(--yellow)', position: 'relative' } }, 'Your price · installed'),
        e('div', { className: 'display num', style: { fontSize: 52, fontWeight: 700, lineHeight: 1, marginTop: 8, position: 'relative', letterSpacing: '-.02em' } },
          result.configured ? GW.fmt(result.price) : '—'),
        e('div', { style: { fontSize: 13, color: 'rgba(255,255,255,.8)', marginTop: 8, position: 'relative' } },
          result.configured ? (qty > 1 ? (qty + ' doors · ' + GW.fmt(result.unitPrice) + ' each, installed') : 'Includes professional install & haul-away of your old door.') : 'Pick a size, height & model to see the price.'),
      ),

      // quantity
      result.configured ? e('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: '#fff', border: '1px solid var(--line)', borderRadius: 12, padding: '10px 14px' } },
        e('div', null,
          e('div', { style: { fontWeight: 700, fontSize: 14 } }, 'Quantity'),
          e('div', { className: 'muted', style: { fontSize: 12 } }, 'How many of this door'),
        ),
        e('div', { style: { display: 'flex', alignItems: 'center', gap: 10 } },
          qBtn('−', () => setQty(qty - 1), qty <= 1),
          e('span', { className: 'num', style: { minWidth: 22, textAlign: 'center', fontWeight: 800, fontSize: 17 } }, qty),
          qBtn('+', () => setQty(qty + 1), false),
        ),
      ) : null,

      // line items
      result.lines.length ? e('div', { style: { display: 'flex', flexDirection: 'column', gap: 2 } },
        result.lines.concat(result.addonLines).map(l => e('div', { key: l.key, style: { display: 'flex', alignItems: 'baseline', gap: 10, padding: '8px 2px', borderBottom: '1px dashed var(--line)' } },
          e('div', { className: 'grow', style: { minWidth: 0 } },
            e('div', { style: { fontWeight: 700, fontSize: 14 } }, l.label),
            l.sub ? e('div', { className: 'muted', style: { fontSize: 12, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' } }, l.sub) : null,
          ),
        )),
      ) : null,

      result.bundleSavings > 0 ? e('div', { style: { display: 'flex', alignItems: 'center', gap: 10, background: 'rgba(46,182,125,.1)', border: '1px solid rgba(46,182,125,.35)', borderRadius: 12, padding: '11px 13px' } },
        e(Icon, { name: 'check', size: 18, style: { color: 'var(--good)', flexShrink: 0 } }),
        e('div', { style: { fontSize: 13, color: 'var(--ink-2)', lineHeight: 1.4 } },
          e('strong', { style: { color: 'var(--good)' } }, 'Package savings · ' + GW.fmt(result.bundleSavings)),
          (result.bundlesApplied && result.bundlesApplied.length) ? e('div', { className: 'muted', style: { fontSize: 11.5, marginTop: 1 } }, result.bundlesApplied.map(b => b.name).join(' · ')) : null,
        ),
      ) : null,

      result.configured ? e(Btn, { variant: 'primary', size: 'lg', block: true, icon: 'check', onClick: onPresent }, 'Review & present') : null,
    );
  }
  window.PriceRail = PriceRail;

  /* ---------------- helper rows ---------------- */
  function priceForOpenerTier(tierObj, rail) {
    const op = GW.findOpener(tierObj.openerId);
    return GW.openerCost(op, rail);
  }

  /* ---------------- Bundle / package strip ---------------- */
  // One-tap packages shown above the add-ons list. Adding a package flips all
  // its items on at once; the discount is applied automatically by the engine.
  function BundleStrip({ config, set, app, target }) {
    const t = target || 'door';
    const bundles = (GW.bundles || []).filter(b => b.enabled !== false && (b.target === t || b.target === 'any'));
    if (!bundles.length) return null;
    const isOn = (id) => !!(config.addons && config.addons[id]);
    return e('div', { style: { marginBottom: 20 } },
      e('div', { className: 'eyebrow', style: { color: 'var(--blue)', marginBottom: 10 } }, 'Save with a package'),
      e('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(260px, 1fr))', gap: 12 } },
        bundles.map(b => {
          const pv = GW.bundlePreview(b, app.settings);
          const allOn = b.items.every(isOn);
          const addAll = () => { const next = Object.assign({}, config.addons); b.items.forEach(id => { next[id] = true; }); set({ addons: next }); };
          const removeAll = () => { const next = Object.assign({}, config.addons); b.items.forEach(id => { next[id] = false; }); set({ addons: next }); };
          return e('div', { key: b.id, style: { border: '2px solid ' + (allOn ? 'var(--good)' : 'var(--line)'), borderRadius: 'var(--r-lg)', padding: 16, background: allOn ? 'rgba(46,182,125,.06)' : '#fff', display: 'flex', flexDirection: 'column', gap: 10 } },
            e('div', { style: { display: 'flex', alignItems: 'flex-start', gap: 8 } },
              e('div', { className: 'grow' },
                e('div', { className: 'display', style: { fontSize: 16, fontWeight: 600 } }, b.name),
                e('div', { className: 'muted', style: { fontSize: 12.5, marginTop: 2 } }, b.desc),
              ),
              pv.save > 0 ? e('span', { className: 'badge badge-good', style: { whiteSpace: 'nowrap' } }, 'Save ' + GW.fmt(pv.save)) : null,
            ),
            e('div', { style: { display: 'flex', alignItems: 'baseline', gap: 8 } },
              e('span', { className: 'display num', style: { fontSize: 19, fontWeight: 700, color: 'var(--teal)' } }, GW.fmt(pv.bundlePrice)),
              pv.save > 0 ? e('span', { className: 'num', style: { fontSize: 13.5, color: 'var(--ink-3)', textDecoration: 'line-through' } }, GW.fmt(pv.gross)) : null,
            ),
            allOn
              ? e(Btn, { variant: 'ghost', size: 'sm', block: true, icon: 'check', onClick: removeAll }, 'Added — remove package')
              : e(Btn, { variant: 'primary', size: 'sm', block: true, icon: 'plus', onClick: addAll }, 'Add package'),
          );
        }),
      ),
    );
  }
  window.BundleStrip = BundleStrip;

  /* ---------------- Configurator ---------------- */
  function Configurator() {
    const app = window.useApp();
    const config = app.config;
    const result = GW.compute(config, app.settings);
    const [step, setStep] = useState(0);
    const [maxReached, setMaxReached] = useState(0);
    const [showMorePanels, setShowMorePanels] = useState(() => {
      const p = (GW.panels || []).find(x => x.id === config.panel);
      return p ? !p.primary : false;
    });

    const set = (patch) => app.setConfig(Object.assign({}, config, patch));
    const goStep = (i) => { setStep(i); setMaxReached(m => Math.max(m, i)); };
    const next = () => { if (step < STEPS.length - 1) goStep(step + 1); else app.go('#/quote/summary'); };
    const back = () => { if (step > 0) setStep(step - 1); else app.go('#/dashboard'); };

    const model = GW.findModel(config.modelCode);
    const height = GW.findHeight(config.heightId);
    const rail = height ? height.rail : 7;

    // gating: can continue?
    const canNext = (
      step === 0 ? config.width != null :
      step === 1 ? config.heightId != null :
      step === 3 ? config.modelCode != null :
      true
    );

    /* --- step renderers --- */
    function StepHead({ n, title, sub }) {
      return e('div', { style: { marginBottom: 22 } },
        e('div', { className: 'eyebrow' }, 'Step ' + (n + 1) + ' of ' + STEPS.length),
        e('h1', { className: 'display', style: { fontSize: 30, fontWeight: 600, margin: '5px 0 0' } }, title),
        sub ? e('div', { className: 'muted', style: { fontSize: 15.5, marginTop: 6 } }, sub) : null,
      );
    }

    let body;
    if (step === 0) {
      body = e('div', null,
        e(StepHead, { n: 0, title: 'How wide is the opening?', sub: 'Standard sizes are in stock. Larger sizes are special-order but price instantly.' }),
        e('div', { className: 'tile-grid-3' },
          GW.widths.map(w => e(OptionTile, {
            key: w.ft, selected: config.width === w.ft, onClick: () => set({ width: w.ft }),
            title: w.ft + ' ft', sub: w.std ? 'In stock' : 'Special order',
            badge: w.std ? null : 'order', badgeLabel: w.std ? null : 'Special',
          })),
        ),
      );
    } else if (step === 1) {
      body = e('div', null,
        e(StepHead, { n: 1, title: 'How tall is the door?', sub: 'Height sets the section count and the opener rail size.' }),
        e('div', { className: 'tile-grid-3' },
          GW.heights.map(h => e(OptionTile, {
            key: h.id, selected: config.heightId === h.id, onClick: () => set({ heightId: h.id }),
            title: h.label, sub: h.sections + ' sections · ' + h.rail + 'ft rail',
          })),
        ),
      );
    } else if (step === 2) {
      const grp = (p) => p.group;
      const panelThumb = (p) => {
        const cols = grp(p) === 'short' ? 4 : 2;
        const wrap = { display: 'flex', flexDirection: 'column', gap: 3, height: 86, background: '#eef4f6', borderRadius: 10, padding: 8, marginBottom: 14, border: '1px solid var(--line)' };
        const cell = { flex: 1, background: 'linear-gradient(180deg,#fff,#dce6ea)', borderRadius: 3, border: '1px solid var(--line-2)', position: 'relative' };
        if (p.render === 'slat') {
          return e('div', { style: wrap }, Array.from({ length: 5 }).map((_, r) => e('div', { key: r, style: { flex: 1, background: 'linear-gradient(180deg,#fff,#dce6ea)', borderRadius: 2, border: '1px solid var(--line-2)' } })));
        }
        if (p.render === 'flush') {
          return e('div', { style: wrap }, [0, 1, 2].map(r => e('div', { key: r, style: { flex: 1, background: 'linear-gradient(180deg,#fff,#e3ebee)', borderRadius: 3, border: '1px solid var(--line-2)', backgroundImage: 'repeating-linear-gradient(180deg, transparent 0 4px, rgba(8,37,47,.04) 4px 5px)' } })));
        }
        // raised + carriage
        return e('div', { style: wrap }, [0, 1, 2].map(r => e('div', { key: r, style: { flex: 1, display: 'flex', gap: 4 } },
          Array.from({ length: cols }).map((_, c) => e('div', { key: c, style: cell },
            p.render === 'carriage' ? e('div', { style: { position: 'absolute', inset: 2, borderRadius: 2, boxShadow: 'inset 0 0 0 1px rgba(8,37,47,.16)' } }) : null,
            p.render === 'carriage' ? e('div', { style: { position: 'absolute', left: '50%', top: 2, bottom: 2, width: 1, background: 'rgba(8,37,47,.14)' } }) : null,
          )),
        )));
      };
      const panelTile = (p) => e('button', {
        key: p.id, onClick: () => set({ panel: p.id }),
        style: {
          textAlign: 'left', border: '2.5px solid ' + (config.panel === p.id ? 'var(--blue)' : 'transparent'),
          boxShadow: config.panel === p.id ? '0 8px 22px rgba(0,177,237,.18)' : 'inset 0 0 0 1px var(--line)',
          background: '#fff', borderRadius: 'var(--r-lg)', padding: 18, cursor: 'pointer', position: 'relative',
        },
      },
        e('div', { style: { position: 'absolute', top: 14, right: 14, fontSize: 11, fontWeight: 800, letterSpacing: '.04em', color: 'var(--ink-3)' } }, 'SERIES ' + p.series),
        panelThumb(p),
        e('div', { className: 'display', style: { fontSize: 18, fontWeight: 600 } }, p.name),
        e('div', { className: 'muted', style: { fontSize: 13, marginTop: 2 } }, p.desc),
      );
      const primary = GW.panels.filter(p => p.primary);
      const secondary = GW.panels.filter(p => !p.primary);
      body = e('div', null,
        e(StepHead, { n: 2, title: 'Panel style', sub: 'Affects the look, window count and decorative options.' }),
        e('div', { className: 'tile-grid-2' }, primary.map(panelTile)),
        e('button', {
          onClick: () => setShowMorePanels(v => !v),
          style: {
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 9, width: '100%',
            margin: '16px 0 0', padding: '13px', borderRadius: 'var(--r-pill)',
            border: '1.5px dashed var(--line-2)', background: showMorePanels ? '#fff' : 'var(--field)',
            color: 'var(--teal)', fontFamily: 'var(--display)', fontWeight: 600, fontSize: 15, cursor: 'pointer',
          },
        },
          e(Icon, { name: showMorePanels ? 'chevD' : 'plus', size: 18, style: { transform: showMorePanels ? 'rotate(180deg)' : 'none', transition: 'transform .2s' } }),
          showMorePanels ? 'Show fewer styles' : 'More styles (4 more)',
        ),
        showMorePanels ? e('div', { className: 'tile-grid-2', style: { marginTop: 16, animation: 'gw-fade .25s ease' } }, secondary.map(panelTile)) : null,
      );
    } else if (step === 3) {
      const wi = config.width != null ? GW.widthIndex[config.width] : null;
      body = e('div', null,
        e(StepHead, { n: 3, title: 'Which door model?', sub: 'Same great install — better steel and insulation as you move up.' }),
        e('div', { style: { display: 'flex', flexDirection: 'column', gap: 12 } },
          GW.models.map(m => {
            const sellPrice = (wi != null && height) ? m.table[wi][height.col] : null;
            return e(OptionTile, {
              key: m.code, selected: config.modelCode === m.code, onClick: () => set({ modelCode: m.code }),
              title: m.name, sub: m.desc, badge: m.badge, badgeLabel: m.badgeLabel,
            });
          }),
        ),
        (config.width == null || height == null) ? e('div', { className: 'muted', style: { fontSize: 13.5, marginTop: 14, display: 'flex', gap: 8, alignItems: 'center' } }, e(Icon, { name: 'info', size: 17 }), 'Pick a width and height first to lock in model pricing.') : null,
      );
    } else if (step === 4) {
      const glass = GW.findGlass(config.glassId) || GW.glass[0];
      const pGroup = GW.panelGroup(config.panel || 'short');
      const pName = ((GW.panels || []).find(p => p.id === config.panel) || GW.panels[0]).name;
      const cnt = (GW.windowCount[config.width] || {})[pGroup] || 0;
      const cat = GW.glassCat(pGroup, model ? model.insulated : false);
      body = e('div', null,
        e(StepHead, { n: 4, title: 'Windows', sub: 'Optional — adds light and curb appeal.' }),
        e('div', { style: { display: 'flex', alignItems: 'center', gap: 14, background: '#fff', border: '1px solid var(--line)', borderRadius: 'var(--r-lg)', padding: '16px 18px', marginBottom: config.windowsOn ? 18 : 0 } },
          e('div', { className: 'grow' },
            e('div', { className: 'display', style: { fontSize: 18, fontWeight: 600 } }, 'Add a row of windows'),
            e('div', { className: 'muted', style: { fontSize: 13.5 } }, config.width ? (cnt + ' lites for a ' + config.width + 'ft ' + pName) : 'Pick a width first'),
          ),
          e(Toggle, { on: config.windowsOn, onChange: (v) => set({ windowsOn: v }), label: 'Windows' }),
        ),
        config.windowsOn ? e('div', null,
          e('div', { style: { fontWeight: 700, fontSize: 13.5, color: 'var(--ink-2)', margin: '4px 0 10px' } }, 'Glass type'),
          e('div', { style: { display: 'flex', flexDirection: 'column', gap: 10 } },
            GW.glass.map(g => {
              const delta = GW.priceDelta(config, { windowsOn: true, glassId: g.id }, { windowsOn: false }, app.settings);
              return e(OptionTile, {
                key: g.id, compact: true, selected: config.glassId === g.id, onClick: () => set({ glassId: g.id }),
                title: g.name, sub: g.desc,
                badge: g.tier === 'standard' ? 'start' : 'prem', badgeLabel: g.tier === 'standard' ? 'Included' : 'Upgrade',
                right: e('div', { style: { textAlign: 'right' } },
                  e('div', { className: 'display num', style: { fontWeight: 600, fontSize: 15.5, color: 'var(--teal)' } }, (delta >= 0 ? '+' : '') + GW.fmt(delta)),
                  e('div', { style: { fontSize: 10.5, fontWeight: 700, letterSpacing: '.05em', color: 'var(--ink-3)' } }, 'TO PRICE'),
                ),
              });
            }),
          ),
        ) : null,
      );
    } else if (step === 5) {
      body = e('div', null,
        e(StepHead, { n: 5, title: 'Add an opener?', sub: 'Good · Better · Best. Priced for your ' + rail + 'ft rail.' }),
        e('div', { style: { display: 'flex', flexDirection: 'column', gap: 12 } },
          e(OptionTile, { compact: true, selected: config.openerMode === 'none', onClick: () => set({ openerMode: 'none' }), title: 'No opener', sub: 'Door only — customer keeps their current opener' }),
          GW.openerTiers.filter(t => { const op = GW.findOpener(t.openerId); return op && op.enabled && !((app.disabledMfrs || {})[op.brand]); }).map(t => {
            const op = GW.findOpener(t.openerId);
            const delta = GW.priceDelta(config, { openerMode: 'tier', openerTier: t.tier }, { openerMode: 'none' }, app.settings);
            return e(OptionTile, {
              key: t.tier, selected: config.openerMode === 'tier' && config.openerTier === t.tier,
              onClick: () => set({ openerMode: 'tier', openerTier: t.tier }),
              title: t.tier + ' · ' + op.brand + ' ' + op.id, sub: op.desc + ' — ' + t.blurb,
              badge: t.tier === 'Best' ? 'prem' : t.tier === 'Better' ? 'pop' : null,
              badgeLabel: t.tier === 'Best' ? 'Top pick' : t.tier === 'Better' ? 'Most popular' : null,
              right: e('div', { style: { textAlign: 'right' } },
                e('div', { className: 'display num', style: { fontWeight: 600, fontSize: 15.5, color: 'var(--teal)' } }, '+' + GW.fmt(delta)),
                e('div', { style: { fontSize: 10.5, fontWeight: 700, letterSpacing: '.05em', color: 'var(--ink-3)' } }, 'TO PRICE'),
              ),
            });
          }),
        ),
        config.openerMode === 'tier' ? e('div', { style: { marginTop: 22 } },
          e(window.BundleStrip, { config, set, app, target: 'opener' })) : null,
      );
    } else if (step === 6) {
      const items = GW.upsellItems('door');
      const addonRow = (a) => {
        const on = !!(config.addons && config.addons[a.id]);
        const delta = GW.priceDelta(config, { addons: Object.assign({}, config.addons, { [a.id]: true }) }, { addons: Object.assign({}, config.addons, { [a.id]: false }) }, app.settings);
        return e('div', { key: a.id, style: { display: 'flex', alignItems: 'center', gap: 14, background: on ? '#fff' : 'var(--field)', border: '2px solid ' + (on ? 'var(--good)' : 'transparent'), boxShadow: on ? 'none' : 'inset 0 0 0 1px var(--line)', borderRadius: 'var(--r-lg)', padding: '14px 18px', transition: 'all .15s' } },
          e('div', { className: 'grow' },
            e('div', { className: 'display', style: { fontSize: 17, fontWeight: 600 } }, a.name),
            e('div', { className: 'muted', style: { fontSize: 13.5 } }, a.desc),
          ),
          e('div', { className: 'display num', style: { fontWeight: 600, fontSize: 15.5, color: on ? 'var(--good)' : 'var(--ink-3)', whiteSpace: 'nowrap' } }, '+' + GW.fmt(delta)),
          e(Toggle, { on, onChange: (v) => set({ addons: Object.assign({}, config.addons, { [a.id]: v }) }), label: a.name }),
        );
      };
      // decorative inserts — a door upgrade priced by width + panel group
      const insGroup = GW.panelGroup(config.panel || 'short');
      const insCost = config.width != null ? ((GW.inserts[config.width] || {})[insGroup] || 0) : 0;
      const insAvail = insCost > 0 && !!config.windowsOn;
      const insOn = !!config.insertsOn;
      const insDelta = GW.priceDelta(config, { insertsOn: true }, { insertsOn: false }, app.settings);
      const insertsRow = insAvail ? e('div', { key: 'inserts', style: { display: 'flex', alignItems: 'center', gap: 14, background: insOn ? '#fff' : 'var(--field)', border: '2px solid ' + (insOn ? 'var(--good)' : 'transparent'), boxShadow: insOn ? 'none' : 'inset 0 0 0 1px var(--line)', borderRadius: 'var(--r-lg)', padding: '14px 18px', transition: 'all .15s' } },
        e('div', { className: 'grow' },
          e('div', { className: 'display', style: { fontSize: 17, fontWeight: 600 } }, 'Decorative inserts'),
          e('div', { className: 'muted', style: { fontSize: 13.5 } }, 'Designer hardware row — adds curb appeal'),
        ),
        e('div', { className: 'display num', style: { fontWeight: 600, fontSize: 15.5, color: insOn ? 'var(--good)' : 'var(--ink-3)', whiteSpace: 'nowrap' } }, '+' + GW.fmt(insDelta)),
        e(Toggle, { on: insOn, onChange: (v) => set({ insertsOn: v }), label: 'Decorative inserts' }),
      ) : null;
      body = e('div', null,
        e(StepHead, { n: 6, title: 'Add-ons & upgrades', sub: 'Flip any on — the price updates instantly.' }),
        e('div', { style: { display: 'flex', flexDirection: 'column', gap: 10 } }, [insertsRow].concat(items.map(addonRow))),
      );
    }

    return e('div', { className: 'config-wrap' },
      // step rail (left, navy)
      e('aside', { className: 'config-rail' },
        e('button', { onClick: () => app.go('#/dashboard'), style: { display: 'flex', alignItems: 'center', gap: 8, background: 'transparent', border: 'none', color: 'rgba(255,255,255,.7)', fontWeight: 600, fontFamily: 'var(--display)', fontSize: 14, cursor: 'pointer', marginBottom: 18, padding: '0 13px' } }, e(Icon, { name: 'back', size: 17 }), 'Dashboard'),
        e('div', { className: 'eyebrow', style: { color: 'var(--yellow)', padding: '0 13px 12px' } }, 'Build a door'),
        e(window.StepRail, { steps: STEPS, current: step, maxReached, onJump: goStep }),
        e('button', {
          onClick: () => { if (confirm('Start a new quote? This clears the current build.')) { app.resetConfig(); setStep(0); setMaxReached(0); } },
          style: { display: 'flex', alignItems: 'center', gap: 9, background: 'transparent', border: '1.5px solid rgba(255,255,255,.2)', color: 'rgba(255,255,255,.75)', fontWeight: 600, fontFamily: 'var(--display)', fontSize: 13.5, cursor: 'pointer', margin: '18px 13px 0', padding: '10px 14px', borderRadius: 999 },
        }, e(Icon, { name: 'plus', size: 16 }), 'New quote'),
      ),

      // main content
      e('main', { className: 'config-main' },
        e('div', { className: 'config-progress' },
          e('button', { onClick: back, style: { border: 'none', background: 'var(--field)', borderRadius: 999, width: 38, height: 38, display: 'grid', placeItems: 'center', color: 'var(--ink-2)', cursor: 'pointer', flexShrink: 0 } }, e(Icon, { name: 'arrowL', size: 18 })),
          e('span', { className: 'cp-label' }, (step + 1) + '/' + STEPS.length),
          e('div', { className: 'cp-track' }, e('div', { className: 'cp-fill', style: { width: ((step + 1) / STEPS.length * 100) + '%' } })),
          e('button', {
            onClick: () => { if (confirm('Start a new quote? This clears the current build.')) { app.resetConfig(); setStep(0); setMaxReached(0); } },
            title: 'New quote', style: { border: 'none', background: 'var(--field)', borderRadius: 999, width: 38, height: 38, display: 'grid', placeItems: 'center', color: 'var(--ink-2)', cursor: 'pointer', flexShrink: 0 },
          }, e(Icon, { name: 'plus', size: 18 })),
        ),
        e('div', { className: 'config-body', style: { animation: 'gw-fade .25s ease' }, key: step }, body),
        e('div', { className: 'config-nav' },
          e(Btn, { variant: 'ghost', icon: 'arrowL', onClick: back }, step === 0 ? 'Cancel' : 'Back'),
          e('div', { className: 'config-nav-mobileprice' }, result.configured ? e('div', null, e('div', { style: { fontSize: 11, fontWeight: 800, letterSpacing: '.1em', color: 'var(--blue)' } }, 'PRICE'), e('div', { className: 'display num', style: { fontSize: 24, fontWeight: 700, lineHeight: 1 } }, GW.fmt(result.price))) : null),
          e(Btn, { variant: 'teal', iconRight: step === STEPS.length - 1 ? 'check' : 'arrowR', onClick: next, disabled: !canNext }, step === STEPS.length - 1 ? 'Review' : 'Continue'),
        ),
      ),

      // price rail (right)
      e('aside', { className: 'config-price' },
        e(PriceRail, { config, result, onPresent: () => app.go('#/quote/summary') }),
      ),
    );
  }
  window.Configurator = Configurator;
})();
