<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>OKELaundry - Customer Tracking</title>
  @include('partials.favicon')
  @include('partials.brand-fonts')
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
  <style>
    :root{
      --brand-deep:#1f7fb7;--brand-main:#3aa5e6;--brand-accent:#4BB8FA;--brand-soft:#7BCBF6;
      --brand-tint:#C4E2F5;--brand-tint-2:#E5F2FB;
      --blue:#4BB8FA;--blue-soft:#C4E2F5;--green:#22c55e;--danger:#dc2626;--text:#0F172A;
      --muted:#5B6B80;--line:#D9E6F2;--bg:#F4F9FE;--card:#FFFFFF;--shadow:0 14px 30px rgba(31,127,183,.10);
      font-family:'Plus Jakarta Sans',Inter,Segoe UI,Roboto,system-ui,sans-serif
    }
    *{box-sizing:border-box} body{margin:0;background:linear-gradient(180deg,#F4F9FE 0%,#E5F2FB 100%);color:var(--text)}
    button,input{font:inherit}.page-wrap{max-width:1280px;margin:0 auto;padding:24px}.screen{position:relative;background:var(--card);border:1px solid #D9E6F2;border-radius:24px;overflow:hidden;box-shadow:var(--shadow)}
    .brand-strip{background:linear-gradient(135deg,rgba(255,255,255,.08),rgba(255,255,255,0) 45%),linear-gradient(90deg,var(--brand-deep),var(--brand-main),var(--brand-accent));color:#fff;padding:18px 28px;display:flex;justify-content:space-between;align-items:center}
    .brand-sub{font-size:14px;opacity:.95}.brand-mini{display:flex;align-items:center;gap:10px;font-weight:700}.logo-dot{width:22px;height:22px;border-radius:50%;background:#fff1;border:2px solid #fff;box-shadow:inset 0 0 0 4px #C4E2F5}
    .customer-hero{padding:20px 28px;background:linear-gradient(180deg,rgba(31,127,183,.96),rgba(58,165,230,.92)),radial-gradient(circle at 20% 20%,rgba(255,255,255,.10),transparent 32%)}
    .slider-shell{display:grid;grid-template-columns:56px 1fr 56px;gap:14px;align-items:center}
    .slider-arrow{
      height:54px;width:54px;border-radius:50%;
      border:1px solid rgba(255,255,255,.55);
      background:rgba(255,255,255,.22);color:#fff;font-size:26px;font-weight:800;
      display:grid;place-items:center;cursor:pointer;
      backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
      box-shadow:0 8px 22px rgba(12,36,51,.28);
      transition:transform .25s cubic-bezier(.22,.8,.2,1), background .25s ease, box-shadow .25s ease;
      z-index:3;
    }
    .slider-arrow:hover{transform:scale(1.08);background:#fff;color:var(--brand-deep);box-shadow:0 12px 28px rgba(12,36,51,.32)}
    .slider-arrow:active{transform:scale(.95)}
    .slider-viewport{overflow:hidden}
    .slider-track{display:flex;gap:16px;transition:transform .6s cubic-bezier(.22,.8,.2,1);will-change:transform}
    .slide-card{flex:0 0 calc((100% - 32px) / 3);height:240px;border-radius:18px;overflow:hidden;border:1px solid rgba(255,255,255,.2);position:relative}
    .slider-track.banner-mode .slide-card{height:auto;aspect-ratio:3 / 1;border:none}
    .slide-card.banner{background:#0c2433}
    .slide-card.banner img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .9s cubic-bezier(.22,.8,.2,1),filter .4s ease}
    .slide-card.banner:hover img{transform:scale(1.06);filter:saturate(1.08)}
    .slide-card.banner.has-overlay::before{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.18) 0%,rgba(0,0,0,0) 30%,rgba(0,0,0,0) 60%,rgba(0,0,0,.78) 100%);pointer-events:none;z-index:1}
    .slide-card.banner .slide-overlay{position:absolute;left:0;right:0;bottom:0;padding:16px 18px 18px;color:#fff;z-index:2;transform:translateY(0);transition:transform .35s ease}
    .slide-card.banner .slide-overlay h3{margin:0;font-size:19px;line-height:1.2;font-weight:800;letter-spacing:-0.01em;text-shadow:0 2px 8px rgba(0,0,0,.45)}
    .slide-card.banner .slide-overlay .caption{color:#fff;opacity:.94;font-size:13px;margin-top:6px;text-shadow:0 1px 4px rgba(0,0,0,.45)}
    .slide-card.red{background:linear-gradient(135deg,#1f7fb7,#4BB8FA)}.slide-card.center{background:#E5F2FB}.slide-card.info{background:linear-gradient(135deg,#3aa5e6,#7BCBF6)}
    .slide-inner{padding:22px;height:100%;display:flex;flex-direction:column;justify-content:space-between}.slide-card h3{margin:0;font-size:20px;line-height:1.1}.slide-card.red h3,.slide-card.info h3{color:#fff}
    .task-row{display:flex;gap:8px}.task-box{flex:1;background:#fff;border-radius:14px;padding:12px;text-align:center;font-size:12px;font-weight:700;min-height:72px}
    .hanger-box{background:#fff;border-radius:16px;padding:14px;height:120px;display:flex;align-items:center;justify-content:center;color:#1f7fb7;font-weight:800;font-size:28px;border:1px solid #C4E2F5}
    .caption{color:#fff;opacity:.92;font-size:14px}.dots{display:flex;justify-content:center;align-items:center;margin-top:14px}
    .customer-body{padding:30px 28px 34px;background:var(--bg)}.tracking-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:24px;align-items:start}.panel{background:#fff;border:1px solid var(--line);border-radius:22px;padding:22px;box-shadow:0 6px 16px rgba(36,18,18,.04)}
    .section-title{margin:0 0 16px;font-size:32px;letter-spacing:-0.03em}.track-row{display:flex;gap:12px}.input-main{width:100%;border:1px solid #D9E6F2;border-radius:12px;padding:14px 16px;background:#fff;color:var(--text);transition:border-color .2s ease}.input-main:focus{outline:none;border-color:var(--brand-accent);box-shadow:0 0 0 3px rgba(75,184,250,.18)}
    .btn-primary,.btn-secondary{border:none;border-radius:12px;padding:14px 18px;font-weight:700;cursor:pointer;transition:.2s ease}.btn-primary{background:linear-gradient(135deg,var(--blue),#2f8fff);color:#fff;box-shadow:0 10px 20px rgba(74,103,255,.18)}.btn-primary:hover{transform:translateY(-1px)}.btn-primary:active{transform:translateY(1px)}.btn-primary:disabled{opacity:.6;cursor:not-allowed;transform:none}
    .btn-secondary{background:linear-gradient(135deg,var(--brand-main),var(--brand-accent));color:#fff;box-shadow:0 10px 20px rgba(75,184,250,.28)}.btn-secondary:hover{transform:translateY(-1px)}.small-note{font-size:13px;color:var(--muted);margin-top:10px;line-height:1.55}
    .btn-share-loc{margin-top:12px;display:inline-flex;align-items:center;gap:6px;padding:10px 14px;border:1px solid #C4E2F5;background:#E5F2FB;color:#1f7fb7;font-weight:700;font-size:13px;border-radius:10px;cursor:pointer;transition:background .15s ease}
    .btn-share-loc:hover{background:#C4E2F5}
    .btn-share-loc:disabled{opacity:.6;cursor:not-allowed}
    .guide-card{padding:0;overflow:hidden}.guide-head{background:linear-gradient(135deg,var(--brand-main),var(--brand-soft));color:#fff;padding:16px 20px;font-size:24px;font-weight:800}.guide-body{padding:22px 24px;background:#fff}.guide-body ol{margin:0;padding-left:20px;line-height:1.8}.guide-body li strong{color:var(--brand-accent)}
    .order-card{margin-top:22px;background:#fff;border:1px solid #D9E6F2;border-radius:22px;padding:20px 22px;display:none}.order-card.rejected{background:#fff6f6;border-color:#f1c7c7}.order-top{display:flex;justify-content:space-between;gap:16px;align-items:start}
    .meta-muted{font-size:13px;color:var(--muted)}.order-status{font-size:15px;font-weight:800;text-transform:capitalize}.order-status.reject{color:var(--danger)}.cost{font-size:16px;font-weight:800;margin-top:4px}
    .progress-wrap{margin-top:16px}.progress{height:8px;border-radius:999px;background:#D9E6F2;position:relative;overflow:hidden}.progress-bar{position:absolute;left:0;top:0;height:100%;width:0%;background:linear-gradient(90deg,var(--blue),#7BCBF6);border-radius:999px;transition:width .5s ease}
    .step-row{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:14px}.step{text-align:center;padding-top:8px;color:#8a98a8}.step .icon{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;margin:0 auto 8px;background:#E5F2FB;border:1px solid #C4E2F5;font-size:18px;transition:all .3s ease}
    .step.active .icon{background:var(--blue-soft);border-color:var(--brand-accent);color:var(--blue)}.step.complete .icon{background:#dcfce7;border-color:#86efac;color:var(--green)}.sub-process{display:none;margin-top:16px;padding:16px;border-radius:16px;background:#F4F9FE;border:1px solid #D9E6F2}
    .stage-row{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:12px;font-size:12px;text-align:center;color:#7e7171}#trackingMapWrap{display:none;margin-top:18px}.map-card{background:#fff;border:1px solid var(--line);border-radius:22px;padding:18px}.map-card h3{margin:0 0 10px}
    #trackingMap{height:360px;border-radius:16px;overflow:hidden;background:#E5F2FB}.map-note{font-size:12px;color:var(--muted);margin-top:8px}.footer-note{margin-top:24px;padding-top:16px;border-top:1px solid #D9E6F2;font-size:12px;color:#7a8597}
    .wa-fab{position:fixed;right:24px;bottom:24px;z-index:50;display:inline-flex;align-items:center;gap:10px;text-decoration:none;padding:14px 18px;border-radius:999px;background:#25D366;color:#fff;font-weight:800;font-size:15px;box-shadow:0 14px 30px rgba(37,211,102,.38);transition:transform .2s ease,box-shadow .2s ease}
    .wa-fab:hover{transform:translateY(-2px);box-shadow:0 18px 36px rgba(37,211,102,.46)}
    .wa-fab:active{transform:translateY(0)}
    .wa-fab svg{width:26px;height:26px;fill:#fff;flex:none}
    .wa-fab .wa-label{white-space:nowrap}
    .ic{width:20px;height:20px;display:inline-block;vertical-align:middle;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
    .step .icon .ic{width:20px;height:20px}
    .courier-icon .ic{width:18px;height:18px}
    .sync-badge,.sync-dot,.sync-flash{display:none}
    .loading-inline{display:none;padding:20px;text-align:center;color:var(--muted);font-size:14px}.loading-inline.show{display:block}
    .courier-card{display:none;margin-top:16px;padding:14px;border-radius:14px;background:#F4F9FE;border:1px solid #D9E6F2;align-items:center;gap:12px}
    .history-wrap{margin-top:18px;padding:16px;border-radius:16px;background:#fff;border:1px solid var(--line)}
    .history-title{font-weight:800;font-size:15px;margin-bottom:12px;color:var(--brand-deep)}
    .history-list{display:flex;flex-direction:column;gap:0}
    .history-item{position:relative;padding:0 0 16px 22px;border-left:2px solid #e8d9d9}
    .history-item:last-child{padding-bottom:0;border-left-color:transparent}
    .history-item::before{content:'';position:absolute;left:-7px;top:2px;width:12px;height:12px;border-radius:50%;background:var(--brand-accent);border:2px solid #fff;box-shadow:0 0 0 2px #e8d9d9}
    .history-item:first-child::before{background:var(--green,#2ECC71)}
    .history-status{font-weight:700;font-size:14px;text-transform:capitalize}
    .history-time{font-size:12px;color:var(--muted);margin-top:2px}
    .courier-card .courier-icon{background:var(--blue-soft);color:var(--blue);width:40px;height:40px;border-radius:50%;display:grid;place-items:center;font-size:18px}
    @media (max-width:1200px){
      .slide-card{height:210px}
    }
    @media (max-width:980px){
      .tracking-grid{grid-template-columns:1fr}
      .slider-shell{grid-template-columns:1fr}
      .slider-arrow{display:none}
      .slide-card{flex:0 0 100%;height:200px}
      .track-row{flex-direction:column}
      .order-top{flex-direction:column}
    }
    @media (max-width:560px){
      .slide-card{height:170px}
    }
  </style>
</head>
<body>
  <div class="page-wrap">
    <section class="screen">
      <div class="brand-strip"><div class="brand-mini">@include('partials.brand-logo', ['size' => 26])</div><div class="brand-sub">Cuci Ekspres - Pasti Beres</div></div>
      <div class="customer-hero">
        <div class="slider-shell">
          <button class="slider-arrow" id="prevSlide" type="button" aria-label="Slide sebelumnya"><span style="transform:translateX(-1px)">‹</span></button>
          <div class="slider-viewport">
            <div class="slider-track" id="sliderTrack">
              <div class="slide-card red"><div class="slide-inner"><h3>OKE TIME!</h3><div class="task-row"><div class="task-box">FOLLOW</div><div class="task-box">COMMENT</div><div class="task-box">MENANGKAN HADIAH</div></div><div class="caption">Promo & info seputar laundry</div></div></div>
              <div class="slide-card center"><div class="slide-inner"><div class="hanger-box">OKE LAUNDRY</div><div style="text-align:center;color:#1f7fb7;font-weight:700">Cuci express, Pasti Beres</div></div></div>
              <div class="slide-card info"><div class="slide-inner"><h3>CUCI EXPRESS, PASTI BERES!</h3><div style="font-size:14px;color:#fff;opacity:.92">Cuci kiloan • Dry clean • Cuci sepatu • Antar jemput</div><div class="caption">Katalog & layanan unggulan</div></div></div>
              <div class="slide-card red"><div class="slide-inner"><h3>PROMO MEMBER</h3><div style="font-size:14px;color:#fff;opacity:.92">Member dapat info promo rutin dan prioritas proses.</div><div class="caption">Program loyalti pelanggan</div></div></div>
              <div class="slide-card center"><div class="slide-inner"><div class="hanger-box">FREE PICKUP</div><div style="text-align:center;color:#1f7fb7;font-weight:700">Gratis jemput untuk area dekat toko</div></div></div>
              <div class="slide-card info"><div class="slide-inner"><h3>KATALOG CEPAT</h3><div style="font-size:14px;color:#fff;opacity:.92">Geser banner untuk lihat promo dan layanan lain.</div><div class="caption">Promo & katalog layanan</div></div></div>
            </div>
            <div class="dots" id="sliderDots" aria-label="Navigasi slide"></div>
          </div>
          <button class="slider-arrow" id="nextSlide" type="button" aria-label="Slide berikutnya"><span style="transform:translateX(1px)">›</span></button>
        </div>
      </div>
      <div class="customer-body">
        <div class="tracking-grid">
          <div>
            <div class="panel">
              <h2 class="section-title">Pelacakan Pesanan</h2>
              <div class="track-row">
                <input id="resiInput" class="input-main" placeholder="Masukkan nomor order (contoh: OKE001)" aria-label="Nomor resi order" />
                <button id="btnLacak" class="btn-primary" type="button">Lacak</button>
              </div>
              <div class="small-note">Masukkan nomor order lalu klik tombol Lacak untuk melihat status, detail proses, dan informasi ongkir. Data ditarik langsung dari database server secara real-time.</div>
            </div>
            <div class="loading-inline" id="trackingLoading">Memuat data pesanan...</div>
            <div id="orderResult" class="order-card">
              <div class="order-top">
                <div>
                  <div id="rNomor" style="font-size:22px;font-weight:800"></div>
                  <div id="rCust" class="meta-muted"></div>
                  <div style="margin-top:8px">Catatan: <span id="rNote">-</span></div>
                </div>
                <div style="text-align:right">
                  <div id="rStatus" class="order-status"></div>
                  <div id="rCost" class="cost"></div>
                </div>
              </div>
              <div class="progress-wrap">
                <div class="progress"><div id="bar" class="progress-bar"></div></div>
                <div class="step-row">
                  <div id="s1" class="step"><div class="icon"><svg class="ic" viewBox="0 0 24 24"><path d="M1 3h15v13H1z"/><path d="M16 8h4l3 3v5h-7z"/><circle cx="5.5" cy="18.5" r="2.5"/><circle cx="18.5" cy="18.5" r="2.5"/></svg></div><div>Jemput</div></div>
                  <div id="s2" class="step"><div class="icon"><svg class="ic" viewBox="0 0 24 24"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><path d="M3.27 6.96 12 12.01l8.73-5.05M12 22.08V12"/></svg></div><div>Proses</div></div>
                  <div id="s3" class="step"><div class="icon"><svg class="ic" viewBox="0 0 24 24"><circle cx="6" cy="19" r="2"/><circle cx="18" cy="5" r="2"/><path d="M8 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h3"/></svg></div><div>Antar</div></div>
                  <div id="s4" class="step"><div class="icon"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M9 12l2 2 4-4"/></svg></div><div>Selesai</div></div>
                </div>
              </div>
              <div id="subProcess" class="sub-process"><div class="meta-muted">Detail Proses: <strong id="subLabel"></strong></div><div class="progress" style="margin-top:10px"><div id="subBar" class="progress-bar"></div></div><div class="stage-row"><div>Cuci</div><div>Kering</div><div>Setrika</div></div></div>

              <div id="historyWrap" class="history-wrap" style="display:none">
                <div class="history-title">Riwayat Status</div>
                <div id="historyList" class="history-list"></div>
              </div>

              <div id="courierDetails" class="courier-card">
                <div class="courier-icon"><svg class="ic" viewBox="0 0 24 24"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></div>
                <div>
                  <div style="font-size:12px;color:var(--muted);font-weight:600;" id="courierRoleLabel">Kurir Penjemput</div>
                  <div style="font-weight:800;font-size:15px;" id="courierNameLabel">-</div>
                  <div style="font-size:13px;color:var(--muted);" id="courierPhoneLabel">-</div>
                </div>
              </div>

              <button id="btnReset" class="btn-secondary" type="button" style="margin-top:16px;display:none">Lacak Lagi</button>
            </div>
            <div id="trackingMapWrap" class="map-card"><h3>Peta Jangkauan</h3><div id="trackingMap"></div><div class="map-note">Zona hijau = radius 2 km (gratis ongkir). Area peta tetap netral agar informasi lokasi lebih jelas.</div></div>
          </div>
          <div class="panel guide-card"><div class="guide-head">Panduan Pelacakan</div><div class="guide-body"><ol><li>Masukkan nomor order, misalnya <strong>OKE001</strong>.</li><li>Klik tombol <strong>Lacak</strong> untuk melihat status dan detail pesanan.</li><li>Status mengikuti alur: <strong>Jemput</strong> → <strong>Proses</strong> → <strong>Antar</strong> → <strong>Selesai</strong>.</li><li>Zona ongkir: jarak ≤ 2 km = <strong>Gratis Ongkir</strong>, jarak &gt; 2 km = <strong>Biaya Ongkir</strong>.</li><li>Jika nomor tidak ditemukan, hubungi admin atau cek kembali format nomor resi.</li></ol></div></div>
        </div>
        <div class="footer-note">©2025 OKE Laundry — Sistem Informasi Pelacakan dan Pengelolaan Pesanan Laundry Berbasis Web. Dibangun dengan Laravel, MySQL, Leaflet.js & OpenStreetMap. · <a href="/tentang" style="color:var(--brand-deep);font-weight:700;text-decoration:none">Tentang OKE Laundry</a></div>
      </div>
    </section>
  </div>
  <a class="wa-fab" href="https://wa.me/6281234567890?text=Halo%20OKE%20Laundry%2C%20saya%20mau%20bertanya%20soal%20pesanan%20laundry" target="_blank" rel="noopener" aria-label="Chat WhatsApp OKE Laundry">
    <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12.04 2C6.58 2 2.13 6.45 2.13 11.91c0 1.75.46 3.45 1.32 4.95L2 22l5.25-1.38c1.45.79 3.08 1.21 4.79 1.21h.01c5.46 0 9.91-4.45 9.91-9.91 0-2.65-1.03-5.14-2.9-7.01A9.82 9.82 0 0 0 12.04 2zm0 18.15h-.01c-1.52 0-3.01-.41-4.3-1.18l-.31-.18-3.12.82.83-3.04-.2-.31a8.21 8.21 0 0 1-1.26-4.36c0-4.54 3.7-8.23 8.24-8.23 2.2 0 4.27.86 5.82 2.42a8.18 8.18 0 0 1 2.41 5.82c0 4.54-3.69 8.24-8.23 8.24zm4.52-6.16c-.25-.12-1.47-.72-1.69-.81-.23-.08-.39-.12-.56.12-.16.25-.64.81-.78.97-.14.17-.29.19-.54.06-.25-.12-1.05-.39-2-1.23-.74-.66-1.24-1.47-1.38-1.72-.14-.25-.02-.38.11-.51.11-.11.25-.29.37-.43.12-.14.16-.25.25-.41.08-.17.04-.31-.02-.43-.06-.12-.56-1.35-.77-1.85-.2-.48-.41-.42-.56-.43h-.48c-.17 0-.43.06-.66.31-.23.25-.86.85-.86 2.07 0 1.22.89 2.4 1.01 2.56.12.17 1.75 2.67 4.23 3.74.59.26 1.05.41 1.41.52.59.19 1.13.16 1.56.1.48-.07 1.47-.6 1.68-1.18.21-.58.21-1.07.14-1.18-.06-.11-.22-.17-.47-.29z"/></svg>
    <span class="wa-label">Chat WhatsApp</span>
  </a>
  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
  <script>
    // === Utility ===
    function escapeHtml(str) {
      if (!str) return '';
      const div = document.createElement('div');
      div.textContent = str;
      return div.innerHTML;
    }

    function renderHistory(history) {
      if (!historyWrap || !historyList) return;
      if (!history || !history.length) {
        historyWrap.style.display = 'none';
        historyList.innerHTML = '';
        return;
      }
      // Tampilkan terbaru di atas
      const items = history.slice().reverse().map(h => {
        let label = h.status.charAt(0).toUpperCase() + h.status.slice(1);
        if (h.status === 'proses' && h.stage) {
          label += ' (' + h.stage.charAt(0).toUpperCase() + h.stage.slice(1) + ')';
        }
        return '<div class="history-item"><div class="history-status">' + escapeHtml(label) + '</div><div class="history-time">' + escapeHtml(h.time) + '</div></div>';
      }).join('');
      historyList.innerHTML = items;
      historyWrap.style.display = 'block';
    }

    // === State ===
    let mitra = { lat: -6.39778, lng: 106.79769, free_radius_km: 2 };
    let activeTrackingNumber = '';
    const syncBadge = null;
    const syncText = null;

    // === Map ===
    const trackingMap = L.map('trackingMap').setView([mitra.lat, mitra.lng], 14);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '&copy; OpenStreetMap' }).addTo(trackingMap);
    let mitraCircle = L.circle([mitra.lat, mitra.lng], { radius: 2000, color: 'green', fillOpacity: 0.08 }).addTo(trackingMap);
    let mitraMarker = L.marker([mitra.lat, mitra.lng]).addTo(trackingMap).bindPopup('OKE Laundry (Mitra)');
    let trackingMarker = null;

    (async function loadMitra() {
      try {
        const res = await fetch('/api/mitra');
        if (!res.ok) return;
        const m = await res.json();
        mitra = { lat: parseFloat(m.lat), lng: parseFloat(m.lng), free_radius_km: parseFloat(m.free_radius_km) || 0 };
        mitraMarker.setLatLng([mitra.lat, mitra.lng]).bindPopup(m.name || 'OKE Laundry (Mitra)');
        mitraCircle.setLatLng([mitra.lat, mitra.lng]).setRadius((mitra.free_radius_km || 2) * 1000);
        trackingMap.setView([mitra.lat, mitra.lng], 14);
      } catch (_) { /* pakai default */ }
    })();

    // === DOM References ===
    const resiInput = document.getElementById('resiInput'),
          btnLacak = document.getElementById('btnLacak'),
          orderResult = document.getElementById('orderResult'),
          trackingMapWrap = document.getElementById('trackingMapWrap'),
          trackingLoading = document.getElementById('trackingLoading'),
          rNomor = document.getElementById('rNomor'),
          rCust = document.getElementById('rCust'),
          rNote = document.getElementById('rNote'),
          rStatus = document.getElementById('rStatus'),
          rCost = document.getElementById('rCost'),
          bar = document.getElementById('bar'),
          subProcess = document.getElementById('subProcess'),
          subBar = document.getElementById('subBar'),
          subLabel = document.getElementById('subLabel'),
          btnReset = document.getElementById('btnReset'),
          courierDetails = document.getElementById('courierDetails');
    const historyWrap = document.getElementById('historyWrap'),
          historyList = document.getElementById('historyList');

    function flashSync(_message) { /* badge dihapus, no-op */ }

    // === Tracking Logic ===
    async function renderTrackingByNumber(rawValue, options = {}) {
      const raw = (rawValue || '').trim();
      if (!raw) {
        if (!options.silent) alert('Masukkan nomor order terlebih dahulu');
        return;
      }

      if (!options.silent) {
        trackingLoading.classList.add('show');
        btnLacak.disabled = true;
      }

      try {
        const res = await fetch('/api/track/' + encodeURIComponent(raw));
        if (!res.ok) {
          if (!options.silent) {
            orderResult.style.display = 'none';
            trackingMapWrap.style.display = 'none';
            alert('Pesanan dengan nomor "' + raw + '" tidak ditemukan. Periksa kembali nomor resi Anda.');
          }
          return;
        }
        const found = await res.json();

        activeTrackingNumber = found.nomor;
        resiInput.value = found.nomor;
        orderResult.style.display = 'block';
        orderResult.classList.remove('rejected');
        rStatus.classList.remove('reject');
        rNomor.textContent = found.nomor;
        rCust.textContent = found.nama + ' • ' + found.date;
        rNote.textContent = found.note || '-';
        rCost.textContent = found.cost > 0 ? 'Rp ' + found.cost.toLocaleString() : 'Gratis Ongkir';
        renderHistory(found.history);

        const steps = ['jemput','proses','antar','selesai'];
        const idx = steps.indexOf(found.status);

        if (found.status === 'ditolak') {
          rStatus.textContent = 'Ditolak';
          rStatus.classList.add('reject');
          orderResult.classList.add('rejected');
          bar.style.width = '0%';
          steps.forEach((s,i) => document.getElementById('s'+(i+1)).className = 'step');
          subProcess.style.display = 'block';
          subBar.style.width = '0%';
          subLabel.textContent = 'Pesanan ditolak';
          trackingMapWrap.style.display = 'none';
          courierDetails.style.display = 'none';
          if (historyWrap) historyWrap.style.display = 'none';
          btnReset.style.display = 'inline-flex';
          if (options.fromSync) flashSync('Status pesanan diupdate');
          return;
        }

        rStatus.textContent = found.status.charAt(0).toUpperCase() + found.status.slice(1);
        bar.style.width = idx >= 0 ? ((idx + 1) * 25) + '%' : '0%';
        steps.forEach((s,i) => {
          const el = document.getElementById('s'+(i+1));
          el.className = 'step';
          if (i < idx) el.classList.add('complete');
          if (i === idx) el.classList.add('active');
        });

        if (found.status === 'proses') {
          subProcess.style.display = 'block';
          const stages = ['cuci','kering','setrika'];
          const sIdx = stages.indexOf(found.processStage || '');
          subBar.style.width = sIdx >= 0 ? (((sIdx + 1) / 3) * 100) + '%' : '0%';
          subLabel.textContent = found.processStage ? found.processStage.charAt(0).toUpperCase() + found.processStage.slice(1) : '-';
        } else {
          subProcess.style.display = 'none';
          subBar.style.width = '0%';
          subLabel.textContent = '';
        }

        // Courier details
        if ((found.status === 'jemput' || found.status === 'antar') && found.courier_name) {
          courierDetails.style.display = 'flex';
          document.getElementById('courierRoleLabel').textContent = found.status === 'jemput' ? 'Kurir Penjemput' : 'Kurir Pengantar';
          document.getElementById('courierNameLabel').textContent = found.courier_name;
          document.getElementById('courierPhoneLabel').textContent = found.courier_phone || '-';
        } else {
          courierDetails.style.display = 'none';
        }

        // Map display
        if (found.status === 'jemput' || found.status === 'antar') {
          trackingMapWrap.style.display = 'block';
          if (trackingMarker) trackingMap.removeLayer(trackingMarker);
          if (found.customer && found.customer.pos) {
            const popupCost = found.cost > 0 ? 'Rp ' + found.cost.toLocaleString() : 'Gratis Ongkir';
            const popupHtml = '<b>' + escapeHtml(found.customer.name) + '</b><br>Jarak: ' + (found.jarak || 0) + ' km<br>' + popupCost;
            trackingMarker = L.marker([found.customer.pos.lat, found.customer.pos.lng]).addTo(trackingMap).bindPopup(popupHtml).openPopup();
            trackingMap.setView([found.customer.pos.lat, found.customer.pos.lng], 15);
          } else {
            trackingMap.setView([mitra.lat, mitra.lng], 14);
          }
          setTimeout(() => trackingMap.invalidateSize(), 120);
        } else {
          trackingMapWrap.style.display = 'none';
        }

        btnReset.style.display = 'inline-flex';
        if (options.fromSync) flashSync('Status pesanan diupdate');
      } catch (e) {
        if (!options.silent) alert('Gagal memuat data pelacakan. Periksa koneksi internet Anda.');
      } finally {
        trackingLoading.classList.remove('show');
        btnLacak.disabled = false;
      }
    }

    // === Event Handlers ===
    btnLacak.onclick = () => renderTrackingByNumber(resiInput.value);

    // Allow tracking on Enter key
    resiInput.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        renderTrackingByNumber(resiInput.value);
      }
    });

    btnReset.onclick = () => {
      activeTrackingNumber = '';
      resiInput.value = '';
      orderResult.style.display = 'none';
      orderResult.classList.remove('rejected');
      rStatus.classList.remove('reject');
      trackingMapWrap.style.display = 'none';
      subProcess.style.display = 'none';
      subBar.style.width = '0%';
      subLabel.textContent = '';
      courierDetails.style.display = 'none';
      if (historyWrap) historyWrap.style.display = 'none';
      btnReset.style.display = 'none';
      if (syncText) syncText.textContent = 'Terhubung ke database OKE Laundry';
      resiInput.focus();
    };

    // === Slider ===
    const sliderTrack = document.getElementById('sliderTrack');
    let slideCards = Array.from(sliderTrack.children);
    let bannerMode = false;
    const prevSlideBtn = document.getElementById('prevSlide');
    const nextSlideBtn = document.getElementById('nextSlide');
    const sliderDots = document.getElementById('sliderDots');
    let currentIndex = 0;

    function escapeAttr(s) { return String(s || '').replace(/"/g, '&quot;').replace(/</g, '&lt;'); }

    async function loadBannersFromAPI() {
      try {
        const res = await fetch('/api/banners');
        if (!res.ok) return;
        const banners = await res.json();
        if (!Array.isArray(banners) || !banners.length) return;
        // Replace slider content with uploaded banners
        sliderTrack.innerHTML = banners.map(b => {
          const title = b.title ? `<h3>${escapeHtml(b.title)}</h3>` : '';
          const caption = b.caption ? `<div class="caption">${escapeHtml(b.caption)}</div>` : '';
          const overlay = (title || caption) ? `<div class="slide-overlay">${title}${caption}</div>` : '';
          const overlayClass = (title || caption) ? ' has-overlay' : '';
          return `<div class="slide-card banner${overlayClass}"><img src="${escapeAttr(b.url)}" alt="${escapeAttr(b.title || 'banner')}" loading="lazy" />${overlay}</div>`;
        }).join('');
        slideCards = Array.from(sliderTrack.children);
        bannerMode = true;
        sliderTrack.classList.add('banner-mode');
        currentIndex = 0;
        renderDots();
        updateSlider();
        if (typeof startAutoplay === 'function') startAutoplay();
      } catch (_) { /* tetap pakai default */ }
    }

    const getVisibleSlides = () => {
      if (bannerMode) return 1; // banner upload selalu 1 per layar (rasio 3:1 = sama dgn hasil crop)
      const n = slideCards.length;
      if (window.innerWidth <= 980) return 1;
      return Math.min(n, 3); // kartu promo default: 1→1, 2→2, 3+→3
    };
    const getMaxIndex = () => Math.max(0, slideCards.length - getVisibleSlides());

    // Atur lebar tiap kartu agar memenuhi viewport sesuai jumlah yang terlihat
    const applySlideWidth = () => {
      const visible = getVisibleSlides();
      const gap = 16;
      slideCards.forEach(card => {
        card.style.flex = `0 0 calc((100% - ${gap * (visible - 1)}px) / ${visible})`;
        card.style.maxWidth = `calc((100% - ${gap * (visible - 1)}px) / ${visible})`;
      });
      // Sembunyikan panah & dots kalau semua slide sudah muat (tidak perlu geser)
      const needNav = slideCards.length > visible;
      [prevSlideBtn, nextSlideBtn].forEach(b => { if (b) b.style.visibility = needNav ? 'visible' : 'hidden'; });
      if (sliderDots) sliderDots.style.display = needNav ? 'flex' : 'none';
    };

    const renderDots = () => {
      const pages = getMaxIndex() + 1;
      sliderDots.innerHTML = '';
      for (let i = 0; i < pages; i++) {
        const dot = document.createElement('button');
        dot.type = 'button';
        dot.setAttribute('aria-label', 'Buka slide ' + (i + 1));
        const active = i === currentIndex;
        dot.style.cssText = 'height:8px;border:none;border-radius:999px;margin:0 3px;cursor:pointer;padding:0;vertical-align:middle;transition:width .3s ease,background .3s ease;width:' + (active ? '22px' : '8px') + ';background:' + (active ? '#fff' : 'rgba(255,255,255,.45)');
        dot.addEventListener('click', () => { currentIndex = i; updateSlider(); });
        sliderDots.appendChild(dot);
      }
    };

    const updateSlider = () => {
      applySlideWidth();
      const visible = getVisibleSlides();
      const maxIndex = Math.max(0, slideCards.length - visible);
      if (currentIndex > maxIndex) currentIndex = maxIndex;
      const gap = 16;
      const step = slideCards[0].getBoundingClientRect().width + gap;
      sliderTrack.style.transform = 'translateX(-' + (currentIndex * step) + 'px)';
      Array.from(sliderDots.children).forEach((dot, idx) => {
        const active = idx === currentIndex;
        dot.style.width = active ? '22px' : '8px';
        dot.style.background = active ? '#fff' : 'rgba(255,255,255,.45)';
      });
    };

    prevSlideBtn.addEventListener('click', () => {
      const maxIndex = getMaxIndex();
      currentIndex = currentIndex <= 0 ? maxIndex : currentIndex - 1;
      updateSlider();
    });

    nextSlideBtn.addEventListener('click', () => {
      const maxIndex = getMaxIndex();
      currentIndex = currentIndex >= maxIndex ? 0 : currentIndex + 1;
      updateSlider();
    });

    let resizeTimer;
    window.addEventListener('resize', () => {
      clearTimeout(resizeTimer);
      resizeTimer = setTimeout(() => { renderDots(); updateSlider(); }, 120);
    });

    renderDots();
    updateSlider();
    loadBannersFromAPI();

    // === Auto-play slider ===
    const AUTOPLAY_MS = 4000;
    let autoTimer = null;
    function startAutoplay() {
      stopAutoplay();
      // Hanya autoplay kalau ada slide yang perlu digeser
      if (slideCards.length <= getVisibleSlides()) return;
      autoTimer = setInterval(() => {
        const maxIndex = getMaxIndex();
        currentIndex = currentIndex >= maxIndex ? 0 : currentIndex + 1;
        updateSlider();
      }, AUTOPLAY_MS);
    }
    function stopAutoplay() {
      if (autoTimer) { clearInterval(autoTimer); autoTimer = null; }
    }

    // Pause saat user hover / pakai panah / ganti tab
    const sliderShell = document.querySelector('.slider-shell');
    if (sliderShell) {
      sliderShell.addEventListener('mouseenter', stopAutoplay);
      sliderShell.addEventListener('mouseleave', startAutoplay);
      sliderShell.addEventListener('focusin', stopAutoplay);
      sliderShell.addEventListener('focusout', startAutoplay);
    }
    document.addEventListener('visibilitychange', () => {
      if (document.hidden) stopAutoplay(); else startAutoplay();
    });

    // Manual control juga reset timer
    [prevSlideBtn, nextSlideBtn].forEach(btn => btn?.addEventListener('click', () => {
      stopAutoplay();
      // restart setelah jeda agar tidak langsung lompat
      setTimeout(startAutoplay, 1500);
    }));

    startAutoplay();

    // === Auto-load by ?resi= URL param (untuk scan QR) ===
    (function () {
      const params = new URLSearchParams(window.location.search);
      const r = params.get('resi');
      if (r) {
        resiInput.value = r;
        renderTrackingByNumber(r);
      }
    })();

    // === Auto-refresh polling (every 10 seconds instead of 5 to reduce server load) ===
    setInterval(() => {
      if (activeTrackingNumber) {
        renderTrackingByNumber(activeTrackingNumber, { silent: true, fromSync: true });
      }
    }, 10000);
  </script>
</body>
</html>
