/* eslint-disable */
/**
 * Shared relocation preset picker used by:
 *   1. The international-moving landing calculator (landing/calculator.jsx)
 *   2. The homepage hero relocation flow (components/HeroAnimated.jsx)
 *
 * Single source of truth for the Rooms / Boxes / Types tabbed picker so:
 *   - Admin Quote Config changes propagate to both surfaces
 *   - Per-preset items[] (multi-row packages) flows through one schema
 *   - Visual + behaviour are identical across landing and homepage
 *
 * Reads presets from `window.__landingBuilders.applyConfig(overrides)` so
 * any admin config doc (Firestore `config/landing-international-moving`)
 * automatically becomes the picker's source data.
 *
 * Exposes on `window.__abgsSharedCalculator.MovePresetPicker`.
 *
 * Babel-standalone'd in the browser. Load AFTER `landing/quote-builders.js`.
 */
(function () {
  const React = window.React;
  if (!React) return;

  const PRESET_TABS = [
    { key: 'rooms', enLabel: 'By rooms',          esLabel: 'Por habitaciones', icon: 'home' },
    { key: 'boxes', enLabel: 'Boxes + furniture', esLabel: 'Cajas + muebles',  icon: 'box' },
    { key: 'types', enLabel: 'Shipment type',     esLabel: 'Tipo de envío',    icon: 'container' },
  ];

  const isEs = () => {
    // Landing pages set window.LANG before loading this module; the homepage
    // hero relies on the document's <html lang> attribute instead. Honour
    // both so the picker localises consistently across surfaces.
    if (window.LANG) return String(window.LANG).toLowerCase().startsWith('es');
    const htmlLang = (document.documentElement && document.documentElement.lang) || '';
    return htmlLang.toLowerCase().startsWith('es');
  };

  // ─── Shared tab-strip icon + size-card icon ──────────────────────────────
  // Both calculators (landing + homepage hero) share the same visual size
  // picker via this module. SVGs live here so the homepage hero's react
  // bundle doesn't need to duplicate the landing's calculator.jsx SizeIcon.
  function TabIcon({ name }) {
    const props = { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none',
      stroke: 'currentColor', strokeWidth: 1.8,
      strokeLinecap: 'round', strokeLinejoin: 'round' };
    if (name === 'home')      return React.createElement('svg', props, React.createElement('path', { d: 'M3 10 L12 3 L21 10 V20 a1 1 0 0 1 -1 1 H4 a1 1 0 0 1 -1 -1 Z' }), React.createElement('path', { d: 'M9 21 V13 h6 v8' }));
    if (name === 'box')       return React.createElement('svg', props, React.createElement('path', { d: 'M21 8 L12 13 L3 8' }), React.createElement('path', { d: 'M3 8 L12 3 L21 8 V16 L12 21 L3 16 Z' }), React.createElement('path', { d: 'M12 13 V21' }));
    if (name === 'container') return React.createElement('svg', props, React.createElement('rect', { x: 2, y: 7, width: 20, height: 10, rx: 1 }), React.createElement('path', { d: 'M6 7 V17 M10 7 V17 M14 7 V17 M18 7 V17' }));
    return null;
  }
  // SizeIcon — house/boxes/container glyphs that vary by preset key. Mirrors
  // landing/calculator.jsx SizeIcon so the homepage hero can render the same
  // tile UI without duplicating SVG paths.
  function SizeIcon({ mode, keyName }) {
    if (mode === 'rooms') {
      const beds = keyName === 'studio' ? 0 : keyName === '1bed' ? 1 : keyName === '2bed' ? 2 : 3;
      const kids = [
        React.createElement('path', { key: 'h', d: 'M5 26 L5 14 L16 6 L27 14 L27 26 Z', stroke: 'currentColor', strokeWidth: 1.6, strokeLinejoin: 'round' }),
        React.createElement('path', { key: 'f', d: 'M5 26 L27 26', stroke: 'currentColor', strokeWidth: 1.6 }),
      ];
      if (beds >= 1) kids.push(React.createElement('rect', { key: 'b1', x: 8,  y: 18, width: 6, height: 5, rx: 1, stroke: 'currentColor', strokeWidth: 1.4, fill: 'none' }));
      if (beds >= 2) kids.push(React.createElement('rect', { key: 'b2', x: 18, y: 18, width: 6, height: 5, rx: 1, stroke: 'currentColor', strokeWidth: 1.4, fill: 'none' }));
      if (beds >= 3) kids.push(React.createElement('rect', { key: 'b3', x: 13, y: 11, width: 6, height: 4, rx: 1, stroke: 'currentColor', strokeWidth: 1.4, fill: 'none' }));
      return React.createElement('svg', { width: 32, height: 32, viewBox: '0 0 32 32', fill: 'none' }, kids);
    }
    if (mode === 'boxes') {
      const stacks = keyName === 'sm' ? 1 : keyName === 'md' ? 2 : keyName === 'lg' ? 3 : 4;
      const kids = [];
      for (let i = 0; i < stacks; i++) {
        kids.push(React.createElement('rect', { key: 'st' + i, x: 4 + i * 5.5, y: 26 - i * 4, width: 9, height: 4, rx: 0.5, stroke: 'currentColor', strokeWidth: 1.4, fill: 'none' }));
      }
      kids.push(React.createElement('rect',  { key: 'box', x: 15, y: 14, width: 13, height: 10, rx: 1, stroke: 'currentColor', strokeWidth: 1.6, fill: 'none' }));
      kids.push(React.createElement('path',  { key: 'bh',  d: 'M15 18 L28 18', stroke: 'currentColor', strokeWidth: 1.2 }));
      kids.push(React.createElement('path',  { key: 'bv',  d: 'M21.5 14 L21.5 18', stroke: 'currentColor', strokeWidth: 1.2 }));
      return React.createElement('svg', { width: 32, height: 32, viewBox: '0 0 32 32', fill: 'none' }, kids);
    }
    // types tab: small/medium LCL or 20'/40' containers
    const isFcl = String(keyName || '').startsWith('fcl');
    const w = keyName === 'lcl-sm' ? 14 : keyName === 'lcl-md' ? 18 : keyName === 'fcl-20' ? 22 : 26;
    const h = isFcl ? 14 : 10;
    const slats = keyName === 'lcl-sm' ? 3 : keyName === 'lcl-md' ? 4 : 5;
    const wheelY = isFcl ? 27 : 24;
    const wheel2X = keyName === 'lcl-sm' ? 14 : keyName === 'lcl-md' ? 16 : keyName === 'fcl-20' ? 20 : 24;
    const kids = [
      React.createElement('rect', { key: 'b', x: 3, y: 11, width: w, height: h, rx: 1, stroke: 'currentColor', strokeWidth: 1.6, fill: 'none' }),
    ];
    for (let i = 0; i < slats; i++) {
      kids.push(React.createElement('line', { key: 's' + i, x1: 6 + i * 3.5, y1: 14, x2: 6 + i * 3.5, y2: isFcl ? 22 : 19, stroke: 'currentColor', strokeWidth: 1.1 }));
    }
    kids.push(React.createElement('circle', { key: 'w1', cx: 9, cy: wheelY, r: 2, stroke: 'currentColor', strokeWidth: 1.4, fill: 'none' }));
    kids.push(React.createElement('circle', { key: 'w2', cx: wheel2X, cy: wheelY, r: 2, stroke: 'currentColor', strokeWidth: 1.4, fill: 'none' }));
    return React.createElement('svg', { width: 32, height: 32, viewBox: '0 0 32 32', fill: 'none' }, kids);
  }
  // homePlus — house with a "+" inside. Used for the rooms-tab Custom card
  // and any "add" affordance that wants to read as room-related.
  function HomePlusIcon({ size }) {
    const s = size || 32;
    return React.createElement('svg', { width: s, height: s, viewBox: '0 0 32 32', fill: 'none' },
      React.createElement('path', { d: 'M5 26 L5 14 L16 6 L27 14 L27 26 Z', stroke: 'currentColor', strokeWidth: 1.6, strokeLinejoin: 'round' }),
      React.createElement('path', { d: 'M5 26 L27 26', stroke: 'currentColor', strokeWidth: 1.6 }),
      React.createElement('path', { d: 'M16 14 V22 M12 18 H20', stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round' })
    );
  }

  function labelOf(p) {
    if (!p) return '';
    return isEs() ? (p.label || p.labelEn || '') : (p.labelEn || p.label || '');
  }
  function subOf(p) {
    if (!p) return '';
    return isEs() ? (p.sub || p.subEn || '') : (p.subEn || p.sub || '');
  }

  // Compute a derived summary for the picked preset (CBM / weight / mode).
  // Pulls per-item dimensions from the new preset.lcl.items[] schema and
  // sums them in m³, with the preset's declared `cbm` acting as a floor.
  // Returns null for unknown presets.
  function computePresetSummary(preset) {
    if (!preset) return null;
    const items = (preset.lcl && Array.isArray(preset.lcl.items)) ? preset.lcl.items : [];
    const inToCm  = (v) => v * 2.54;
    const lbsToKg = (v) => v * 0.453592;
    let cbm = 0, weightKg = 0, pieces = 0;
    items.forEach((it) => {
      const dimFn = (it.dimensionUnit === 'CM') ? (v) => v : inToCm;
      const wFn   = (it.weightUnit    === 'KG') ? (v) => v : lbsToKg;
      const qty = Math.max(1, Number(it.qty) || 1);
      const L = dimFn(Number(it.length) || 0);
      const W = dimFn(Number(it.width)  || 0);
      const H = dimFn(Number(it.height) || 0);
      cbm     += (L * W * H * qty) / 1000000;
      weightKg += wFn(Number(it.weightPerPiece) || 0) * qty;
      pieces  += qty;
    });
    const declaredCbm = Math.max(0.1, Number(preset.cbm) || 1);
    const effectiveCbm = Math.max(declaredCbm, cbm) || declaredCbm;
    return {
      mode: preset.mode || 'LCL',
      cbm: effectiveCbm,
      weightKg: weightKg > 0 ? Math.round(weightKg) : Math.round(effectiveCbm * 250),
      pieces: pieces > 0 ? pieces : Math.max(1, preset.pieces || 10),
      containers: (preset.fcl && preset.fcl.containers) || null,
    };
  }

  // Resolve the effective tables — applying any caller-provided override doc
  // (typically the Firestore `config/landing-<slug>` payload) on top of the
  // hardcoded DEFAULTS from quote-builders.js.
  function resolveTables(overrides) {
    const LB = window.__landingBuilders;
    if (!LB || !LB.applyConfig) return null;
    return LB.applyConfig(overrides || {});
  }

  // ─── Custom-rooms synthetic preset ──────────────────────────────────────
  // Per-room baseline derived from the rooms.1bed default in quote-builders.js
  // (~14 m³ per bedroom, with 7 pallets + 5 wardrobe + 8 medium boxes). We
  // scale these linearly with N rooms so a customer can request "15 rooms"
  // without forcing the admin to maintain a 15-bed preset.
  //
  // Mode auto-decision:
  //   N × 14 m³ <  25 m³  → LCL (single groupage shipment, < 1× 20')
  //   N × 14 m³ >= 25 m³  → FCL, ceil(CBM / 67) 40HC containers
  //
  // (40HC capacity is ~67 m³; using HC over standard 40' gives ~10 m³ extra
  // headroom which household goods love — vertical stacking of boxes.)
  function buildCustomRoomsPreset(N, baseline) {
    const n = Math.max(1, Math.floor(Number(N) || 1));
    // baseline is the effective `rooms.1bed` preset (admin-config-aware) so
    // if the admin overrides the 1bed mix, the extrapolation respects it.
    const baseItems = (baseline && baseline.lcl && Array.isArray(baseline.lcl.items)
                       && baseline.lcl.items.length > 0)
      ? baseline.lcl.items
      : [
          { id: 'pallet',   label: 'Pallet',       length: 40, width: 40, height: 85, qty: 7, weightPerPiece: 800, dimensionUnit: 'IN', weightUnit: 'LBS' },
          { id: 'wardrobe', label: 'Wardrobe box', length: 24, width: 24, height: 30, qty: 5, weightPerPiece:  60, dimensionUnit: 'IN', weightUnit: 'LBS' },
          { id: 'medium',   label: 'Medium box',   length: 18, width: 18, height: 16, qty: 8, weightPerPiece:  30, dimensionUnit: 'IN', weightUnit: 'LBS' },
        ];
    const baseCbm = (baseline && baseline.cbm) ? Number(baseline.cbm) : 14;
    const basePieces = (baseline && baseline.pieces) ? Number(baseline.pieces) : 20;
    const cbm = +(baseCbm * n).toFixed(2);
    const pieces = basePieces * n;
    const cuft = Math.round(cbm * 35.31);
    // FCL threshold: 25 m³ — below that an LCL groupage shipment is cheaper.
    // Above 25 m³ we move to FCL with high-cube containers (67 m³ capacity).
    const FCL_THRESHOLD_CBM = 25;
    const HC_CAPACITY_CBM = 67;
    const isFcl = cbm >= FCL_THRESHOLD_CBM;
    let containers = null;
    if (isFcl) {
      const count = Math.max(1, Math.ceil(cbm / HC_CAPACITY_CBM));
      containers = { '40HC': count };
    }
    return {
      mode: isFcl ? 'FCL' : 'LCL',
      cbm, pieces, cuft,
      subtype: n + 'br_custom',
      label:   isEs() ? (n + ' habitaciones') : (n + ' bedrooms'),
      labelEn: n + ' bedrooms',
      sub:   isEs()
        ? ('~' + cbm + ' m³' + (isFcl ? ' · ' + (containers['40HC']) + '× 40\'HC' : ''))
        : ('~' + cbm + ' m³' + (isFcl ? ' · ' + (containers['40HC']) + '× 40\'HC' : '')),
      subEn: '~' + cbm + ' m³' + (isFcl ? ' · ' + (containers && containers['40HC']) + '× 40\'HC' : ''),
      lcl: { items: baseItems.map((it) => ({ ...it, qty: (Number(it.qty) || 1) * n })) },
      fcl: { containers },
    };
  }

  // ─── <MovePresetPicker> ─────────────────────────────────────────────────
  // Props:
  //   activeKey:    which preset key is selected
  //   activeTab:    optional initial tab (rooms|boxes|types) — defaults to
  //                 whatever tab contains activeKey, or 'rooms'
  //   overrides:    optional Firestore config doc (passed to applyConfig)
  //   onPick:       (key, preset, tabKey) — fires on chip click
  //   onTabChange:  (tabKey) — optional, when the user switches tabs
  //   theme:        'hero' | 'landing' — controls styling (defaults to 'hero'
  //                 for the homepage; landing keeps its own CSS classes)
  function MovePresetPicker({ activeKey, activeTab, overrides, onPick, onTabChange, theme }) {
    const tables = resolveTables(overrides);
    if (!tables) {
      return React.createElement('div', {
        style: { padding: 10, fontSize: 11, color: '#98A2B3' },
      }, 'Loading…');
    }
    // Resolve the initial tab from activeKey if not provided.
    const findTabForKey = (k) => {
      if (!k) return 'rooms';
      for (const t of PRESET_TABS) {
        if (tables[t.key] && tables[t.key][k]) return t.key;
      }
      return 'rooms';
    };
    const [tab, setTab] = React.useState(activeTab || findTabForKey(activeKey));
    // Custom-rooms stepper state — only relevant on the Rooms tab. Default 4
    // because 1-3 are already covered by the standard chips. The synthetic
    // preset is fired through `onPick` whenever the count changes, so the
    // form stays in sync without an explicit "Confirm" button.
    const [customRoomCount, setCustomRoomCount] = React.useState(4);
    const [customRoomsOpen, setCustomRoomsOpen] = React.useState(
      activeKey && /custom/i.test(String(activeKey)));
    React.useEffect(() => {
      // Sync tab to activeKey when the parent flips it (e.g. on edit-search).
      const t = findTabForKey(activeKey);
      if (t && t !== tab) setTab(t);
    }, [activeKey]);

    const presets = tables[tab] || {};
    const isHero = (theme || 'hero') === 'hero';
    // Helper to fire the synthetic custom-rooms preset. Uses the effective
    // rooms.1bed as the per-room baseline so admin edits to 1bed scale up.
    const fireCustomRooms = (n) => {
      if (!onPick) return;
      const baseline = (tables.rooms && tables.rooms['1bed']) || null;
      const synth = buildCustomRoomsPreset(n, baseline);
      onPick('custom-' + n + '-rooms', synth, 'rooms');
    };

    // Two themes:
    //   hero    — homepage-style cards (white pill chips, mono labels)
    //   landing — landing-style class-based (uses calc__tab/calc__size CSS)
    if (!isHero) {
      // Render as the landing calculator's existing JSX classes
      return React.createElement(React.Fragment, null,
        React.createElement('div', { className: 'calc__tabs', role: 'tablist' },
          PRESET_TABS.map((t) =>
            React.createElement('button', {
              key: t.key,
              type: 'button',
              role: 'tab',
              className: 'calc__tab' + (t.key === tab ? ' is-active' : ''),
              onClick: () => { setTab(t.key); onTabChange && onTabChange(t.key); },
            }, isEs() ? t.esLabel : t.enLabel)
          )
        ),
        React.createElement('div', { className: 'calc__size-grid' },
          Object.entries(presets).map(([key, p]) =>
            React.createElement('button', {
              key,
              type: 'button',
              className: 'calc__size' + (key === activeKey ? ' is-active' : ''),
              onClick: () => onPick && onPick(key, p, tab),
            },
              React.createElement('div', { className: 'calc__size-label' }, labelOf(p)),
              React.createElement('div', { className: 'calc__size-sub' }, subOf(p))
            )
          ).concat(tab === 'rooms' ? [
            React.createElement('button', {
              key: '__custom__',
              type: 'button',
              className: 'calc__size' + (customRoomsOpen ? ' is-active' : ''),
              style: { borderStyle: customRoomsOpen ? 'solid' : 'dashed' },
              onClick: () => {
                setCustomRoomsOpen(true);
                fireCustomRooms(customRoomCount);
              },
            },
              React.createElement('div', { className: 'calc__size-label' },
                isEs() ? 'Personalizado' : 'Custom'),
              React.createElement('div', { className: 'calc__size-sub' },
                isEs() ? 'Más habitaciones…' : 'More rooms…')
            ),
          ] : [])
        ),
        // Custom-rooms stepper for the landing theme (rendered after the grid)
        (tab === 'rooms' && customRoomsOpen) ? React.createElement('div', {
          style: { marginTop: 12, padding: 14, borderRadius: 10,
                   background: 'rgba(30,87,214,0.06)',
                   border: '1px solid rgba(30,87,214,0.2)' },
        },
          React.createElement('div', {
            style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                     gap: 12, flexWrap: 'wrap' },
          },
            React.createElement('div', null,
              React.createElement('div', {
                style: { fontSize: 13, fontWeight: 700, color: '#0B1220',
                         letterSpacing: '-0.005em', marginBottom: 3 },
              }, isEs() ? 'Número de habitaciones' : 'Number of bedrooms'),
              React.createElement('div', {
                style: { fontSize: 11, color: '#1846B0',
                         fontFamily: 'JetBrains Mono, monospace', fontWeight: 600 },
              }, (() => {
                const baseline = (tables.rooms && tables.rooms['1bed']) || null;
                const synth = buildCustomRoomsPreset(customRoomCount, baseline);
                const containerNote = synth.fcl && synth.fcl.containers && synth.fcl.containers['40HC']
                  ? ' · ' + synth.fcl.containers['40HC'] + '× 40\'HC'
                  : ' · LCL groupage';
                return '~' + synth.cbm + ' m³' + containerNote;
              })())
            ),
            React.createElement('div', {
              style: { display: 'inline-flex', alignItems: 'center', gap: 4,
                       border: '1px solid rgba(16,24,40,0.12)', borderRadius: 9,
                       background: '#fff', padding: 4 },
            },
              React.createElement('button', {
                type: 'button',
                onClick: () => {
                  const next = Math.max(1, customRoomCount - 1);
                  setCustomRoomCount(next);
                  fireCustomRooms(next);
                },
                style: { width: 32, height: 32, borderRadius: 7,
                         background: 'transparent', border: 0, cursor: 'pointer',
                         color: '#475467', fontSize: 18, fontWeight: 600,
                         fontFamily: 'inherit', lineHeight: 1 },
              }, '−'),
              React.createElement('div', {
                style: { minWidth: 32, textAlign: 'center',
                         fontSize: 15, fontWeight: 700, color: '#0B1220',
                         fontFamily: 'JetBrains Mono, monospace',
                         fontVariantNumeric: 'tabular-nums' },
              }, String(customRoomCount)),
              React.createElement('button', {
                type: 'button',
                onClick: () => {
                  const next = Math.min(50, customRoomCount + 1);
                  setCustomRoomCount(next);
                  fireCustomRooms(next);
                },
                style: { width: 32, height: 32, borderRadius: 7,
                         background: 'transparent', border: 0, cursor: 'pointer',
                         color: '#1846B0', fontSize: 18, fontWeight: 600,
                         fontFamily: 'inherit', lineHeight: 1 },
              }, '+')
            )
          )
        ) : null
      );
    }

    // Hero theme — same look as the landing's MOVING SIZE block: inline tab
    // strip (segmented rectangle) above a horizontal row of tile cards with
    // SVG icons. Inline styles only — the homepage hero doesn't pull in the
    // landing's CSS, so all visuals have to ship with the component.
    const tabsStripStyle = {
      display: 'grid',
      gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
      background: 'transparent',
      border: '1px solid #EAECF0',
      borderRadius: 10,
      overflow: 'hidden',
      marginBottom: 12,
    };
    const tabBtnStyle = (active) => ({
      appearance: 'none',
      border: 0,
      background: active ? '#EFF6FF' : 'transparent',
      padding: '11px 12px',
      fontSize: 13, fontWeight: 600,
      color: active ? '#1846B0' : '#667085',
      cursor: 'pointer',
      display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      fontFamily: 'inherit',
      boxShadow: active ? 'inset 0 -2px 0 0 #1E57D6' : 'none',
      transition: 'color 160ms ease, background 160ms ease',
    });
    const tileBtnStyle = (active, dashed) => ({
      border: '1px solid ' + (active ? '#1E57D6' : (dashed ? 'rgba(30,87,214,0.5)' : '#EAECF0')),
      borderStyle: dashed && !active ? 'dashed' : 'solid',
      background: active ? '#EFF6FF' : '#fff',
      borderRadius: 10,
      padding: '14px 10px',
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      gap: 6,
      cursor: 'pointer',
      textAlign: 'center',
      fontFamily: 'inherit',
      boxShadow: active ? '0 0 0 4px rgba(30,87,214,0.12)' : 'none',
      transition: 'all 160ms ease',
    });
    const tileIconStyle = { width: 32, height: 32, display: 'flex',
      alignItems: 'center', justifyContent: 'center', color: '#1846B0' };
    const tileLabelStyle = { fontSize: 12.5, fontWeight: 600, color: '#0B1220',
      letterSpacing: '-0.005em', lineHeight: 1.2 };
    const tileSubStyle = (active) => ({
      fontFamily: 'JetBrains Mono, ui-monospace, monospace',
      fontSize: 9.5, fontWeight: 600, color: active ? '#1E57D6' : '#98A2B3',
      letterSpacing: '0.8px', textTransform: 'uppercase',
    });
    // Column count matches the landing: rooms tab gets 5 (4 presets + Custom),
    // boxes/types get 4.
    const gridCols = tab === 'rooms' ? 5 : 4;

    return React.createElement('div', null,
      // Inline tab strip — segmented control above the tiles.
      React.createElement('div', { style: tabsStripStyle, role: 'tablist' },
        PRESET_TABS.map((t) =>
          React.createElement('button', {
            key: t.key,
            type: 'button',
            role: 'tab',
            onClick: () => { setTab(t.key); onTabChange && onTabChange(t.key); },
            style: tabBtnStyle(t.key === tab),
          },
            React.createElement(TabIcon, { name: t.icon }),
            isEs() ? t.esLabel : t.enLabel
          )
        )
      ),
      // Tile-card grid — icon + label + sub, all centered, single row.
      React.createElement('div', {
        style: {
          display: 'grid',
          gridTemplateColumns: 'repeat(' + gridCols + ', minmax(0, 1fr))',
          gap: 8,
        },
      },
        Object.entries(presets).map(([key, p]) => {
          const isActive = key === activeKey && !customRoomsOpen;
          return React.createElement('button', {
            key,
            type: 'button',
            onClick: () => {
              if (tab === 'rooms') setCustomRoomsOpen(false);
              onPick && onPick(key, p, tab);
            },
            style: tileBtnStyle(isActive, false),
          },
            React.createElement('div', { style: tileIconStyle },
              React.createElement(SizeIcon, { mode: tab, keyName: key })),
            React.createElement('div', { style: tileLabelStyle }, labelOf(p)),
            React.createElement('div', { style: tileSubStyle(isActive) }, subOf(p))
          );
        }).concat(tab === 'rooms' ? [
          React.createElement('button', {
            key: '__custom__',
            type: 'button',
            onClick: () => {
              setCustomRoomsOpen(true);
              fireCustomRooms(customRoomCount);
            },
            style: tileBtnStyle(customRoomsOpen, true),
          },
            React.createElement('div', { style: tileIconStyle },
              React.createElement(HomePlusIcon, { size: 32 })),
            React.createElement('div', { style: tileLabelStyle },
              isEs() ? 'Personalizado' : 'Custom'),
            React.createElement('div', { style: tileSubStyle(customRoomsOpen) },
              isEs() ? 'Más habitaciones…' : 'More rooms…')
          ),
        ] : [])
      ),
      // Custom-rooms stepper — only shown on Rooms tab when "Custom" is active.
      // Lets the user dial in 4+ bedrooms; the synthetic preset auto-flips to
      // FCL once cargo crosses 25 m³ and adds the right number of 40' HC
      // containers (capacity ~67 m³ each).
      (tab === 'rooms' && customRoomsOpen) ? React.createElement('div', {
        style: { marginTop: 10, padding: 12, borderRadius: 10,
                 background: 'rgba(30,87,214,0.05)',
                 border: '1px solid rgba(30,87,214,0.18)' },
      },
        React.createElement('div', {
          style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                   gap: 12, flexWrap: 'wrap' },
        },
          React.createElement('div', null,
            React.createElement('div', {
              style: { fontSize: 11, fontWeight: 700, color: '#0B1220',
                       letterSpacing: '-0.005em', marginBottom: 2 },
            }, isEs() ? 'Número de habitaciones' : 'Number of bedrooms'),
            React.createElement('div', {
              style: { fontSize: 10, color: '#475467',
                       fontFamily: 'JetBrains Mono, monospace' },
            }, (() => {
              const baseline = (tables.rooms && tables.rooms['1bed']) || null;
              const synth = buildCustomRoomsPreset(customRoomCount, baseline);
              const containerNote = synth.fcl && synth.fcl.containers && synth.fcl.containers['40HC']
                ? ' · ' + synth.fcl.containers['40HC'] + '× 40\'HC'
                : ' · LCL groupage';
              return '~' + synth.cbm + ' m³' + containerNote;
            })())
          ),
          // Stepper
          React.createElement('div', {
            style: { display: 'inline-flex', alignItems: 'center', gap: 4,
                     border: '1px solid rgba(16,24,40,0.12)', borderRadius: 8,
                     background: '#fff', padding: 3 },
          },
            React.createElement('button', {
              type: 'button',
              onClick: () => {
                const next = Math.max(1, customRoomCount - 1);
                setCustomRoomCount(next);
                fireCustomRooms(next);
              },
              style: { width: 28, height: 28, borderRadius: 6,
                       background: 'transparent', border: 0, cursor: 'pointer',
                       color: '#475467', fontSize: 16, fontWeight: 600,
                       fontFamily: 'inherit', lineHeight: 1 },
            }, '−'),
            React.createElement('div', {
              style: { minWidth: 28, textAlign: 'center',
                       fontSize: 14, fontWeight: 700, color: '#0B1220',
                       fontFamily: 'JetBrains Mono, monospace',
                       fontVariantNumeric: 'tabular-nums' },
            }, String(customRoomCount)),
            React.createElement('button', {
              type: 'button',
              onClick: () => {
                const next = Math.min(50, customRoomCount + 1);
                setCustomRoomCount(next);
                fireCustomRooms(next);
              },
              style: { width: 28, height: 28, borderRadius: 6,
                       background: 'transparent', border: 0, cursor: 'pointer',
                       color: '#1846B0', fontSize: 16, fontWeight: 600,
                       fontFamily: 'inherit', lineHeight: 1 },
            }, '+')
          )
        )
      ) : null
    );
  }

  // ─── Relocation vehicles (mirrored from HeroAnimated.jsx) ───────────────
  // Each vehicle reserves ~1100 cuft (one 20' container's worth). This is a
  // deliberate simplification for the customer-facing quote — actual packing
  // is per-vehicle but the booking team's flat-fee model treats every car as
  // one bay. Keys must match HeroAnimated's catalog so both surfaces share
  // the same booking-team semantics.
  const VEHICLE_SLOT_CUFT = 1100;
  const RELOCATION_VEHICLES = [
    { key: 'motorcycle',   weightKg: 200,  enLabel: 'Motorcycle',     esLabel: 'Motocicleta' },
    { key: 'atv',          weightKg: 350,  enLabel: 'ATV / quad',     esLabel: 'ATV / cuatrimoto' },
    { key: 'jet_ski',      weightKg: 400,  enLabel: 'Jet ski',        esLabel: 'Moto acuática' },
    { key: 'golf_cart',    weightKg: 400,  enLabel: 'Golf cart',      esLabel: 'Carrito de golf' },
    { key: 'sedan',        weightKg: 1500, enLabel: 'Sedan',          esLabel: 'Auto sedán' },
    { key: 'suv',          weightKg: 2000, enLabel: 'SUV',            esLabel: 'SUV' },
    { key: 'pickup',       weightKg: 2200, enLabel: 'Pickup truck',   esLabel: 'Camioneta' },
    { key: 'van',          weightKg: 2500, enLabel: 'Van',            esLabel: 'Van' },
    { key: 'large_pickup', weightKg: 2800, enLabel: 'Large pickup',   esLabel: 'Camioneta grande' },
    { key: 'small_boat',   weightKg: 1000, enLabel: 'Small boat',     esLabel: 'Bote pequeño' },
  ].map(v => ({ ...v, cuft: VEHICLE_SLOT_CUFT }));
  const RELOCATION_VEHICLE_BY_KEY = (() => {
    const m = {};
    RELOCATION_VEHICLES.forEach(v => { m[v.key] = v; });
    return m;
  })();
  const cuftToCbm = (cuft) => Math.round((cuft / 35.315) * 100) / 100;
  const cuftToWeightKg = (cuft) => Math.round(cuft * 3.175);

  // FCL container recommendation — same logic as HeroAnimated.jsx
  // recommendFclForCuft. Returns MIXED container counts when efficient
  // (e.g. 8400 cuft → 3× 40' + 1× 20' instead of 4× 40'). 10% packing
  // buffer. Always returns { '20', '40', '40HC', '45' } with zeros filled.
  function recommendFclForCuft(cuft) {
    const buffered = cuft * 1.1;
    const blank = { '20': 0, '40': 0, '40HC': 0, '45': 0 };
    if (buffered <= 1100) return { ...blank, '20': 1 };
    if (buffered <= 2200) return { ...blank, '40': 1 };
    if (buffered <= 2500) return { ...blank, '40HC': 1 };
    const fortyCapacity = 2400;
    const twentyCapacity = 1320;
    const forties = Math.floor(buffered / fortyCapacity);
    const remainder = buffered - (forties * fortyCapacity);
    if (remainder <= 0) return { ...blank, '40': forties };
    if (remainder <= twentyCapacity) return { ...blank, '40': forties, '20': 1 };
    return { ...blank, '40': forties + 1 };
  }

  // Pretty-print a containers map as "3× 40' + 1× 20'" (in order from largest
  // to smallest, skipping zero counts). Lang-agnostic — uses the standard
  // container size names everywhere.
  function formatContainersMix(map) {
    if (!map) return '';
    const order = ['45', '40HC', '40', '20'];
    const titles = { '20': "20'", '40': "40'", '40HC': "40' HC", '45': "45'" };
    return order
      .map(c => ({ code: c, n: Number(map[c]) || 0 }))
      .filter(x => x.n > 0)
      .map(x => `${x.n}× ${titles[x.code]}`)
      .join(' + ');
  }

  // ─── <RelocationVehiclePicker> ──────────────────────────────────────────
  // Drop-in component for both the homepage hero and the landing calculator.
  // Renders:
  //   - "+ Add vehicle…" dropdown (10 vehicle types, same labels EN/ES)
  //   - Chip row of added vehicles (Motorcycle 1× 20' [×])
  // Props:
  //   vehicles:     [{ id, type }] — current array
  //   onChange:     (next) => void — fires on add/remove with the next array
  //   theme:        'hero' | 'landing' — visual treatment
  function RelocationVehiclePicker({ vehicles, onChange, theme }) {
    const isHero = (theme || 'hero') === 'hero';
    const labelOfVeh = (v) => isEs() ? v.esLabel : v.enLabel;
    const arr = Array.isArray(vehicles) ? vehicles : [];

    const add = (type) => {
      const next = arr.concat([{ id: 'v-' + Date.now() + '-' + Math.random().toString(36).slice(2, 6), type }]);
      onChange && onChange(next);
    };
    const remove = (id) => {
      const next = arr.filter(v => v.id !== id);
      onChange && onChange(next);
    };

    // Dropdown — native <select> for accessibility + zero CSS overhead.
    const selectStyle = isHero
      ? { padding: '6px 10px', borderRadius: 8,
          border: '1px solid rgba(30,87,214,0.25)',
          background: '#fff', color: '#1846B0',
          fontSize: 11.5, fontWeight: 700, cursor: 'pointer',
          fontFamily: 'inherit', appearance: 'auto' }
      : { padding: '8px 12px', borderRadius: 8,
          border: '1px solid #d0d5dd', background: '#fff',
          fontFamily: 'inherit', fontSize: 13, color: '#0B1220',
          cursor: 'pointer', appearance: 'auto' };

    return React.createElement(React.Fragment, null,
      // Add dropdown
      React.createElement('select', {
        value: '',
        onChange: (e) => {
          const v = e.target.value;
          if (v) add(v);
          e.target.value = '';
        },
        style: selectStyle,
      },
        React.createElement('option', { value: '' },
          isEs() ? '+ Agregar vehículo…' : '+ Add vehicle…'),
        RELOCATION_VEHICLES.map(v =>
          React.createElement('option', { key: v.key, value: v.key },
            labelOfVeh(v) + " · " + (isEs() ? "ocupa 1× 20'" : "takes 1× 20'"))
        )
      ),
      // Chip row
      arr.length > 0 ? React.createElement('div', {
        style: { marginTop: 8, display: 'flex', flexWrap: 'wrap', gap: 6 },
      },
        arr.map(v => {
          const def = RELOCATION_VEHICLE_BY_KEY[v.type];
          if (!def) return null;
          return React.createElement('span', {
            key: v.id,
            style: {
              display: 'inline-flex', alignItems: 'center', gap: 6,
              padding: '4px 4px 4px 10px', borderRadius: 9999,
              background: 'rgba(30,87,214,0.08)',
              border: '1px solid rgba(30,87,214,0.25)',
              fontSize: 11, fontWeight: 700, color: '#1846B0',
              fontFamily: 'inherit',
            },
          },
            labelOfVeh(def),
            React.createElement('span', {
              style: { fontSize: 9.5, fontWeight: 600, opacity: 0.85,
                       fontFamily: 'JetBrains Mono, ui-monospace, monospace' },
            }, "1× 20'"),
            React.createElement('button', {
              type: 'button',
              onClick: () => remove(v.id),
              'aria-label': 'Remove vehicle',
              style: {
                width: 18, height: 18, borderRadius: 9999,
                background: 'rgba(220,38,38,0.12)', color: '#B42318',
                border: 0, cursor: 'pointer', fontFamily: 'inherit',
                fontSize: 12, fontWeight: 700, lineHeight: 1,
                display: 'inline-grid', placeItems: 'center',
              },
            }, '×')
          );
        })
      ) : null
    );
  }

  window.__abgsSharedCalculator = {
    PRESET_TABS,
    MovePresetPicker,
    computePresetSummary,
    buildCustomRoomsPreset,
    resolveTables,
    labelOf,
    subOf,
    // Vehicle picker exports
    VEHICLE_SLOT_CUFT,
    RELOCATION_VEHICLES,
    RELOCATION_VEHICLE_BY_KEY,
    cuftToCbm,
    cuftToWeightKg,
    recommendFclForCuft,
    formatContainersMix,
    RelocationVehiclePicker,
  };
})();
