(() => {
  const $ = (sel) => document.querySelector(sel);
  const fromEl = $('#from');
  const toEl = $('#to');
  const tripsEl = $('#trips');
  const priceBox = $('#priceBox');
  const voucherBox = $('#voucherBox');
  let previewSeq = 0;
  let lastPreviewKey = '';

  const api = {
    fareQuery: async (from, to) => {
      const r = await fetch(`/api/public/fares/query?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`);
      return r.json();
    },
    createOrder: async (payload) => {
      const r = await fetch('/api/public/orders', { method:'POST', headers:{ 'Content-Type':'application/json' }, body: JSON.stringify(payload) });
      return r.json();
    }
  };

  // Fetch and Render Map
  const mapContainer = $('#stationMap');
  let selection = [null, null];
  let currentRoute = [];
  let currentRouteTransfers = [];
  let stationNameByCode = {};
  let stationEnByCode = {};
  let stationCanonicalByCode = {};
  let stationCodesByCanonical = {};
  let stationXByCanonical = {};
  let stationYByCanonical = {};
  let stationTransfer = new Set();
  
  const piePath = (cx, cy, r, a0, a1) => {
      const x0 = cx + r * Math.cos(a0);
      const y0 = cy + r * Math.sin(a0);
      const x1 = cx + r * Math.cos(a1);
      const y1 = cy + r * Math.sin(a1);
      const large = (a1 - a0) > Math.PI ? 1 : 0;
      return `M ${cx} ${cy} L ${x0} ${y0} A ${r} ${r} 0 ${large} 1 ${x1} ${y1} Z`;
  };
  
  const pieSvg = (cx, cy, r, colors) => {
      const cols = (Array.isArray(colors) ? colors.filter(Boolean) : []).slice(0, 4);
      if (cols.length === 0) return '';
      if (cols.length === 1) return `<circle cx="${cx}" cy="${cy}" r="${r}" fill="${cols[0]}" />`;
      const step = (Math.PI * 2) / cols.length;
      let out = '';
      for (let i = 0; i < cols.length; i++) {
          const a0 = -Math.PI / 2 + i * step;
          const a1 = a0 + step;
          out += `<path d="${piePath(cx, cy, r, a0, a1)}" fill="${cols[i]}" />`;
      }
      return out;
  };

  async function loadMap() {
      try {
          const res = await fetch('/api/public/fares/map/light');
          const svg = await res.text();
          mapContainer.innerHTML = svg;
          
          const svgEl = mapContainer.querySelector('svg');
          if(!svgEl) return;

          renderLineMap();
      } catch(e) {
          mapContainer.innerHTML = '<div class="error">加载地图失败</div>';
      }
  }

  async function renderLineMap() {
      try {
          const [lines, stations] = await Promise.all([
              fetch('/api/public/lines').then(r=>r.json()),
              fetch('/api/public/stations').then(r=>r.json())
          ]);
          
          let html = '';
          lines.forEach(line => {
              const stList = line.站序 || []; 

          });
      } catch(e) {}
  }
  

  
  async function renderSystemMap() {
      mapContainer.innerHTML = '<div class="loading">加载线路数据...</div>';
      try {
          const [linesData, stationsData] = await Promise.all([
              fetch('/api/public/lines').then(r=>r.json()),
              fetch('/api/public/stations').then(r=>r.json())
          ]);

          window.cachedStationsData = stationsData;
          stationTransfer = new Set();
          stationCanonicalByCode = {};
          stationCodesByCanonical = {};
          stationNameByCode = {};
          stationEnByCode = {};
          for (const s of stationsData) {
              const code = String(s.code || s.编号 || '').trim();
              if (!code) continue;
              stationNameByCode[code] = String(s.name || s.名称 || code);
              stationEnByCode[code] = String(s.en_name || s.英文名 || '');
          }

          const transferGroups = buildTransferGroups(stationsData);
          stationCanonicalByCode = transferGroups.canonicalByCode;
          stationCodesByCanonical = transferGroups.codesByCanonical;
          for (const codes of Object.values(stationCodesByCanonical)) {
              if (codes.length >= 2) codes.forEach(code => stationTransfer.add(code));
          }

          const lineStops = [];
          const lineColors = [];
          const linesByStation = new Map();
          for (let i = 0; i < linesData.length; i++) {
              const line = linesData[i] || {};
              const color = line.color || line.颜色 || '#93a2b7';
              const stopsRaw = Array.isArray(line.stops) ? line.stops : (Array.isArray(line.站点列表) ? line.站点列表 : []);
              const stops = stopsRaw.map(c => String(c || '').trim()).filter(Boolean);
              if (stops.length === 0) continue;
              lineStops.push({ idx: lineStops.length, name: line.name || line.线路名称 || '', color, stops });
              lineColors.push(color);
              for (const c of stops) {
                  const arr = linesByStation.get(c) || [];
                  arr.push(lineStops.length - 1);
                  linesByStation.set(c, arr);
              }
          }

          if (lineStops.length === 0) {
              mapContainer.innerHTML = '<div class="empty-state jr-empty-state"><p>暂无可显示的线路数据。</p></div>';
              return;
          }

          for (const [c, arr] of linesByStation.entries()) {
              const uniq = Array.from(new Set(arr));
              if (uniq.length >= 2) stationTransfer.add(c);
          }
          
          // Build SVG
          const legendW = 210;
          const legendX = 16;
          const legendSwatchW = 22;
          const legendTextX = legendX + legendSwatchW + 10;
          const startX = legendW + 90;
          const baseY = 44;
          const lineGapY = 92;
          const minGapX = 78;

          const occurrences = {};
          for (const li of lineStops) {
              for (let i = 0; i < li.stops.length; i++) {
                  const code = li.stops[i];
                  const canonical = stationCanonicalByCode[code] || code;
                  if (!occurrences[canonical]) occurrences[canonical] = [];
                  occurrences[canonical].push(i * minGapX);
              }
          }
          stationXByCanonical = {};
          for (const canonical of Object.keys(occurrences)) {
              const arr = occurrences[canonical];
              const avg = arr.reduce((a,b)=>a+b,0) / Math.max(1, arr.length);
              stationXByCanonical[canonical] = startX + Math.round(avg);
          }

          for (let pass = 0; pass < 3; pass++) {
              for (const li of lineStops) {
                  let prevX = startX - minGapX;
                  for (const code of li.stops) {
                      const canonical = stationCanonicalByCode[code] || code;
                      const x = stationXByCanonical[canonical] ?? (prevX + minGapX);
                      const nx = Math.max(x, prevX + minGapX);
                      if (stationXByCanonical[canonical] == null || nx > stationXByCanonical[canonical]) stationXByCanonical[canonical] = nx;
                      prevX = stationXByCanonical[canonical];
                  }
              }
          }

          const primaryLineByStation = {};
          for (const [c, arr] of linesByStation.entries()) {
              const uniq = Array.from(new Set(arr)).sort((a,b)=>a-b);
              if (uniq.length === 0) continue;
              primaryLineByStation[c] = uniq[0];
          }

          stationYByCanonical = {};
          for (const c of Object.keys(primaryLineByStation)) {
              const li = primaryLineByStation[c];
              if (li == null) continue;
              stationYByCanonical[c] = baseY + li * lineGapY;
          }

          const allStations = Object.keys(primaryLineByStation);
          if (allStations.length === 0) {
              mapContainer.innerHTML = '<div class="empty-state jr-empty-state"><p>线路数据为空，请稍后再试。</p></div>';
              return;
          }
          const labelShownForCanonical = new Set();
          const transferColorsByStation = {};
          const primaryColorByStation = {};
          for (const c of allStations) {
              const lineIdxs = Array.from(new Set(linesByStation.get(c) || [])).sort((a,b)=>a-b);
              const colors = lineIdxs.map(i => lineStops[i]?.color).filter(Boolean);
              transferColorsByStation[c] = Array.from(new Set(colors));
              primaryColorByStation[c] = colors[0] || '#93a2b7';
          }

          let svgContent = '';

          for (const li of lineStops) {
              const yLine = baseY + li.idx * lineGapY;
              svgContent += `<rect x="${legendX}" y="${yLine-10}" width="${legendSwatchW}" height="10" rx="5" fill="${li.color}" />`;
              svgContent += `<text x="${legendTextX}" y="${yLine-1}" fill="#e5e7eb" font-size="16" font-weight="800">${li.name}</text>`;

              if (li.stops.length >= 2) {
                  const firstX = stationXByCanonical[stationCanonicalByCode[li.stops[0]] || li.stops[0]];
                  let d = `M ${firstX} ${yLine}`;
                  for (let i = 1; i < li.stops.length; i++) {
                      const x = stationXByCanonical[stationCanonicalByCode[li.stops[i]] || li.stops[i]];
                      d += ` L ${x} ${yLine}`;
                  }
                  svgContent += `<path d="${d}" fill="none" stroke="${li.color}" stroke-width="8" stroke-linecap="round" stroke-linejoin="round" />`;
              }
          }

          for (const canonical of Object.keys(stationCodesByCanonical)) {
              const codes = (stationCodesByCanonical[canonical] || []).filter(code => Number.isFinite(stationYByCanonical[code]));
              if (codes.length < 2) continue;
              const ys = codes.map(code => stationYByCanonical[code]).sort((a, b) => a - b);
              const x = stationXByCanonical[canonical];
              const labelY = ys[ys.length - 1] + 34;
              svgContent += `<line x1="${x}" y1="${ys[0]}" x2="${x}" y2="${ys[ys.length - 1]}" stroke="#cbd5e1" stroke-width="12" stroke-linecap="round" opacity="0.98" />`;
              svgContent += `<circle cx="${x}" cy="${(ys[0] + ys[ys.length - 1]) / 2}" r="7" fill="#ffffff" stroke="#111827" stroke-width="3" />`;
              svgContent += `<rect x="${x - 42}" y="${labelY - 16}" width="84" height="24" rx="12" fill="rgba(241,245,249,0.92)" stroke="#cbd5e1" stroke-width="1.5" />`;
              svgContent += `<text x="${x}" y="${labelY}" text-anchor="middle" fill="#334155" font-size="13" font-weight="800">${getStationDisplayName(canonical)}</text>`;
              labelShownForCanonical.add(canonical);
          }

          for (const c of allStations) {
              const canonical = stationCanonicalByCode[c] || c;
              const x = stationXByCanonical[canonical];
              const yNode = stationYByCanonical[c] ?? baseY;
              const name = stationNameByCode[c] || c;
              const isTransfer = stationTransfer.has(c);
              const cls = isTransfer ? 'map-station transfer' : 'map-station';
              const ringSvg = '';
              const primaryColor = primaryColorByStation[c] || '#93a2b7';
              const outer = isTransfer
                ? `<circle cx="${x}" cy="${yNode}" r="13" fill="#ffffff" stroke="${primaryColor}" stroke-width="5" />`
                : `<circle cx="${x}" cy="${yNode}" r="12" fill="#ffffff" stroke="${primaryColor}" stroke-width="5" />`;
              const transferFill = isTransfer ? `<circle cx="${x}" cy="${yNode}" r="7" fill="#ffffff" stroke="#111827" stroke-width="3" />` : '';
              const coreFill = isTransfer ? '#ffffff' : '#ffffff';
              const showLabel = !isTransfer || !labelShownForCanonical.has(canonical);
              const textSvg = showLabel
                ? `<text x="${x}" y="${yNode+28}" text-anchor="middle" fill="#e5e7eb" font-size="14" font-weight="700">${name}</text>`
                : '';
              svgContent += `
                <g class="${cls}" data-code="${c}" onclick="handleStationClick('${c}')" style="cursor:pointer">
                    ${ringSvg}
                    ${outer}
                    ${transferFill}
                    <circle class="node-core" cx="${x}" cy="${yNode}" r="8" fill="${coreFill}" stroke="#111827" stroke-width="3" />
                    ${textSvg}
                </g>
              `;
          }

          const width = Math.max(560, Math.max(...allStations.map(c => stationXByCanonical[stationCanonicalByCode[c] || c] || 0)) + 120);
          const height = Math.max(260, baseY + lineStops.length * lineGapY + 60);
          mapContainer.innerHTML = `<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">${svgContent}</svg>`;
          
          // Bind click events (standard onclick attribute in SVG string might not work in some contexts, but usually fine in innerHTML)
          // Better to add event listeners via delegation
          
      } catch(e) {
          console.error(e);
          mapContainer.innerHTML = '<div class="error">地图加载失败</div>';
      }
  }
  
  window.handleStationClick = (code) => {
      code = String(code || '').trim();
      // Toggle if already selected
      if (selection[0] === code) {
          selection[0] = null;
      } else if (selection[1] === code) {
          selection[1] = null;
      } else {
          // Add new selection
          if (!selection[0]) {
              selection[0] = code;
          } else if (!selection[1]) {
              selection[1] = code;
          } else {
              // When both ends are already selected, start a new selection flow.
              selection[0] = code;
              selection[1] = null;
              currentRoute = [];
              currentRouteTransfers = [];
          }
      }
      
      // Ensure no gaps (if start removed, move end to start)
      if (!selection[0] && selection[1]) {
          selection[0] = selection[1];
          selection[1] = null;
      }
      
      updateSelectionUI();
  };
  
  function normalizeTrips() {
      const raw = Number(tripsEl?.value || 1);
      const trips = Number.isFinite(raw) ? Math.max(1, Math.floor(raw)) : 1;
      if (tripsEl) tripsEl.value = String(trips);
      return trips;
  }

  function getStationDisplayName(code) {
      return stationNameByCode[String(code || '').trim()] || String(code || '').trim();
  }

  function getStationNameKey(code) {
      const cn = getStationDisplayName(code).replace(/\s+/g, '');
      const en = String(stationEnByCode[String(code || '').trim()] || '').toLowerCase().replace(/\s+/g, '');
      return `${cn}|${en}`;
  }

  function buildTransferGroups(stationsData) {
      const parent = {};
      const codesByName = {};
      const find = (code) => {
          if (!parent[code]) parent[code] = code;
          if (parent[code] !== code) parent[code] = find(parent[code]);
          return parent[code];
      };
      const union = (a, b) => {
          if (!a || !b) return;
          const ra = find(a);
          const rb = find(b);
          if (ra !== rb) parent[rb] = ra;
      };

      for (const s of stationsData) {
          const code = String(s?.code || s?.编号 || '').trim();
          if (!code) continue;
          parent[code] = code;
          const cn = String(s?.name || s?.名称 || '').replace(/\s+/g, '');
          const en = String(s?.en_name || s?.英文名 || '').toLowerCase().replace(/\s+/g, '');
          const nameKey = `${cn}|${en}`;
          if (cn || en) {
              if (!codesByName[nameKey]) codesByName[nameKey] = [];
              codesByName[nameKey].push(code);
          }
      }

      for (const s of stationsData) {
          const code = String(s?.code || s?.编号 || '').trim();
          if (!code) continue;
          const list = Array.isArray(s?.transfer_to) ? s.transfer_to : [];
          for (const item of list) {
              const to = String((typeof item === 'string') ? item : (item?.code || item?.station || item?.id || item?.[0] || '')).trim();
              if (to) union(code, to);
          }
      }

      for (const codes of Object.values(codesByName)) {
          if (!Array.isArray(codes) || codes.length < 2) continue;
          for (let i = 1; i < codes.length; i++) {
              union(codes[0], codes[i]);
          }
      }

      const byRoot = {};
      for (const code of Object.keys(parent)) {
          const root = find(code);
          if (!byRoot[root]) byRoot[root] = [];
          byRoot[root].push(code);
      }

      const canonicalByCode = {};
      const codesByCanonical = {};
      for (const codes of Object.values(byRoot)) {
          codes.sort((a, b) => a.localeCompare(b));
          const canonical = codes[0];
          codesByCanonical[canonical] = codes;
          for (const code of codes) canonicalByCode[code] = canonical;
      }
      return { canonicalByCode, codesByCanonical };
  }

  function buildDisplayRouteCodes(route, from, to) {
      const middle = Array.isArray(route) ? route.filter(c => c && c !== from && c !== to) : [];
      const merged = [];
      for (const code of [from, ...middle, to].filter(Boolean)) {
          const prev = merged[merged.length - 1];
          const prevName = prev ? getStationDisplayName(prev).replace(/\s+/g, '') : '';
          const nextName = getStationDisplayName(code).replace(/\s+/g, '');
          if (prev && prevName && prevName === nextName) continue;
          merged.push(code);
      }
      return merged;
  }

  function updateSelectionUI(skipPreview = false) {
      if (!(selection[0] && selection[1])) {
          currentRoute = [];
          currentRouteTransfers = [];
      }

      // Update Inputs
      fromEl.value = selection[0] || '';
      toEl.value = selection[1] || '';
      
      // Update Displays with Chinese names
      const getName = (code) => {
          return stationNameByCode[String(code || '').trim()] || code;
      };

      $('#fromDisplay').textContent = selection[0] ? getName(selection[0]) : '请在上方地图选择';
      $('#toDisplay').textContent = selection[1] ? getName(selection[1]) : '请在上方地图选择';
      
      // Update Map Styles
      document.querySelectorAll('.map-station').forEach(el => {
          const code = el.getAttribute('data-code');
          el.classList.remove('start', 'end', 'selected', 'route', 'route-transfer');
          if(code === selection[0]) el.classList.add('start');
          if(code === selection[1]) el.classList.add('end');
      });

      if (Array.isArray(currentRoute) && currentRoute.length > 0) {
          for (const c of currentRoute) {
              const el = document.querySelector(`.map-station[data-code="${c}"]`);
              if (el) el.classList.add('route');
          }
      }
      if (Array.isArray(currentRouteTransfers) && currentRouteTransfers.length > 0) {
          for (const c of currentRouteTransfers) {
              const el = document.querySelector(`.map-station[data-code="${c}"]`);
              if (el) el.classList.add('route-transfer');
          }
      }
      
      // Auto preview if both selected
      if(!skipPreview && selection[0] && selection[1]) previewPrice();
  }

  // Load Map on Start
  renderSystemMap();

  async function previewPrice(force = false){
    const seq = ++previewSeq;
    const from = (fromEl.value||'').trim();
    const to = (toEl.value||'').trim();
    const type = document.querySelector('input[name="trainType"]:checked').value;
    const trips = normalizeTrips();
    if(!from || !to){ priceBox.innerHTML = '<div class="empty-state jr-empty-state"><p>请选择起点与终点</p></div>'; return; }
    const previewKey = `${from}|${to}|${type}|${trips}`;
    if (!force && previewKey === lastPreviewKey) return;
    lastPreviewKey = previewKey;
    
    try{
      const fare = await api.fareQuery(from, to);
      if (seq !== previewSeq) return;
      if(fare && (fare.error || fare['错误'])){ priceBox.innerHTML = '<div class="list-item jr-result-row"><span class="k">提示</span><span class="v">未找到对应票价</span></div>'; return; }
      const resolvedFrom = String(fare?.from_code || '').trim();
      const resolvedTo = String(fare?.to_code || '').trim();
      if ((resolvedFrom && resolvedFrom !== from) || (resolvedTo && resolvedTo !== to)) {
        lastPreviewKey = '';
        priceBox.innerHTML = `
          <div class="empty-state jr-empty-state">
            <p>站点解析异常，当前后端返回的站码与页面选择不一致。</p>
            <p>已选：${getStationDisplayName(from)}(${from}) -> ${getStationDisplayName(to)}(${to})</p>
            <p>返回：${getStationDisplayName(resolvedFrom)}(${resolvedFrom || '-'}) -> ${getStationDisplayName(resolvedTo)}(${resolvedTo || '-'})</p>
            <p>请先部署最新后端并清理 CDN 缓存后再试。</p>
          </div>
        `;
        currentRoute = [];
        currentRouteTransfers = [];
        updateSelectionUI(true);
        return;
      }
      const discRaw = Number(fare?.discount ?? fare?.['折扣'] ?? 1);
      const disc = Number.isFinite(discRaw) && discRaw > 0 ? discRaw : 1;
      const base = (type==='Express')
        ? Number(fare?.express_fare ?? fare?.['特快票价'] ?? 0)
        : Number(fare?.regular_fare ?? fare?.['常规票价'] ?? 0);
      const discountedRaw = (type==='Express')
        ? (fare?.discounted_express_fare ?? fare?.['优惠后特快票价'])
        : (fare?.discounted_regular_fare ?? fare?.['优惠后常规票价']);
      const discountedSingle = Number(discountedRaw ?? Math.floor(base * disc) ?? 0);
      const price = discountedSingle * trips;

      const routeKey = (type === 'Express') ? 'express_path' : 'regular_path';
      const transferKey = (type === 'Express') ? 'express_transfers' : 'regular_transfers';
      currentRoute = Array.isArray(fare?.[routeKey]) ? fare[routeKey] : [];
      currentRouteTransfers = Array.isArray(fare?.[transferKey]) ? fare[transferKey] : [];
      const displayRoute = buildDisplayRouteCodes(currentRoute, from, to);
      const routeText = displayRoute.length > 0 ? displayRoute.map(getStationDisplayName).join(' → ') : '';
      const transferStops = [];
      const seenTransferNames = new Set();
      for (const code of currentRouteTransfers) {
        if (code === from || code === to) continue;
        const nameKey = getStationDisplayName(code).replace(/\s+/g, '');
        if (!nameKey || seenTransferNames.has(nameKey)) continue;
        seenTransferNames.add(nameKey);
        transferStops.push(code);
      }
      const transferHtml = transferStops.length
        ? `<div class="jr-transfer-chips">${transferStops.map(c => `<span class="badge badge-secondary">${getStationDisplayName(c)}</span>`).join('')}</div>`
        : `<span class="text-muted">无</span>`;

      priceBox.innerHTML = `
        <div class="list-item jr-result-row"><span class="k">原始票价</span><span class="v">${base}</span></div>
        <div class="list-item jr-result-row"><span class="k">优惠后票价</span><span class="v">${discountedSingle}</span></div>
        <div class="list-item jr-result-row"><span class="k">折扣</span><span class="v">-${Math.round((1-disc)*100)}%</span></div>
        ${routeText ? `<div class="list-item jr-result-row jr-result-multiline"><span class="k">路径</span><span class="v jr-route-text">${routeText}</span></div>` : ``}
        <div class="list-item jr-result-row jr-result-multiline"><span class="k">换乘</span><span class="v jr-route-text">${transferHtml}</span></div>
        <div class="list-item jr-result-row jr-total-row">
            <span class="k">总价</span><span class="v jr-total-amount">${price}</span>
        </div>
      `;
      updateSelectionUI(true);
    }catch(e){
      lastPreviewKey = '';
      priceBox.innerHTML = '<div class="empty-state jr-empty-state"><p>票价预估失败，请稍后再试。</p></div>';
    }
  }

  // Create Order with auto-preview
  async function createOrder(){
    const from = (fromEl.value||'').trim();
    const to = (toEl.value||'').trim();
    const type = document.querySelector('input[name="trainType"]:checked').value;
    const trips = normalizeTrips();
    const ride_date = new Date().toISOString().slice(0, 10);
    if(!from || !to){ alert('请完整填写信息'); return; }
    
    // Auto-fetch price before creating
    await previewPrice(true);

    try{
      const payload = { start: from, terminal: to, train_type: type, trips, ride_date };
      const res = await fetch('/api/public/orders', { method:'POST', headers:{ 'Content-Type':'application/json' }, body: JSON.stringify(payload) });
      const r = await res.json();
      if(r && r.ok){
        // Link to external subdomain or local page
        const buildTokenLink = (code) => {
            if (location.hostname.includes('fse-media.group')) {
                return `https://ticket.fse-media.group/token?code=${encodeURIComponent(code)}`;
            }
            return `/token.html?code=${encodeURIComponent(code)}`;
        };
        
        voucherBox.innerHTML = `
          <div class="voucher-container jr-voucher-panel">
            <div class="jr-voucher-meta">凭证码</div>
            <div class="voucher-code">${r.code}</div>
            <div class="voucher-hint">请在游戏内任意售票机选择线上订票并输入该凭证码兑票。</div>
            <div class="toolbar jr-voucher-actions">
                <a class="btn jr-detail-btn" href="${buildTokenLink(r.code)}" target="_self"><i class="fas fa-eye"></i> 详情</a>
            </div>
          </div>
        `;
      }else{
        alert('创建失败: ' + (r.error || '未知错误'));
      }
    }catch(e){ alert('创建失败'); }
  }

  const btnPreview = $('#previewPrice');
  if(btnPreview) btnPreview.onclick = previewPrice;
  
  const btnCreate = $('#createOrder');
  if(btnCreate) btnCreate.onclick = createOrder;
  // Listen for Type change to auto-update price
  document.querySelectorAll('input[name="trainType"]').forEach(el => {
      el.onchange = () => { if(fromEl.value && toEl.value) previewPrice(); };
  });
  if (tripsEl) {
      tripsEl.oninput = () => { if(fromEl.value && toEl.value) previewPrice(); };
      tripsEl.onchange = () => { normalizeTrips(); if(fromEl.value && toEl.value) previewPrice(); };
  }
})();
