const { useState: useStateD, useEffect: useEffectD, useRef: useRefD } = React;

// ── Helpers ────────────────────────────────────────────────────────────────────

function fmtAddrShort(addr) {
  if (!addr) return '—';
  if (typeof addr === 'string') return addr;
  return addr.sublocality || addr.city || addr.municipality || addr.address_line_1 || '—';
}

function fmtTime(ts) {
  if (!ts) return '—';
  return new Date(ts).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });
}

function fmtDate(ts) {
  if (!ts) return '—';
  const d = new Date(ts);
  const today = new Date(); today.setHours(0,0,0,0);
  const dd = new Date(d); dd.setHours(0,0,0,0);
  if (dd.getTime() === today.getTime()) return fmtTime(ts);
  return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) + ' ' + fmtTime(ts);
}

function fmtDist(m) {
  if (!m) return '—';
  return (m / 1000).toFixed(1) + ' km';
}

function fmtDistKm(km) {
  if (km == null) return '—';
  return Number(km).toFixed(1) + ' km';
}

function fmtDuration(s) {
  if (!s) return '—';
  const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60);
  return h > 0 ? `${h}h ${m}m` : `${m}m`;
}

function currency(n) {
  return 'Rs ' + Number(n || 0).toLocaleString();
}

function initials(name) {
  if (!name) return '?';
  return name.split(' ').map(s => s[0]).join('').slice(0, 2).toUpperCase();
}

function currentDispatchWindow() {
  const h = new Date().getHours();
  if (h < 12) return 'morning';
  if (h < 17) return 'afternoon';
  return 'evening';
}

const NEPAL_BOUNDS = { minLat: 26.3, maxLat: 30.5, minLng: 80.0, maxLng: 88.2 };
function inNepal(lat, lng) {
  return lat >= NEPAL_BOUNDS.minLat && lat <= NEPAL_BOUNDS.maxLat &&
         lng >= NEPAL_BOUNDS.minLng && lng <= NEPAL_BOUNDS.maxLng;
}

const ROUTE_STATUS_META = {
  assembling: { label: 'Assembling', chip: 'warn' },
  optimized:  { label: 'Optimized',  chip: 'accent' },
  planned:    { label: 'Planned',    chip: 'accent' },
  dispatched: { label: 'Dispatched', chip: 'pos' },
  completed:  { label: 'Completed',  chip: 'pos' },
  cancelled:  { label: 'Cancelled',  chip: 'neg' },
};

const FLASH_STATUS_META = {
  pending:            { label: 'Pending',    chip: 'warn' },
  assigned:           { label: 'Assigned',   chip: 'accent' },
  picked_up:          { label: 'Picked up',  chip: 'accent' },
  in_transit:         { label: 'In transit', chip: 'pos' },
  arrived:            { label: 'Arrived',    chip: 'pos' },
  delivered:          { label: 'Delivered',  chip: 'pos' },
  failed:             { label: 'Failed',     chip: 'neg' },
  returning_to_store: { label: 'Returning',  chip: 'warn' },
  returned:           { label: 'Returned',   chip: 'neg' },
};

function extractCoords(addr) {
  if (!addr) return null;
  // flat shape: { latitude, longitude } or { lat, lng }
  const flatLat = addr.latitude ?? addr.lat;
  const flatLng = addr.longitude ?? addr.lng;
  if (flatLat != null && flatLng != null) {
    const lat = Number(flatLat), lng = Number(flatLng);
    if (lat && lng && inNepal(lat, lng)) return { lat, lng };
  }
  // nested shape: { coordinates: { latitude, longitude } }
  const c = addr.coordinates;
  if (!c) return null;
  const lat = Number(c.latitude ?? c.lat);
  const lng = Number(c.longitude ?? c.lng);
  if (!lat || !lng || !inNepal(lat, lng)) return null;
  return { lat, lng };
}

// ── DB fetch helpers ───────────────────────────────────────────────────────────

async function dbFetchActiveRoutes(sb) {
  const { data: routesData, error } = await sb.from('routes')
    .select('id, driver_id, status, dispatch_window, total_stops, total_distance_m, total_duration_s, optimized_polyline, dispatched_at, created_at, window_start, window_end')
    .in('status', ['assembling', 'optimized', 'dispatched'])
    .order('created_at', { ascending: false })
    .limit(20);
  if (error || !routesData) return [];

  const routeIds = routesData.map(r => r.id);
  const driverIds = [...new Set(routesData.map(r => r.driver_id).filter(Boolean))];

  const [stopsRes, delivRes, driverProfileRes, driverPartnerRes] = await Promise.all([
    routeIds.length
      ? sb.from('route_stops')
          .select('id, route_id, delivery_id, stop_type, sequence, address, latitude, longitude, estimated_arrival, actual_arrival, completed_at, status')
          .in('route_id', routeIds)
          .order('sequence', { ascending: true })
      : Promise.resolve({ data: [] }),
    routeIds.length
      ? sb.from('deliveries')
          .select('id, route_id, tracking_number, delivery_tier, is_flash, pickup_address, delivery_address, distance_km, status, orders(order_number, total_amount)')
          .in('route_id', routeIds)
      : Promise.resolve({ data: [] }),
    driverIds.length
      ? sb.from('user_profiles').select('id, display_name, phone').in('id', driverIds)
      : Promise.resolve({ data: [] }),
    driverIds.length
      ? sb.from('delivery_partners').select('user_id, vehicle_type, last_location_latitude, last_location_longitude').in('user_id', driverIds)
      : Promise.resolve({ data: [] }),
  ]);

  const profileMap = {};
  (driverProfileRes.data || []).forEach(p => { profileMap[p.id] = p; });
  const partnerMap = {};
  (driverPartnerRes.data || []).forEach(p => { partnerMap[p.user_id] = p; });
  const stopsByRoute = {};
  (stopsRes.data || []).forEach(s => {
    (stopsByRoute[s.route_id] = stopsByRoute[s.route_id] || []).push(s);
  });
  const delivByRoute = {};
  (delivRes.data || []).forEach(d => {
    if (!d.route_id) return;
    (delivByRoute[d.route_id] = delivByRoute[d.route_id] || []).push({ ...d, order: d.orders });
  });

  const dispatchedIds = routesData.filter(r => r.status === 'dispatched').map(r => r.id);
  const progressMap = {};
  if (dispatchedIds.length) {
    const results = await Promise.all(
      dispatchedIds.map(id => sb.rpc('get_route_progress', { p_route_id: id }).then(({ data }) => ({ id, data })))
    );
    results.forEach(({ id, data }) => { if (data) progressMap[id] = data; });
  }

  return routesData.map(r => {
    const partner = partnerMap[r.driver_id] || {};
    const driverLat = Number(partner.last_location_latitude);
    const driverLng = Number(partner.last_location_longitude);
    return {
      ...r,
      driver: profileMap[r.driver_id] || null,
      vehicle_type: partner.vehicle_type || null,
      driver_lat: inNepal(driverLat, driverLng) ? driverLat : null,
      driver_lng: inNepal(driverLat, driverLng) ? driverLng : null,
      stops: stopsByRoute[r.id] || [],
      deliveries: delivByRoute[r.id] || [],
      progress: progressMap[r.id] || null,
    };
  });
}

async function dbFetchPlannedRoutes(sb) {
  const { data: routesData, error } = await sb.from('routes')
    .select('id, driver_id, status, dispatch_window, tier, cut_time, total_stops, total_distance_m, total_duration_s, optimized_polyline, created_at, window_start, window_end')
    .eq('status', 'planned')
    .order('cut_time', { ascending: true })
    .limit(50);
  if (error || !routesData) return [];

  const routeIds = routesData.map(r => r.id);

  const [stopsRes, delivRes] = await Promise.all([
    routeIds.length
      ? sb.from('route_stops')
          .select('id, route_id, delivery_id, stop_type, sequence, address, latitude, longitude')
          .in('route_id', routeIds)
          .order('sequence', { ascending: true })
      : Promise.resolve({ data: [] }),
    routeIds.length
      ? sb.from('deliveries')
          .select('id, route_id, tracking_number, delivery_tier, pickup_address, delivery_address, distance_km, orders(order_number, total_amount)')
          .in('route_id', routeIds)
      : Promise.resolve({ data: [] }),
  ]);

  const stopsByRoute = {};
  (stopsRes.data || []).forEach(s => {
    (stopsByRoute[s.route_id] = stopsByRoute[s.route_id] || []).push(s);
  });
  const delivByRoute = {};
  (delivRes.data || []).forEach(d => {
    if (!d.route_id) return;
    (delivByRoute[d.route_id] = delivByRoute[d.route_id] || []).push({ ...d, order: d.orders });
  });

  return routesData.map(r => ({
    ...r,
    driver: null,
    stops: stopsByRoute[r.id] || [],
    deliveries: delivByRoute[r.id] || [],
  }));
}

async function dbFetchCompletedRoutes(sb) {
  const { data: routesData, error } = await sb.from('routes')
    .select('id, driver_id, status, dispatch_window, total_stops, total_distance_m, total_duration_s, dispatched_at, completed_at, created_at, updated_at')
    .in('status', ['completed', 'cancelled'])
    .order('created_at', { ascending: false })
    .limit(30);
  if (error || !routesData) return [];

  const driverIds = [...new Set(routesData.map(r => r.driver_id).filter(Boolean))];
  const routeIds = routesData.map(r => r.id);

  const [driverRes, delivRes, stopsRes] = await Promise.all([
    driverIds.length
      ? sb.from('user_profiles').select('id, display_name, phone').in('id', driverIds)
      : Promise.resolve({ data: [] }),
    routeIds.length
      ? sb.from('deliveries')
          .select('id, route_id, tracking_number, pickup_address, delivery_address, status, orders(order_number, total_amount)')
          .in('route_id', routeIds)
      : Promise.resolve({ data: [] }),
    routeIds.length
      ? sb.from('route_stops')
          .select('id, route_id, stop_type, sequence, latitude, longitude, status, address, estimated_arrival, actual_arrival, completed_at, delivery_id')
          .in('route_id', routeIds)
          .order('sequence', { ascending: true })
      : Promise.resolve({ data: [] }),
  ]);

  const driverMap = {};
  (driverRes.data || []).forEach(d => { driverMap[d.id] = d; });
  const delivByRoute = {};
  (delivRes.data || []).forEach(d => {
    if (!d.route_id) return;
    (delivByRoute[d.route_id] = delivByRoute[d.route_id] || []).push({ ...d, order: d.orders });
  });
  const stopsByRoute = {};
  (stopsRes.data || []).forEach(s => {
    (stopsByRoute[s.route_id] = stopsByRoute[s.route_id] || []).push(s);
  });

  return routesData.map(r => {
    const deliveries = (delivByRoute[r.id] || []).map(d => ({ ...d, order: d.orders }));
    let stops = stopsByRoute[r.id] || [];
    if (stops.length === 0) {
      let seq = 1;
      deliveries.forEach(d => {
        const pc = d.pickup_address?.coordinates;
        const dc = d.delivery_address?.coordinates;
        if (pc?.latitude && pc?.longitude) {
          stops.push({ id: `${d.id}-p`, route_id: r.id, stop_type: 'pickup', sequence: seq++, latitude: pc.latitude, longitude: pc.longitude, status: 'completed', address: d.pickup_address });
        }
        if (dc?.latitude && dc?.longitude) {
          stops.push({ id: `${d.id}-d`, route_id: r.id, stop_type: 'dropoff', sequence: seq++, latitude: dc.latitude, longitude: dc.longitude, status: 'completed', address: d.delivery_address });
        }
      });
    }
    return { ...r, driver: driverMap[r.driver_id] || null, deliveries, stops };
  });
}

async function dbFetchPendingDeliveries(sb) {
  const { data } = await sb.from('deliveries')
    .select('id, tracking_number, delivery_tier, is_flash, pickup_address, delivery_address, distance_km, fee, created_at, order_id, orders(order_number, total_amount, buyer_id, stores(name))')
    .eq('status', 'pending')
    .is('route_id', null)
    .eq('is_flash', false)
    .order('created_at', { ascending: true })
    .limit(100);
  const deliveries = (data || []).map(d => ({ ...d, order: d.orders }));
  const buyerIds = [...new Set(deliveries.map(d => d.order?.buyer_id).filter(Boolean))];
  const profileMap = {};
  if (buyerIds.length) {
    const { data: profiles } = await sb.from('user_profiles').select('id, username').in('id', buyerIds);
    (profiles || []).forEach(p => { profileMap[p.id] = p; });
  }
  return deliveries.map(d => ({
    ...d,
    order: d.order ? { ...d.order, buyer: profileMap[d.order.buyer_id] || null } : null,
  }));
}

async function dbFetchFlashNew(sb) {
  const { data } = await sb.from('deliveries')
    .select('id, tracking_number, delivery_tier, is_flash, pickup_address, delivery_address, distance_km, fee, created_at, status, driver_id, orders(order_number, total_amount)')
    .eq('is_flash', true)
    .eq('status', 'pending')
    .order('created_at', { ascending: false })
    .limit(50);
  return (data || []).map(d => ({ ...d, order: d.orders }));
}

async function dbFetchFlashActive(sb) {
  const { data } = await sb.from('deliveries')
    .select('id, tracking_number, delivery_tier, is_flash, pickup_address, delivery_address, distance_km, fee, created_at, assigned_at, picked_up_at, estimated_arrival, status, driver_id, orders(order_number, total_amount)')
    .eq('is_flash', true)
    .in('status', ['assigned', 'picked_up', 'in_transit', 'arrived'])
    .order('created_at', { ascending: false })
    .limit(50);
  if (!data?.length) return [];
  const driverIds = [...new Set(data.map(d => d.driver_id).filter(Boolean))];
  const [profileRes, partnerRes] = await Promise.all([
    driverIds.length
      ? sb.from('user_profiles').select('id, display_name, phone').in('id', driverIds)
      : Promise.resolve({ data: [] }),
    driverIds.length
      ? sb.from('delivery_partners').select('user_id, vehicle_type, last_location_latitude, last_location_longitude').in('user_id', driverIds)
      : Promise.resolve({ data: [] }),
  ]);
  const profileMap = {};
  (profileRes.data || []).forEach(p => { profileMap[p.id] = p; });
  const partnerMap = {};
  (partnerRes.data || []).forEach(p => { partnerMap[p.user_id] = p; });
  return data.map(d => {
    const partner = partnerMap[d.driver_id] || {};
    const lat = Number(partner.last_location_latitude);
    const lng = Number(partner.last_location_longitude);
    return {
      ...d,
      order: d.orders,
      driver: profileMap[d.driver_id] || null,
      vehicle_type: partner.vehicle_type || null,
      driver_lat: inNepal(lat, lng) ? lat : null,
      driver_lng: inNepal(lat, lng) ? lng : null,
    };
  });
}

async function dbFetchFlashCompleted(sb) {
  const { data } = await sb.from('deliveries')
    .select('id, tracking_number, delivery_tier, is_flash, pickup_address, delivery_address, distance_km, fee, created_at, assigned_at, picked_up_at, delivered_at, status, driver_id, orders(order_number, total_amount)')
    .eq('is_flash', true)
    .in('status', ['delivered', 'failed', 'returning_to_store', 'returned'])
    .order('created_at', { ascending: false })
    .limit(50);
  if (!data?.length) return [];
  const driverIds = [...new Set(data.map(d => d.driver_id).filter(Boolean))];
  const profileRes = driverIds.length
    ? await sb.from('user_profiles').select('id, display_name, phone').in('id', driverIds)
    : { data: [] };
  const profileMap = {};
  (profileRes.data || []).forEach(p => { profileMap[p.id] = p; });
  return data.map(d => ({ ...d, order: d.orders, driver: profileMap[d.driver_id] || null }));
}

async function dbFetchDriversList(sb) {
  const { data: partners } = await sb.from('delivery_partners')
    .select('user_id, is_online, vehicle_type')
    .eq('is_active', true)
    .eq('is_online', true);
  if (!partners?.length) return [];
  const ids = partners.map(p => p.user_id);
  const { data: profiles } = await sb.from('user_profiles').select('id, display_name, phone').in('id', ids);
  const vmap = {};
  partners.forEach(p => { vmap[p.user_id] = p.vehicle_type; });
  return (profiles || []).map(p => ({
    id: p.id,
    display_name: p.display_name || 'Driver',
    phone: p.phone || null,
    vehicle_type: vmap[p.id] || null,
  }));
}

// ── Small reusable pieces ──────────────────────────────────────────────────────

const MapStat = ({ label, v }) => (
  <div>
    <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9.5, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase' }}>{label}</div>
    <div className="num" style={{ fontSize: 12.5, fontWeight: 550, color: 'var(--ink)' }}>{v}</div>
  </div>
);

const RouteStat = ({ label, value }) => (
  <div>
    <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9.5, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase' }}>{label}</div>
    <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink)', marginTop: 2 }}>{value}</div>
  </div>
);

const Donut = ({ value, size = 42, stroke = 5 }) => {
  const r = (size - stroke) / 2;
  const circ = 2 * Math.PI * r;
  const dash = circ * Math.min(1, Math.max(0, value));
  return (
    <svg width={size} height={size} style={{ flexShrink: 0 }}>
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--surface-3)" strokeWidth={stroke} />
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--accent)" strokeWidth={stroke}
        strokeDasharray={`${dash} ${circ}`} strokeDashoffset={circ/4} strokeLinecap="round" />
    </svg>
  );
};

// ── Pending deliveries map (Dispatch New tab) ──────────────────────────────────

const PMAP_COLORS = ['#f59e0b','#3b82f6','#8b5cf6','#ec4899','#10b981','#f97316','#06b6d4','#84cc16'];

const PendingMap = ({ pending }) => {
  const mapRef = useRefD(null);
  const leafletRef = useRefD(null);

  useEffectD(() => {
    if (!mapRef.current || !window.L) return;
    const L = window.L;
    const map = L.map(mapRef.current, { center: [27.7172, 85.324], zoom: 12, zoomControl: false });
    L.control.zoom({ position: 'bottomright' }).addTo(map);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '© OpenStreetMap', maxZoom: 19,
    }).addTo(map);
    leafletRef.current = map;
    setTimeout(() => map.invalidateSize(), 150);
    return () => { map.remove(); leafletRef.current = null; };
  }, []);

  useEffectD(() => {
    const map = leafletRef.current;
    if (!map || !window.L) return;
    const L = window.L;
    map.eachLayer(l => { if (l._url === undefined) { try { map.removeLayer(l); } catch {} } });
    const bounds = [];
    pending.forEach((d, i) => {
      const color = PMAP_COLORS[i % PMAP_COLORS.length];
      const label = i + 1;
      const pickup = extractCoords(d.pickup_address);
      const dropoff = extractCoords(d.delivery_address);
      function makeIcon(letter) {
        return L.divIcon({
          className: '',
          iconSize: [26, 26], iconAnchor: [13, 13], popupAnchor: [0, -16],
          html: `<div style="width:26px;height:26px;border-radius:50%;background:${color};border:2.5px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,0.25);display:flex;align-items:center;justify-content:center;font-family:monospace;font-size:10px;font-weight:700;color:#fff">${letter}</div>`,
        });
      }
      if (pickup) {
        L.marker([pickup.lat, pickup.lng], { icon: makeIcon(`P${label}`) })
          .bindPopup(`<b>📦 Pickup ${label}</b><br>${d.pickup_address?.address_line_1 || ''}`)
          .addTo(map);
        bounds.push([pickup.lat, pickup.lng]);
      }
      if (dropoff) {
        L.marker([dropoff.lat, dropoff.lng], { icon: makeIcon(`D${label}`) })
          .bindPopup(`<b>🏠 Dropoff ${label}</b><br>${d.delivery_address?.address_line_1 || ''}`)
          .addTo(map);
        bounds.push([dropoff.lat, dropoff.lng]);
      }
      if (pickup && dropoff) {
        L.polyline([[pickup.lat, pickup.lng], [dropoff.lat, dropoff.lng]], {
          color, weight: 2, opacity: 0.55, dashArray: '5 4',
        }).addTo(map);
      }
    });
    if (bounds.length > 1) {
      map.fitBounds(L.latLngBounds(bounds), { padding: [40, 40], maxZoom: 14 });
    }
    setTimeout(() => map.invalidateSize(), 100);
  }, [pending.length]);

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
        <span style={{ fontSize: 11.5, color: 'var(--ink-2)' }}>
          Pending deliveries map
          <span className="muted" style={{ marginLeft: 6, fontWeight: 400 }}>— pickup → dropoff</span>
        </span>
      </div>
      <div ref={mapRef} style={{ height: 240, borderRadius: 6, overflow: 'hidden', border: '1px solid var(--hairline)' }} />
    </div>
  );
};

// ── Flash delivery map (single delivery, live driver) ─────────────────────────

const FlashMap = ({ delivery, showDriverPath = false }) => {
  const sb = window.supabaseClient;
  const mapRef = useRefD(null);
  const leafletRef = useRefD(null);
  const driverMarkerRef = useRefD(null);
  const pathLayerRef = useRefD(null);
  const [driverPos, setDriverPos] = useStateD(null);
  const [driverUpdatedAt, setDriverUpdatedAt] = useStateD(null);
  const [driverPath, setDriverPath] = useStateD([]);

  const driverUserId = delivery?.driver_id;
  const deliveryId = delivery?.id;

  useEffectD(() => {
    if (!mapRef.current || !window.L) return;
    const L = window.L;
    const map = L.map(mapRef.current, { center: [27.7172, 85.324], zoom: 13, zoomControl: false });
    L.control.zoom({ position: 'bottomright' }).addTo(map);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
      maxZoom: 19,
    }).addTo(map);
    leafletRef.current = map;
    setTimeout(() => map.invalidateSize(), 150);
    return () => { map.remove(); leafletRef.current = null; };
  }, []);

  // Redraw pickup/dropoff markers + OSRM road route when delivery changes
  useEffectD(() => {
    const map = leafletRef.current;
    if (!map || !window.L || !delivery) return;
    const L = window.L;

    map.eachLayer(l => { if (l._url === undefined) { try { map.removeLayer(l); } catch {} } });
    pathLayerRef.current = null;
    setDriverPath([]);
    setDriverPos(null);

    const pickup = extractCoords(delivery.pickup_address);
    const dropoff = extractCoords(delivery.delivery_address);
    const bounds = [];

    if (pickup) {
      const icon = L.divIcon({
        className: '',
        iconSize: [28, 28], iconAnchor: [14, 14], popupAnchor: [0, -18],
        html: `<div style="width:28px;height:28px;border-radius:50%;background:#f59e0b;border:2.5px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,0.25);display:grid;place-items:center;font-size:13px">📦</div>`,
      });
      L.marker([pickup.lat, pickup.lng], { icon })
        .bindPopup(`<b>Pickup</b><br>${delivery.pickup_address?.address_line_1 || fmtAddrShort(delivery.pickup_address)}`)
        .addTo(map);
      bounds.push([pickup.lat, pickup.lng]);
    }
    if (dropoff) {
      const icon = L.divIcon({
        className: '',
        iconSize: [28, 28], iconAnchor: [14, 14], popupAnchor: [0, -18],
        html: `<div style="width:28px;height:28px;border-radius:50%;background:#16a34a;border:2.5px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,0.25);display:grid;place-items:center;font-size:13px">🏠</div>`,
      });
      L.marker([dropoff.lat, dropoff.lng], { icon })
        .bindPopup(`<b>Dropoff</b><br>${delivery.delivery_address?.address_line_1 || fmtAddrShort(delivery.delivery_address)}`)
        .addTo(map);
      bounds.push([dropoff.lat, dropoff.lng]);
    }
    if (bounds.length > 0) {
      map.fitBounds(bounds.length === 1 ? L.latLngBounds([bounds[0], bounds[0]]) : L.latLngBounds(bounds), { padding: [60, 60], maxZoom: 15 });
    }
    setTimeout(() => map.invalidateSize(), 100);

    // OSRM road route between pickup and dropoff
    if (pickup && dropoff) {
      const waypoints = `${pickup.lng},${pickup.lat};${dropoff.lng},${dropoff.lat}`;
      fetch(`https://router.project-osrm.org/route/v1/driving/${waypoints}?overview=full&geometries=geojson`)
        .then(r => r.json())
        .then(data => {
          if (data.code !== 'Ok' || !data.routes?.[0]) return;
          const coords = data.routes[0].geometry.coordinates.map(([lng, lat]) => [lat, lng]);
          if (!leafletRef.current) return;
          L.polyline(coords, { color: '#2563eb', weight: 4, opacity: 0.8 }).addTo(leafletRef.current);
        })
        .catch(() => {
          if (!leafletRef.current || !pickup || !dropoff) return;
          L.polyline([[pickup.lat, pickup.lng], [dropoff.lat, dropoff.lng]], {
            color: '#2563eb', weight: 2, opacity: 0.5, dashArray: '6 5',
          }).addTo(leafletRef.current);
        });
    }
  }, [deliveryId]);

  // Live driver location (active flash) — always subscribe when driverUserId is set and not in history-path mode
  useEffectD(() => {
    if (!sb || !driverUserId || showDriverPath) return;

    sb.from('delivery_partners')
      .select('last_location_latitude, last_location_longitude, last_location_updated_at')
      .eq('user_id', driverUserId)
      .single()
      .then(({ data }) => {
        if (data?.last_location_latitude && data?.last_location_longitude) {
          const lat = Number(data.last_location_latitude);
          const lng = Number(data.last_location_longitude);
          if (inNepal(lat, lng)) {
            setDriverPos([lat, lng]);
            setDriverUpdatedAt(data.last_location_updated_at || null);
          }
        }
      });

    const channel = sb.channel(`flash-driver-${driverUserId}-${deliveryId}`)
      .on('postgres_changes', {
        event: 'UPDATE', schema: 'public',
        table: 'delivery_partners',
        filter: `user_id=eq.${driverUserId}`,
      }, payload => {
        const row = payload.new;
        if (row.last_location_latitude && row.last_location_longitude) {
          const lat = Number(row.last_location_latitude);
          const lng = Number(row.last_location_longitude);
          if (inNepal(lat, lng)) {
            setDriverPos([lat, lng]);
            setDriverUpdatedAt(row.last_location_updated_at || null);
          }
        }
      })
      .subscribe();
    return () => { sb.removeChannel(channel); };
  }, [driverUserId, deliveryId, showDriverPath]);

  // Driver path for completed flash
  useEffectD(() => {
    if (!showDriverPath || !sb || !deliveryId) return;
    sb.from('driver_location_history')
      .select('latitude, longitude, recorded_at')
      .eq('delivery_id', deliveryId)
      .order('recorded_at', { ascending: true })
      .limit(500)
      .then(({ data }) => {
        const pts = (data || []).filter(p => inNepal(Number(p.latitude), Number(p.longitude)));
        setDriverPath(pts);
      });
  }, [deliveryId, showDriverPath]);

  // Draw driver path layer — depends on driverPath array identity, not just length
  useEffectD(() => {
    const map = leafletRef.current;
    if (!map || !window.L) return;
    if (pathLayerRef.current) { try { map.removeLayer(pathLayerRef.current); } catch {} pathLayerRef.current = null; }
    if (driverPath.length > 1) {
      const pts = driverPath.map(p => [Number(p.latitude), Number(p.longitude)]);
      pathLayerRef.current = window.L.polyline(pts, { color: '#7c3aed', weight: 3, opacity: 0.85, dashArray: '6 4' }).addTo(map);
    }
  }, [driverPath]);

  // Update driver marker whenever position changes or delivery switches
  useEffectD(() => {
    const map = leafletRef.current;
    if (!map || !window.L) return;
    if (driverMarkerRef.current) { try { map.removeLayer(driverMarkerRef.current); } catch {} driverMarkerRef.current = null; }
    if (driverPos) {
      const driverName = (delivery?.driver?.display_name || 'Driver').split(' ')[0];
      const updatedStr = driverUpdatedAt
        ? new Date(driverUpdatedAt).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false })
        : '';
      const icon = window.L.divIcon({
        className: '',
        iconSize: [32, 42], iconAnchor: [16, 42], popupAnchor: [0, -44],
        html: `<div style="display:flex;flex-direction:column;align-items:center;gap:2px">
          <div style="background:#2563eb;color:#fff;font-family:monospace;font-size:9px;font-weight:600;padding:2px 6px;border-radius:3px;white-space:nowrap;box-shadow:0 1px 3px rgba(0,0,0,0.3)">${driverName}</div>
          <div style="width:32px;height:32px;border-radius:50%;background:#2563eb;border:3px solid #fff;box-shadow:0 2px 8px rgba(37,99,235,0.5);display:flex;align-items:center;justify-content:center;font-size:15px">⚡</div>
        </div>`,
      });
      driverMarkerRef.current = window.L.marker(driverPos, { icon, zIndexOffset: 2000 })
        .bindPopup(`<b>${delivery?.driver?.display_name || 'Driver'}</b>${updatedStr ? `<br><span style="font-size:10px;color:#666">Updated ${updatedStr}</span>` : ''}`)
        .addTo(map);
    }
  }, [driverPos, deliveryId]);

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 300 }}>
      {(driverUserId && !showDriverPath) && (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap',
          padding: '5px 10px', borderBottom: '1px solid var(--hairline)',
          background: 'var(--surface-2)', flexShrink: 0,
        }}>
          {driverUserId && !showDriverPath && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 10.5, fontFamily: 'var(--font-mono)' }}>
              <span style={{ width: 6, height: 6, borderRadius: '50%', background: driverPos ? '#16a34a' : '#9C988D', display: 'inline-block' }} />
              {driverPos ? 'Driver live' : 'Awaiting location'}
            </div>
          )}

        </div>
      )}
      <div style={{ flex: 1, position: 'relative', minHeight: 0 }}>
        <div ref={mapRef} style={{ position: 'absolute', inset: 0, zIndex: 0 }} />
      </div>
    </div>
  );
};

// ── Route map (Leaflet) ────────────────────────────────────────────────────────

const RouteMap = ({ route, locationHistory, showDriverPath = false }) => {
  const sb = window.supabaseClient;
  const mapRef = useRefD(null);
  const leafletRef = useRefD(null);
  const layersRef = useRefD({});
  const driverMarkerRef = useRefD(null);
  const [driverPos, setDriverPos] = useStateD(null);
  const [driverUpdatedAt, setDriverUpdatedAt] = useStateD(null);
  const [driverPath, setDriverPath] = useStateD([]);
  const [completionPins, setCompletionPins] = useStateD([]);

  const stops = route.stops || [];
  const routeId = route.id;
  const driverUserId = route.driver_id;
  const accentHex = '#3a8f5c';
  const paperHex = '#F6F4EE';

  function makeStopIcon(label, bg, border, color, size) {
    return window.L.divIcon({
      className: '',
      iconSize: [size, size], iconAnchor: [size / 2, size / 2], popupAnchor: [0, -(size / 2 + 4)],
      html: `<div style="width:${size}px;height:${size}px;border-radius:50%;background:${bg};border:2px solid ${border};color:${color};display:grid;place-items:center;font-family:monospace;font-size:10px;font-weight:700;box-shadow:0 2px 6px rgba(0,0,0,0.25);box-sizing:border-box;">${label}</div>`,
    });
  }

  function makeDriverIcon(name) {
    return window.L.divIcon({
      className: '',
      iconSize: [32, 42], iconAnchor: [16, 42], popupAnchor: [0, -44],
      html: `<div style="display:flex;flex-direction:column;align-items:center;gap:2px">
        <div style="background:#2563eb;color:#fff;font-family:monospace;font-size:9px;font-weight:600;padding:2px 6px;border-radius:3px;white-space:nowrap;box-shadow:0 1px 3px rgba(0,0,0,0.3)">${name}</div>
        <div style="width:32px;height:32px;border-radius:50%;background:#2563eb;border:3px solid #fff;box-shadow:0 2px 8px rgba(37,99,235,0.5);display:flex;align-items:center;justify-content:center;font-size:15px">🛵</div>
      </div>`,
    });
  }

  useEffectD(() => {
    if (!mapRef.current || !window.L) return;
    const L = window.L;
    const map = L.map(mapRef.current, { center: [27.7172, 85.324], zoom: 13, zoomControl: false });
    L.control.zoom({ position: 'bottomright' }).addTo(map);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
      maxZoom: 19,
    }).addTo(map);
    leafletRef.current = map;
    setTimeout(() => map.invalidateSize(), 150);
    return () => { map.remove(); leafletRef.current = null; };
  }, []);

  useEffectD(() => {
    const map = leafletRef.current;
    if (!map || !window.L) return;
    const L = window.L;

    Object.entries(layersRef.current).forEach(([, l]) => { try { map.removeLayer(l); } catch {} });
    layersRef.current = {};

    const geocodedStops = stops
      .filter(s => s.latitude && s.longitude)
      .sort((a, b) => (a.sequence || 0) - (b.sequence || 0));
    const stopBounds = geocodedStops.map(s => [Number(s.latitude), Number(s.longitude)]);
    const firstPendingIdx = stops.findIndex(s => s.status === 'pending');

    const markerGroup = L.layerGroup().addTo(map);
    geocodedStops.forEach((s, i) => {
      const lat = Number(s.latitude), lng = Number(s.longitude);
      const isDone = s.status === 'completed' || s.status === 'skipped';
      const isCur = stops.indexOf(s) === firstPendingIdx;
      const isPickup = s.stop_type === 'pickup';
      let bg, border, color;
      if (isDone)        { bg = '#E9E5DA'; border = '#9C988D'; color = '#6E6B62'; }
      else if (isCur)    { bg = accentHex; border = paperHex; color = '#fff'; }
      else if (isPickup) { bg = '#f59e0b'; border = '#fff'; color = '#fff'; }
      else               { bg = '#16a34a'; border = '#fff'; color = '#fff'; }
      const label = isDone ? '✓' : isPickup ? 'P' : 'D';
      L.marker([lat, lng], {
        icon: makeStopIcon(label, bg, border, color, isCur ? 30 : 26),
        zIndexOffset: isCur ? 1000 : 0,
      })
        .bindPopup(`<b>${isPickup ? '📦 Pickup' : '🏠 Dropoff'} #${s.sequence}</b><br>${s.address?.city || s.address?.address_line_1 || ''}`)
        .addTo(markerGroup);
    });
    layersRef.current.stops = markerGroup;

    const histPts = (driverPath.length > 1 ? driverPath : locationHistory)
      .map(p => [Number(p.latitude), Number(p.longitude)])
      .filter(([lat, lng]) => inNepal(lat, lng));
    if (histPts.length > 1) {
      layersRef.current.historyLine = L.polyline(histPts, { color: '#7c3aed', weight: 3, opacity: 0.85, dashArray: '6 4' }).addTo(map);
    }

    if (completionPins.length > 0) {
      const pinGroup = L.layerGroup().addTo(map);
      completionPins.forEach(pin => {
        const color = pin.ok ? '#16a34a' : '#dc2626';
        const icon = L.divIcon({
          className: '',
          iconSize: [22, 22], iconAnchor: [11, 11], popupAnchor: [0, -14],
          html: `<div style="width:22px;height:22px;border-radius:50%;background:${color};border:2.5px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,0.3);display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:#fff">${pin.sequence}</div>`,
        });
        L.marker([pin.lat, pin.lng], { icon, zIndexOffset: 500 })
          .bindPopup(`<b>${pin.stop_type === 'pickup' ? '📦' : '🏠'} Stop ${pin.sequence} — ${pin.ok ? '✓ On location' : '⚠ Off location'}</b><br>${pin.city}<br><span style="font-size:10px;color:${pin.ok ? '#16a34a' : '#dc2626'}">${pin.distM}m from stop</span>`)
          .addTo(pinGroup);
        if (!pin.ok) {
          L.polyline([[pin.lat, pin.lng], [pin.stopLat, pin.stopLng]], { color, weight: 1.5, opacity: 0.6, dashArray: '4 3' }).addTo(pinGroup);
        }
      });
      layersRef.current.completionPins = pinGroup;
    }

    if (stopBounds.length > 0) {
      map.fitBounds(L.latLngBounds(stopBounds), { padding: [60, 60], maxZoom: 15 });
    }
    setTimeout(() => map.invalidateSize(), 100);

    if (geocodedStops.length >= 2) {
      const waypoints = geocodedStops.map(s => `${Number(s.longitude)},${Number(s.latitude)}`).join(';');
      fetch(`https://router.project-osrm.org/route/v1/driving/${waypoints}?overview=full&geometries=geojson`)
        .then(r => r.json())
        .then(data => {
          if (data.code !== 'Ok' || !data.routes?.[0]) return;
          const coords = data.routes[0].geometry.coordinates.map(([lng, lat]) => [lat, lng]);
          if (!leafletRef.current) return;
          if (layersRef.current.routeLine) { try { leafletRef.current.removeLayer(layersRef.current.routeLine); } catch {} }
          layersRef.current.routeLine = L.polyline(coords, { color: '#2563eb', weight: 4, opacity: 0.8 }).addTo(leafletRef.current);
        })
        .catch(() => {
          if (!leafletRef.current || stopBounds.length < 2) return;
          layersRef.current.routeLine = L.polyline(stopBounds, { color: accentHex, weight: 2, opacity: 0.5, dashArray: '6 5' }).addTo(leafletRef.current);
        });
    }
  }, [routeId, driverPath.length, locationHistory.length, completionPins.length]);

  useEffectD(() => {
    if (!showDriverPath || !sb || !routeId) return;
    sb.from('driver_location_history')
      .select('latitude, longitude, recorded_at')
      .eq('route_id', routeId)
      .order('recorded_at', { ascending: true })
      .limit(500)
      .then(({ data }) => {
        const pts = (data || []).filter(p => inNepal(Number(p.latitude), Number(p.longitude)));
        setDriverPath(pts);
        const completedStops = stops.filter(s => s.status === 'completed' && s.completed_at);
        const pins = completedStops.map(s => {
          const t = new Date(s.completed_at).getTime();
          let best = null, bestDiff = Infinity;
          pts.forEach(p => { const diff = Math.abs(new Date(p.recorded_at).getTime() - t); if (diff < bestDiff) { bestDiff = diff; best = p; } });
          if (!best) return null;
          const dLat = Number(best.latitude), dLng = Number(best.longitude);
          const sLat = Number(s.latitude), sLng = Number(s.longitude);
          const distM = Math.hypot((dLat - sLat) * 111320, (dLng - sLng) * 111320 * Math.cos(sLat * Math.PI / 180));
          return { lat: dLat, lng: dLng, stopLat: sLat, stopLng: sLng, sequence: s.sequence, stop_type: s.stop_type, distM: Math.round(distM), ok: distM < 200, city: s.address?.city || '' };
        }).filter(Boolean);
        setCompletionPins(pins);
      });
  }, [routeId, showDriverPath]);

  useEffectD(() => {
    if (!sb || !driverUserId) return;
    sb.from('delivery_partners')
      .select('last_location_latitude, last_location_longitude, last_location_updated_at')
      .eq('user_id', driverUserId)
      .single()
      .then(({ data }) => {
        if (data?.last_location_latitude && data?.last_location_longitude) {
          const lat = Number(data.last_location_latitude);
          const lng = Number(data.last_location_longitude);
          if (inNepal(lat, lng)) { setDriverPos([lat, lng]); setDriverUpdatedAt(data.last_location_updated_at || null); }
        }
      });
    const channel = sb.channel(`driver-loc-${driverUserId}`)
      .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'delivery_partners', filter: `user_id=eq.${driverUserId}` }, payload => {
        const row = payload.new;
        if (row.last_location_latitude && row.last_location_longitude) {
          const lat = Number(row.last_location_latitude);
          const lng = Number(row.last_location_longitude);
          if (inNepal(lat, lng)) { setDriverPos([lat, lng]); setDriverUpdatedAt(row.last_location_updated_at || null); }
        }
      })
      .subscribe();
    return () => { sb.removeChannel(channel); };
  }, [driverUserId]);

  useEffectD(() => {
    const map = leafletRef.current;
    if (!map || !window.L) return;
    const driverName = (route.driver?.display_name || 'Driver').split(' ')[0];
    if (driverMarkerRef.current) { try { map.removeLayer(driverMarkerRef.current); } catch {} driverMarkerRef.current = null; }
    if (driverPos) {
      const updatedStr = driverUpdatedAt ? new Date(driverUpdatedAt).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }) : '';
      driverMarkerRef.current = window.L.marker(driverPos, { icon: makeDriverIcon(driverName), zIndexOffset: 2000 })
        .bindPopup(`<b>${route.driver?.display_name || 'Driver'}</b>${updatedStr ? `<br><span style="font-size:10px;color:#666">Updated ${updatedStr}</span>` : ''}`)
        .addTo(map);
    }
  }, [driverPos]);

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 300 }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 8,
        padding: '5px 10px', borderBottom: '1px solid var(--hairline)',
        background: 'var(--surface-2)', flexShrink: 0,
      }}>
        {driverUserId && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 10.5, fontFamily: 'var(--font-mono)' }}>
            <span style={{ width: 6, height: 6, borderRadius: '50%', background: driverPos ? '#16a34a' : '#9C988D', display: 'inline-block' }} />
            {driverPos ? 'Driver live' : 'Awaiting location'}
          </div>
        )}
        <div style={{ marginLeft: 'auto', display: 'flex', gap: 14, alignItems: 'center' }}>
          <MapStat label="Done" v={`${route.progress?.completed_stops ?? 0}/${route.total_stops || 0}`} />
          <MapStat label="Distance" v={fmtDist(route.total_distance_m)} />
          <MapStat label="Duration" v={fmtDuration(route.total_duration_s)} />
        </div>
      </div>
      <div style={{ flex: 1, position: 'relative', minHeight: 0 }}>
        <div ref={mapRef} style={{ position: 'absolute', inset: 0, zIndex: 0 }} />
      </div>
    </div>
  );
};

// ── Assemble form (Dispatch New tab) ──────────────────────────────────────────

const AssembleForm = ({ pendingCount, onAssembled }) => {
  const I = window.Icons;
  const sb = window.supabaseClient;
  const [maxDeliveries, setMaxDeliveries] = useStateD(10);
  const [busy, setBusy] = useStateD(false);
  const [error, setError] = useStateD(null);

  const handleAssemble = async () => {
    setError(null);
    setBusy(true);
    const windowStart = new Date();
    const windowEnd = new Date(windowStart.getTime() + 8 * 60 * 60 * 1000);
    const { data: res, error: err } = await sb.rpc('assemble_standard_route', {
      p_dispatch_window: currentDispatchWindow(),
      p_window_start: windowStart.toISOString(),
      p_window_end: windowEnd.toISOString(),
      p_driver_id: null,
      p_max_deliveries: maxDeliveries,
      p_delivery_ids: null,
    });
    setBusy(false);
    if (err || !res?.success) {
      setError(res?.message ?? err?.message ?? 'No eligible deliveries');
      return;
    }
    onAssembled();
  };

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
        <div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 4 }}>Assemble route</div>
          <div style={{ fontSize: 12, color: 'var(--ink-2)' }}>Bundle pending deliveries into a new route for optimization</div>
        </div>
        <span className={`chip dot${pendingCount > 0 ? ' warn' : ''}`} style={{ flexShrink: 0, marginLeft: 12 }}>{pendingCount} queued</span>
      </div>

      <div style={{ display: 'flex', gap: 10, alignItems: 'flex-end' }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.05em', textTransform: 'uppercase' }}>Max stops</div>
          <input
            type="number" min={1} max={30} value={maxDeliveries}
            onChange={e => setMaxDeliveries(Number(e.target.value))}
            style={{
              width: 72, height: 34, fontSize: 14, textAlign: 'center',
              background: 'var(--surface-2)', border: '1px solid var(--hairline)',
              borderRadius: 5, color: 'var(--ink)', padding: '0 8px',
              fontFamily: 'var(--font-mono)', fontWeight: 600,
            }}
          />
        </div>
        <button
          className="btn primary"
          style={{ height: 34, fontSize: 12.5 }}
          disabled={busy || pendingCount === 0}
          onClick={handleAssemble}
        >
          <I.plus size={12} />
          {busy ? 'Assembling…' : `Assemble route · ${pendingCount} pending`}
        </button>
      </div>

      {error && (
        <div style={{ marginTop: 10, fontSize: 11.5, color: 'var(--neg)', display: 'flex', alignItems: 'center', gap: 5 }}>
          <span style={{ fontSize: 13 }}>⚠</span> {error}
        </div>
      )}
    </div>
  );
};

// ── Flash delivery detail panel ───────────────────────────────────────────────

const FlashDetail = ({ delivery }) => {
  const I = window.Icons;
  if (!delivery) {
    return (
      <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <span className="muted" style={{ fontSize: 12 }}>Select a delivery</span>
      </div>
    );
  }
  const meta = FLASH_STATUS_META[delivery.status] || { label: delivery.status, chip: 'warn' };
  const driverName = delivery.driver?.display_name || '—';

  return (
    <>
      <div className="panel-h"><span>Delivery detail</span></div>
      <div style={{ padding: 14, borderBottom: '1px solid var(--hairline)' }}>
        {delivery.driver ? (
          <div className="row gap-3" style={{ marginBottom: 14 }}>
            <div className="avatar" style={{ width: 36, height: 36, fontSize: 12 }}>{initials(driverName)}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontWeight: 550, color: 'var(--ink)', fontSize: 13.5 }}>{driverName}</div>
              <div className="id">{delivery.vehicle_type || '—'} · {delivery.driver?.phone || '—'}</div>
            </div>
            <span className={`chip dot ${meta.chip}`}>{meta.label}</span>
          </div>
        ) : (
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 14 }}>
            <span className={`chip dot ${meta.chip}`}>{meta.label}</span>
            <span className="muted" style={{ fontSize: 11.5 }}>No driver assigned</span>
          </div>
        )}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 10 }}>
          <RouteStat label="Tracking" value={<span className="id" style={{ color: 'var(--ink)' }}>{delivery.tracking_number || delivery.id.slice(0, 8).toUpperCase()}</span>} />
          <RouteStat label="Distance" value={fmtDistKm(delivery.distance_km)} />
          <RouteStat label="Fee" value={currency(delivery.fee)} />
          <RouteStat label="Order" value={delivery.order?.order_number || '—'} />
        </div>
      </div>
      <div style={{ flex: 1, overflow: 'auto', padding: '12px 14px' }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 10 }}>Route</div>

        <div style={{ display: 'grid', gridTemplateColumns: '24px 1fr', gap: 8, marginBottom: 10 }}>
          <div style={{ display: 'flex', justifyContent: 'center', paddingTop: 2 }}>
            <div style={{ width: 18, height: 18, borderRadius: '50%', background: '#f59e0b', border: '2px solid #fff', boxShadow: '0 1px 3px rgba(0,0,0,0.15)', display: 'grid', placeItems: 'center', fontSize: 10 }}>📦</div>
          </div>
          <div>
            <div style={{ fontSize: 12, fontWeight: 550, color: 'var(--ink)' }}>Pickup</div>
            <div className="muted" style={{ fontSize: 11.5, marginTop: 1 }}>
              {delivery.pickup_address ? [delivery.pickup_address.full_name, delivery.pickup_address.address_line_1, delivery.pickup_address.city].filter(Boolean).join(', ') : '—'}
            </div>
            {delivery.picked_up_at && <div className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', marginTop: 2 }}>Picked up {fmtTime(delivery.picked_up_at)}</div>}
          </div>
        </div>

        <div style={{ marginLeft: 11, width: 1, height: 20, background: 'var(--hairline)', marginBottom: 6 }} />

        <div style={{ display: 'grid', gridTemplateColumns: '24px 1fr', gap: 8 }}>
          <div style={{ display: 'flex', justifyContent: 'center', paddingTop: 2 }}>
            <div style={{ width: 18, height: 18, borderRadius: '50%', background: '#16a34a', border: '2px solid #fff', boxShadow: '0 1px 3px rgba(0,0,0,0.15)', display: 'grid', placeItems: 'center', fontSize: 10 }}>🏠</div>
          </div>
          <div>
            <div style={{ fontSize: 12, fontWeight: 550, color: 'var(--ink)' }}>Dropoff</div>
            <div className="muted" style={{ fontSize: 11.5, marginTop: 1 }}>
              {delivery.delivery_address ? [delivery.delivery_address.full_name, delivery.delivery_address.address_line_1, delivery.delivery_address.city].filter(Boolean).join(', ') : '—'}
            </div>
            {delivery.estimated_arrival && <div className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', marginTop: 2 }}>ETA {fmtTime(delivery.estimated_arrival)}</div>}
            {delivery.delivered_at && <div className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', marginTop: 2 }}>Delivered {fmtTime(delivery.delivered_at)}</div>}
          </div>
        </div>

        {(delivery.assigned_at || delivery.created_at) && (
          <div style={{ marginTop: 16, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            <RouteStat label="Created" value={fmtDate(delivery.created_at)} />
            {delivery.assigned_at && <RouteStat label="Assigned" value={fmtDate(delivery.assigned_at)} />}
            {delivery.delivered_at && <RouteStat label="Delivered" value={fmtDate(delivery.delivered_at)} />}
          </div>
        )}
      </div>
    </>
  );
};

// ── Flash list row ─────────────────────────────────────────────────────────────

const FlashRow = ({ delivery, selected, onClick }) => {
  const meta = FLASH_STATUS_META[delivery.status] || { label: delivery.status, chip: 'warn' };
  return (
    <div onClick={onClick} style={{
      padding: '12px 14px', borderBottom: '1px solid var(--hairline)',
      background: selected ? 'var(--surface-2)' : 'transparent',
      cursor: 'pointer', position: 'relative',
    }}>
      {selected && <div style={{ position: 'absolute', left: 0, top: 8, bottom: 8, width: 2, background: 'var(--warn, #f59e0b)' }} />}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        <span className="id" style={{ color: 'var(--ink)' }}>{delivery.tracking_number || delivery.id.slice(0, 8).toUpperCase()}</span>
        <span className={`chip dot ${meta.chip}`}>{meta.label}</span>
      </div>
      <div style={{ marginTop: 4, fontSize: 12, color: 'var(--ink-2)' }}>
        {fmtAddrShort(delivery.pickup_address)} → {fmtAddrShort(delivery.delivery_address)}
      </div>
      <div className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)', marginTop: 2 }}>
        {delivery.driver?.display_name || 'Unassigned'} · {fmtDistKm(delivery.distance_km)} · {currency(delivery.order?.total_amount)}
      </div>
    </div>
  );
};

// ── Main page ──────────────────────────────────────────────────────────────────

const DispatchPage = () => {
  const I = window.Icons;
  const sb = window.supabaseClient;

  // delivery type toggle: 'dispatch' | 'flash'
  const [deliveryType, setDeliveryType] = useStateD('dispatch');
  const [tab, setTab] = useStateD('active');

  // Dispatch state
  const [routes, setRoutes] = useStateD([]);
  const [completedRoutes, setCompletedRoutes] = useStateD([]);
  const [completedFetched, setCompletedFetched] = useStateD(false);
  const [loadingCompleted, setLoadingCompleted] = useStateD(false);
  const [drivers, setDrivers] = useStateD([]);
  const [pendingDeliveries, setPendingDeliveries] = useStateD([]);
  const [loading, setLoading] = useStateD(true);
  const [selectedId, setSelectedId] = useStateD(null);
  const [completedSelId, setCompletedSelId] = useStateD(null);

  // Planned routes state
  const [plannedRoutes, setPlannedRoutes] = useStateD([]);
  const [cronTier, setCronTier] = useStateD('standard');
  const [cronBusy, setCronBusy] = useStateD(false);
  const [cronResult, setCronResult] = useStateD(null);
  const [cronError, setCronError] = useStateD('');
  const [plannedFetched, setPlannedFetched] = useStateD(false);
  const [loadingPlanned, setLoadingPlanned] = useStateD(false);
  const [plannedSelId, setPlannedSelId] = useStateD(null);
  const [dispatchingPlanned, setDispatchingPlanned] = useStateD({});
  const [plannedError, setPlannedError] = useStateD('');
  const [copiedRouteId, setCopiedRouteId] = useStateD(null);
  const [manualDispatch, setManualDispatch] = useStateD(null); // { routeId, drivers[] }
  const [manualDriverId, setManualDriverId] = useStateD('');
  const [manualDispatching, setManualDispatching] = useStateD(false);

  // Flash state
  const [flashNew, setFlashNew] = useStateD([]);
  const [flashActive, setFlashActive] = useStateD([]);
  const [flashCompleted, setFlashCompleted] = useStateD([]);
  const [flashCompletedFetched, setFlashCompletedFetched] = useStateD(false);
  const [loadingFlashCompleted, setLoadingFlashCompleted] = useStateD(false);
  const [flashNewSelId, setFlashNewSelId] = useStateD(null);
  const [flashActiveSelId, setFlashActiveSelId] = useStateD(null);
  const [flashCompletedSelId, setFlashCompletedSelId] = useStateD(null);
  const [loadingFlash, setLoadingFlash] = useStateD(true);

  // Dispatch action state
  const [addingMore, setAddingMore] = useStateD(false);
  const [addError, setAddError] = useStateD('');
  const [dispatchDriver, setDispatchDriver] = useStateD('');
  const [dispatching, setDispatching] = useStateD(false);
  const [optimizing, setOptimizing] = useStateD(false);
  const [actionError, setActionError] = useStateD('');

  const timerRef = useRefD(null);

  const pendingCount = pendingDeliveries.length;

  const doRefreshDispatch = async () => {
    const [r, d, pd] = await Promise.all([
      dbFetchActiveRoutes(sb),
      dbFetchDriversList(sb),
      dbFetchPendingDeliveries(sb),
    ]);
    setRoutes(r);
    setDrivers(d);
    setPendingDeliveries(pd);
    setLoading(false);
    setSelectedId(prev => {
      if (prev && r.find(x => x.id === prev)) return prev;
      return r.length > 0 ? r[0].id : null;
    });
  };

  const doRefreshCompleted = async () => {
    setLoadingCompleted(true);
    const r = await dbFetchCompletedRoutes(sb);
    setCompletedRoutes(r);
    setCompletedFetched(true);
    setLoadingCompleted(false);
    setCompletedSelId(prev => {
      if (prev && r.find(x => x.id === prev)) return prev;
      return r.length > 0 ? r[0].id : null;
    });
  };

  const doRefreshPlanned = async () => {
    setLoadingPlanned(true);
    const r = await dbFetchPlannedRoutes(sb);
    setPlannedRoutes(r);
    setPlannedFetched(true);
    setLoadingPlanned(false);
    setPlannedSelId(prev => {
      if (prev && r.find(x => x.id === prev)) return prev;
      return r.length > 0 ? r[0].id : null;
    });
  };

  const doRefreshFlash = async () => {
    const [fn, fa] = await Promise.all([dbFetchFlashNew(sb), dbFetchFlashActive(sb)]);
    setFlashNew(fn);
    setFlashActive(fa);
    setLoadingFlash(false);
    setFlashNewSelId(prev => (prev && fn.find(x => x.id === prev)) ? prev : fn.length > 0 ? fn[0].id : null);
    setFlashActiveSelId(prev => (prev && fa.find(x => x.id === prev)) ? prev : fa.length > 0 ? fa[0].id : null);
  };

  const doRefreshFlashCompleted = async () => {
    setLoadingFlashCompleted(true);
    const fc = await dbFetchFlashCompleted(sb);
    setFlashCompleted(fc);
    setFlashCompletedFetched(true);
    setLoadingFlashCompleted(false);
    setFlashCompletedSelId(prev => (prev && fc.find(x => x.id === prev)) ? prev : fc.length > 0 ? fc[0].id : null);
  };

  useEffectD(() => {
    if (!sb) return;
    doRefreshDispatch();
    doRefreshFlash();
    timerRef.current = setInterval(() => {
      doRefreshDispatch();
      doRefreshFlash();
    }, 30000);
    return () => { if (timerRef.current) clearInterval(timerRef.current); };
  }, []);

  const route = routes.find(r => r.id === selectedId) || null;
  const driverName = route?.driver?.display_name || '—';
  const prog = route?.progress || null;
  const doneStops = prog?.completed_stops ?? 0;
  const totalStops = route?.total_stops || 0;
  const gmv = (route?.deliveries || []).reduce((s, d) => s + Number(d.order?.total_amount || 0), 0);
  const stops = route?.stops || [];
  const firstPendingIdx = stops.findIndex(s => s.status === 'pending');
  const delivMap = Object.fromEntries((route?.deliveries || []).map(d => [d.id, d]));
  const completedRoute = completedRoutes.find(r => r.id === completedSelId) || null;
  const completedGmv = (completedRoute?.deliveries || []).reduce((s, d) => s + Number(d.order?.total_amount || 0), 0);

  const handleTabChange = t => {
    setTab(t);
    if (deliveryType === 'dispatch' && t === 'completed' && !completedFetched) doRefreshCompleted();
    if (deliveryType === 'dispatch' && t === 'planned' && !plannedFetched) doRefreshPlanned();
    if (deliveryType === 'flash' && t === 'completed' && !flashCompletedFetched) doRefreshFlashCompleted();
  };

  const handleTypeChange = t => {
    setDeliveryType(t);
    setTab('active');
    if (t === 'flash' && !flashActive.length && !loadingFlash) doRefreshFlash();
  };

  const handleAddMore = async () => {
    const activeRoute = routes.find(r => r.id === selectedId && r.status === 'dispatched') || routes.find(r => r.status === 'dispatched');
    if (!activeRoute) return;
    setAddingMore(true); setAddError('');
    const { data, error } = await sb.rpc('add_deliveries_to_route', { p_route_id: activeRoute.id, p_max_to_add: 5 });
    if (error || !data?.success || data.added === 0) {
      setAddError(data?.message || error?.message || 'No pending deliveries to add');
    } else {
      await doRefreshDispatch();
    }
    setAddingMore(false);
  };

  // Build ORS shipments payload from geocoded stops and a driver start coordinate.
  // Returns { orderedStops, polyline, totalDist, totalDur } or throws.
  // Merged pickups (same seller, multiple deliveries) produce one shipment per
  // delivery so VROOM enforces pickup-before-dropoff for every package while the
  // driver only physically visits the seller once.
  const runOrsOptimize = async (geocodedStops, driverLng, driverLat) => {
    const pickups  = geocodedStops.filter(s => s.stop_type === 'pickup');
    const dropoffs = geocodedStops.filter(s => s.stop_type === 'dropoff');
    const dropoffByDelivery = new Map(dropoffs.map(d => [d.delivery_id, d]));

    // Group pickups by location (rounded to 4dp ≈ 11m) so same-seller stops merge.
    const pickupGroups = new Map();
    for (const p of pickups) {
      const key = `${Number(p.latitude).toFixed(4)},${Number(p.longitude).toFixed(4)}`;
      if (!pickupGroups.has(key)) pickupGroups.set(key, []);
      pickupGroups.get(key).push(p);
    }

    const shipments = [], jobs = [], pairedDropoffIds = new Set();
    // pickupStepIdToStop: every ORS pickup step id → its route_stop row
    const pickupStepIdToStop = new Map();
    // delivStepIdToStop: every ORS delivery step id → its route_stop row
    const delivStepIdToStop = new Map();
    // emitted pickup stop ids — for deduplication in result reconstruction
    const emittedPickupIds = new Set();
    let vid = 0;

    for (const [, group] of pickupGroups) {
      const pairedInGroup = group.filter(p => dropoffByDelivery.has(p.delivery_id));
      if (pairedInGroup.length === 0) {
        // No dropoff match — send as a bare job using the first stop in the group
        jobs.push({ id: vid++, location: [Number(group[0].longitude), Number(group[0].latitude)], _stop: group[0] });
        continue;
      }
      // One shipment per delivery, all sharing the same pickup coordinates
      for (const p of pairedInGroup) {
        const d = dropoffByDelivery.get(p.delivery_id);
        pairedDropoffIds.add(d.id);
        const pickupStepId   = vid++;
        const deliveryStepId = vid++;
        pickupStepIdToStop.set(pickupStepId,   p);
        delivStepIdToStop.set(deliveryStepId, d);
        shipments.push({
          id: vid++,
          pickup:   { id: pickupStepId,   location: [Number(p.longitude), Number(p.latitude)] },
          delivery: { id: deliveryStepId, location: [Number(d.longitude), Number(d.latitude)] },
        });
      }
    }
    for (const d of dropoffs) {
      if (!pairedDropoffIds.has(d.id))
        jobs.push({ id: vid++, location: [Number(d.longitude), Number(d.latitude)], _stop: d });
    }

    const orsBody = {
      vehicles: [{ id: 0, profile: 'driving-car', start: [driverLng, driverLat] }],
      shipments: shipments.map(({ id, pickup, delivery }) => ({
        id,
        pickup:   { id: pickup.id,   location: pickup.location },
        delivery: { id: delivery.id, location: delivery.location },
      })),
      jobs: jobs.map(({ id, location }) => ({ id, location })),
      options: { g: true },
    };

    const res = await fetch('https://api.openrouteservice.org/optimization', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'Authorization': window.ORS_API_KEY },
      body: JSON.stringify(orsBody),
    });
    if (!res.ok) throw new Error(`ORS ${res.status}`);
    const data = await res.json();
    const orsRoute = data.routes?.[0];
    if (!orsRoute) throw new Error('ORS returned no route');

    const jobStepMap = new Map(jobs.map(j => [j.id, j._stop]));
    const ordered = [];
    for (const step of orsRoute.steps) {
      if (step.type === 'start' || step.type === 'end') continue;
      if (step.type === 'pickup') {
        const stop = pickupStepIdToStop.get(step.id);
        if (stop && !emittedPickupIds.has(stop.id)) {
          emittedPickupIds.add(stop.id);
          ordered.push(stop);
        }
      } else if (step.type === 'delivery') {
        const stop = delivStepIdToStop.get(step.id);
        if (stop) ordered.push(stop);
      } else if (step.type === 'job') {
        const stop = jobStepMap.get(step.id);
        if (stop) ordered.push(stop);
      }
    }

    // VROOM step.distance and step.duration are CUMULATIVE from route start.
    // Total route distance = last non-end step's cumulative value.
    const activeSteps = (orsRoute.steps || []).filter(st => st.type !== 'end');
    const lastStep = activeSteps[activeSteps.length - 1];
    const totalDist = Math.round(lastStep?.distance ?? 0);
    const totalDur  = Math.round(lastStep?.duration ?? 0);
    return {
      orderedStops: ordered.length >= 2 ? ordered : geocodedStops,
      polyline:     JSON.stringify(orsRoute.geometry?.coordinates ?? []),
      totalDist,
      totalDur,
    };
  };

  // Fetch online drivers and their display names (two-step: partners then profiles).
  const fetchOnlineDrivers = async () => {
    const { data: partners } = await sb.from('delivery_partners')
      .select('user_id, last_location_latitude, last_location_longitude, vehicle_type')
      .eq('is_active', true)
      .eq('is_online', true);
    if (!partners?.length) return [];
    const ids = partners.map(p => p.user_id);
    const { data: profiles } = await sb.from('user_profiles')
      .select('id, display_name, username')
      .in('id', ids);
    const profileMap = {};
    (profiles || []).forEach(p => { profileMap[p.id] = p; });
    return partners.map(p => ({
      id:      p.user_id,
      lat:     p.last_location_latitude  ? Number(p.last_location_latitude)  : null,
      lng:     p.last_location_longitude ? Number(p.last_location_longitude) : null,
      name:    profileMap[p.user_id]?.display_name || profileMap[p.user_id]?.username || p.user_id.slice(0, 8),
      vehicle: p.vehicle_type,
    }));
  };

  // Drivers with a valid Nepal GPS fix — used for ORS auction.
  const getLocatedDrivers = async () =>
    (await fetchOnlineDrivers()).filter(p => p.lat && p.lng && inNepal(p.lat, p.lng));

  // All online drivers (GPS optional) — used for manual assignment fallback.
  const getAllOnlineDrivers = async () => fetchOnlineDrivers();

  const handleOptimize = async () => {
    const targetRoute = routes.find(r => r.id === selectedId) || routes.find(r => r.status === 'assembling' || r.status === 'optimized');
    if (!targetRoute) { console.warn('[optimize] no targetRoute found'); return; }
    setOptimizing(true); setActionError('');

    const geocodedStops = (targetRoute.stops || [])
      .filter(s => s.latitude && s.longitude)
      .sort((a, b) => (a.sequence || 0) - (b.sequence || 0));

    if (geocodedStops.length < 2) {
      setActionError('Not enough geocoded stops to optimize');
      setOptimizing(false);
      return;
    }

    // Use selected driver's GPS if available, else city center fallback
    const selectedDriverInfo = drivers.find(d => d.id === dispatchDriver);
    let startLng = 85.324, startLat = 27.7172;
    if (dispatchDriver) {
      const { data: partnerRow } = await sb.from('delivery_partners')
        .select('last_location_latitude, last_location_longitude')
        .eq('user_id', dispatchDriver)
        .single();
      const lat = Number(partnerRow?.last_location_latitude);
      const lng = Number(partnerRow?.last_location_longitude);
      if (lat && lng && inNepal(lat, lng)) { startLat = lat; startLng = lng; }
    }

    try {
      const { orderedStops, polyline, totalDist, totalDur } = await runOrsOptimize(geocodedStops, startLng, startLat);
      const stopSeqs = orderedStops.map((s, i) => ({ stop_id: s.id, sequence: i + 1 }));
      const { error } = await sb.rpc('apply_osrm_sequence', {
        p_route_id: targetRoute.id,
        p_stop_sequences: stopSeqs,
        p_polyline: polyline,
        p_total_distance: totalDist,
        p_total_duration: totalDur,
      });
      if (error) throw new Error(error.message);
      console.log('[optimize] done, dist:', totalDist, 'stops:', orderedStops.length);
    } catch (e) {
      console.error('[optimize] failed:', e);
      setActionError('Optimization failed: ' + e.message);
      setOptimizing(false);
      return;
    }

    setOptimizing(false);
    const prevId = selectedId;
    setSelectedId(null);
    await doRefreshDispatch();
    setSelectedId(prevId);
  };

  // Optimize + auto-assign best driver in one shot.
  const handleOptimizeAndDispatch = async () => {
    const targetRoute = routes.find(r => r.id === selectedId) || routes.find(r => r.status === 'assembling' || r.status === 'optimized');
    if (!targetRoute) { console.warn('[optimize+dispatch] no targetRoute'); return; }
    setDispatching(true); setActionError('');

    const geocodedStops = (targetRoute.stops || [])
      .filter(s => s.latitude && s.longitude)
      .sort((a, b) => (a.sequence || 0) - (b.sequence || 0));

    if (geocodedStops.length < 2) {
      setActionError('Not enough geocoded stops to optimize');
      setDispatching(false);
      return;
    }

    // If a driver is manually selected, use them directly (no auction).
    // Otherwise run ORS for every located online driver and pick shortest route.
    let bestDriverId = dispatchDriver || null;
    let bestResult = null;

    try {
      if (bestDriverId) {
        const { data: partnerRow } = await sb.from('delivery_partners')
          .select('last_location_latitude, last_location_longitude')
          .eq('user_id', bestDriverId)
          .single();
        const lat = Number(partnerRow?.last_location_latitude);
        const lng = Number(partnerRow?.last_location_longitude);
        const startLat = (lat && lng && inNepal(lat, lng)) ? lat : 27.7172;
        const startLng = (lat && lng && inNepal(lat, lng)) ? lng : 85.324;
        bestResult = await runOrsOptimize(geocodedStops, startLng, startLat);
      } else {
        const locatedDrivers = await getLocatedDrivers();
        if (!locatedDrivers.length) {
          setActionError('No online drivers with GPS location found. Select a driver manually.');
          setDispatching(false);
          return;
        }
        // Run ORS for all drivers in parallel, pick shortest total distance
        const results = await Promise.all(
          locatedDrivers.map(async driver => {
            try {
              const result = await runOrsOptimize(geocodedStops, driver.lng, driver.lat);
              return { driver, result };
            } catch { return null; }
          })
        );
        const valid = results.filter(Boolean).sort((a, b) => a.result.totalDist - b.result.totalDist);
        if (!valid.length) throw new Error('ORS optimization failed for all drivers');
        bestDriverId = valid[0].driver.id;
        bestResult   = valid[0].result;
        console.log('[optimize+dispatch] best driver:', bestDriverId, 'dist:', bestResult.totalDist,
          'vs others:', valid.map(v => ({ id: v.driver.id, dist: v.result.totalDist })));
      }

      // Persist the winning sequence
      const stopSeqs = bestResult.orderedStops.map((s, i) => ({ stop_id: s.id, sequence: i + 1 }));
      const { error: seqErr } = await sb.rpc('apply_osrm_sequence', {
        p_route_id: targetRoute.id,
        p_stop_sequences: stopSeqs,
        p_polyline: bestResult.polyline,
        p_total_distance: bestResult.totalDist,
        p_total_duration: bestResult.totalDur,
      });
      if (seqErr) throw new Error(seqErr.message);

      // Dispatch to the winning driver
      const { data: dispatchRes, error: dispatchErr } = await sb.rpc('dispatch_route', {
        p_route_id: targetRoute.id,
        p_driver_id: bestDriverId,
      });
      if (dispatchErr || !dispatchRes?.success) throw new Error(dispatchRes?.message || dispatchErr?.message || 'Dispatch failed');

    } catch (e) {
      console.error('[optimize+dispatch] failed:', e);
      setActionError(e.message);
      setDispatching(false);
      return;
    }

    setDispatching(false);
    setDispatchDriver('');
    await doRefreshDispatch();
    setTab('active');
  };

  const handleDeleteRoute = async (routeId) => {
    if (!routeId) return;
    setActionError('');
    // 1. Release deliveries back to pending pool
    await sb.from('deliveries').update({ route_id: null }).eq('route_id', routeId);
    // 2. Delete stops
    await sb.from('route_stops').delete().eq('route_id', routeId);
    // 3. Delete route
    const { error } = await sb.from('routes').delete().eq('id', routeId);
    if (error) { setActionError('Delete failed: ' + error.message); return; }
    setSelectedId(null);
    await doRefreshDispatch();
    setTab('new');
  };

  const handleDispatch = async () => {
    const stagingRoute = routes.find(r => r.id === selectedId && (r.status === 'assembling' || r.status === 'optimized'));
    if (!stagingRoute || !dispatchDriver) return;
    setDispatching(true); setActionError('');
    const { error } = await sb.rpc('dispatch_route', { p_route_id: stagingRoute.id, p_driver_id: dispatchDriver });
    setDispatching(false);
    if (error) { setActionError(error.message); return; }
    setDispatchDriver('');
    await doRefreshDispatch();
    setTab('active');
  };

  // ── type toggle ──────────────────────────────────────────────────────────────

  const TypeToggle = () => (
    <div style={{ display: 'flex', gap: 0, background: 'var(--surface-2)', border: '1px solid var(--hairline)', borderRadius: 6, padding: 3, width: 'fit-content', marginBottom: 14 }}>
      {[
        { id: 'dispatch', label: 'Dispatch' },
        { id: 'flash',    label: 'Flash' },
      ].map(({ id, label }) => (
        <button key={id} onClick={() => handleTypeChange(id)}
          style={{
            padding: '5px 16px', borderRadius: 4, border: 'none', cursor: 'pointer',
            fontSize: 12.5, fontWeight: 550,
            background: deliveryType === id ? 'var(--surface)' : 'transparent',
            color: deliveryType === id ? 'var(--ink)' : 'var(--ink-3)',
            boxShadow: deliveryType === id ? '0 1px 3px rgba(0,0,0,0.08)' : 'none',
            transition: 'all 0.15s',
          }}>
          {id === 'flash' && <span style={{ marginRight: 4, fontSize: 11 }}>⚡</span>}
          {label}
        </button>
      ))}
    </div>
  );

  // ── Shared 3-column layout shell ─────────────────────────────────────────────

  const ThreeCol = ({ left, center, right }) => (
    <div className="mob-stack" style={{ display: 'grid', gridTemplateColumns: '300px 1fr 340px', gap: 14, height: 'calc(100vh - 260px)', minHeight: 520 }}>
      <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>{left}</div>
      <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>{center}</div>
      <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>{right}</div>
    </div>
  );

  // ── Flash New tab ─────────────────────────────────────────────────────────────

  const FlashNewTab = () => {
    const sel = flashNew.find(d => d.id === flashNewSelId) || null;
    return (
      <ThreeCol
        left={
          <>
            <div className="panel-h">
              <span>New Flash</span>
              <div className="right"><I.refresh size={13} className="muted" style={{ cursor: 'pointer' }} onClick={doRefreshFlash} /></div>
            </div>
            <div style={{ flex: 1, overflow: 'auto' }}>
              {loadingFlash ? (
                <div className="muted" style={{ padding: 16, fontSize: 12 }}>Loading…</div>
              ) : flashNew.length === 0 ? (
                <div className="muted" style={{ padding: 16, fontSize: 12 }}>No new flash deliveries.</div>
              ) : flashNew.map(d => (
                <FlashRow key={d.id} delivery={d} selected={d.id === flashNewSelId} onClick={() => setFlashNewSelId(d.id)} />
              ))}
            </div>
            <div style={{ padding: '8px 14px', borderTop: '1px solid var(--hairline)' }}>
              <span className={`chip dot${flashNew.length > 0 ? ' warn' : ''}`}>{flashNew.length} unassigned</span>
            </div>
          </>
        }
        center={
          !sel ? (
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <span className="muted" style={{ fontSize: 12 }}>Select a delivery</span>
            </div>
          ) : (
            <>
              <div className="panel-h" style={{ padding: '3px 14px 0', height: 40 }}>
                <span>{sel.tracking_number || sel.id.slice(0, 8).toUpperCase()}</span>
                <span className={`chip dot ${FLASH_STATUS_META[sel.status]?.chip || 'warn'}`}>{FLASH_STATUS_META[sel.status]?.label || sel.status}</span>
              </div>
              <FlashMap delivery={sel} />
            </>
          )
        }
        right={<FlashDetail delivery={sel} />}
      />
    );
  };

  // ── Flash Active tab ──────────────────────────────────────────────────────────

  const FlashActiveTab = () => {
    const sel = flashActive.find(d => d.id === flashActiveSelId) || null;
    return (
      <ThreeCol
        left={
          <>
            <div className="panel-h">
              <span>Active Flash</span>
              <div className="right"><I.refresh size={13} className="muted" style={{ cursor: 'pointer' }} onClick={doRefreshFlash} /></div>
            </div>
            <div style={{ flex: 1, overflow: 'auto' }}>
              {loadingFlash ? (
                <div className="muted" style={{ padding: 16, fontSize: 12 }}>Loading…</div>
              ) : flashActive.length === 0 ? (
                <div className="muted" style={{ padding: 16, fontSize: 12 }}>No active flash deliveries.</div>
              ) : flashActive.map(d => (
                <FlashRow key={d.id} delivery={d} selected={d.id === flashActiveSelId} onClick={() => setFlashActiveSelId(d.id)} />
              ))}
            </div>
          </>
        }
        center={
          !sel ? (
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <span className="muted" style={{ fontSize: 12 }}>Select a delivery</span>
            </div>
          ) : (
            <>
              <div className="panel-h" style={{ padding: '3px 14px 0', height: 40 }}>
                <span>{sel.tracking_number || sel.id.slice(0, 8).toUpperCase()} · {sel.driver?.display_name || '—'}</span>
                <div className="right">
                  <button className="btn ghost" style={{ height: 24 }} onClick={doRefreshFlash}><I.refresh size={11} />Re-fetch</button>
                </div>
              </div>
              <FlashMap delivery={sel} />
            </>
          )
        }
        right={<FlashDetail delivery={sel} />}
      />
    );
  };

  // ── Flash Completed tab ───────────────────────────────────────────────────────

  const FlashCompletedTab = () => {
    const sel = flashCompleted.find(d => d.id === flashCompletedSelId) || null;
    if (!flashCompletedFetched) {
      return (
        <div className="panel" style={{ padding: 32, textAlign: 'center', maxWidth: 400 }}>
          <button className="btn primary" onClick={doRefreshFlashCompleted}><I.refresh size={12} />Load completed flash</button>
        </div>
      );
    }
    if (loadingFlashCompleted) return <div className="muted" style={{ padding: 24, fontSize: 12 }}>Loading…</div>;
    if (flashCompleted.length === 0) {
      return (
        <div className="panel" style={{ padding: 24, textAlign: 'center', maxWidth: 400 }}>
          <div className="muted" style={{ fontSize: 13 }}>No completed flash deliveries</div>
        </div>
      );
    }
    return (
      <ThreeCol
        left={
          <>
            <div className="panel-h">
              <span>Completed Flash</span>
              <button className="btn ghost" style={{ height: 24 }} onClick={doRefreshFlashCompleted}><I.refresh size={11} /></button>
            </div>
            <div style={{ flex: 1, overflow: 'auto' }}>
              {flashCompleted.map(d => (
                <FlashRow key={d.id} delivery={d} selected={d.id === flashCompletedSelId} onClick={() => setFlashCompletedSelId(d.id)} />
              ))}
            </div>
          </>
        }
        center={
          !sel ? (
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <span className="muted" style={{ fontSize: 12 }}>Select a delivery</span>
            </div>
          ) : (
            <>
              <div className="panel-h" style={{ padding: '3px 14px 0', height: 40 }}>
                <span>{sel.tracking_number || sel.id.slice(0, 8).toUpperCase()} · {sel.driver?.display_name || '—'}</span>
                <span className={`chip dot ${FLASH_STATUS_META[sel.status]?.chip || 'pos'}`}>{FLASH_STATUS_META[sel.status]?.label || sel.status}</span>
              </div>
              <FlashMap delivery={sel} showDriverPath={true} />
            </>
          )
        }
        right={<FlashDetail delivery={sel} />}
      />
    );
  };

  // ── Render ────────────────────────────────────────────────────────────────────

  return (
    <div className="page" data-screen-label="02 Dispatch">
      <div className="page-h">
        <div>
          <div className="ts"><span className="live">LIVE</span><span style={{ margin: '0 8px' }}>·</span>Routing · ORS · Kathmandu</div>
          <h1>{deliveryType === 'flash' ? 'Flash' : 'Dispatch'}</h1>
        </div>
        <div className="acts">
          <button className="btn" onClick={() => { doRefreshDispatch(); doRefreshFlash(); }}><I.refresh size={12} />Refresh</button>
          {deliveryType === 'dispatch' && (
            <button className="btn primary" onClick={() => setTab('new')}><I.plus size={12} />New route</button>
          )}
        </div>
      </div>

      <TypeToggle />

      {/* Tabs */}
      <div className="ftabs" style={{ marginBottom: 14 }}>
        {deliveryType === 'dispatch' ? (
          <>
            <div className={'ftab' + (tab === 'new' ? ' active' : '')} onClick={() => handleTabChange('new')}>
              New {pendingCount > 0 && <span className="ct">{pendingCount}</span>}
            </div>
            <div className={'ftab' + (tab === 'planned' ? ' active' : '')} onClick={() => handleTabChange('planned')}>
              Planned {plannedRoutes.length > 0 && <span className="ct">{plannedRoutes.length}</span>}
            </div>
            <div className={'ftab' + (tab === 'active' ? ' active' : '')} onClick={() => handleTabChange('active')}>
              Active {routes.filter(r => r.status === 'dispatched').length > 0 && <span className="ct">{routes.filter(r => r.status === 'dispatched').length}</span>}
            </div>
            <div className={'ftab' + (tab === 'completed' ? ' active' : '')} onClick={() => handleTabChange('completed')}>
              Completed
            </div>
          </>
        ) : (
          <>
            <div className={'ftab' + (tab === 'new' ? ' active' : '')} onClick={() => handleTabChange('new')}>
              New {flashNew.length > 0 && <span className="ct">{flashNew.length}</span>}
            </div>
            <div className={'ftab' + (tab === 'active' ? ' active' : '')} onClick={() => handleTabChange('active')}>
              Active {flashActive.length > 0 && <span className="ct">{flashActive.length}</span>}
            </div>
            <div className={'ftab' + (tab === 'completed' ? ' active' : '')} onClick={() => handleTabChange('completed')}>
              Completed
            </div>
          </>
        )}
      </div>

      {/* ── DISPATCH: New tab ── */}
      {deliveryType === 'dispatch' && tab === 'new' && (() => {
        // Assembling/optimized routes stay here until dispatched
        const stagingRoutes = routes.filter(r => r.status === 'assembling' || r.status === 'optimized');
        const stagingRoute = stagingRoutes.find(r => r.id === selectedId) || stagingRoutes[0] || null;
        const sStops = stagingRoute?.stops || [];
        const sDelivMap = Object.fromEntries((stagingRoute?.deliveries || []).map(d => [d.id, d]));
        const sGmv = (stagingRoute?.deliveries || []).reduce((s, d) => s + Number(d.order?.total_amount || 0), 0);

        // Step indicator
        const step = !stagingRoute ? 0 : stagingRoute.status === 'assembling' ? 1 : 2;
        const steps = [
          { n: 1, label: 'Queue' },
          { n: 2, label: 'Optimize' },
          { n: 3, label: 'Dispatch' },
        ];

        return (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>

            {/* Step progress bar */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 0, marginBottom: 2 }}>
              {steps.map((s, i) => {
                const done = step > s.n;
                const active = step === s.n - 1 || (s.n === 1 && step === 0) || (s.n === 2 && step === 1) || (s.n === 3 && step === 2);
                const lineColor = done ? 'var(--accent)' : 'var(--hairline)';
                return (
                  <React.Fragment key={s.n}>
                    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
                      <div style={{
                        width: 26, height: 26, borderRadius: '50%', display: 'grid', placeItems: 'center',
                        background: done ? 'var(--accent)' : active ? 'var(--surface-2)' : 'var(--surface-2)',
                        border: active ? '2px solid var(--accent)' : done ? 'none' : '1px solid var(--hairline)',
                        color: done ? '#fff' : active ? 'var(--accent)' : 'var(--ink-3)',
                        fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700,
                      }}>
                        {done ? '✓' : s.n}
                      </div>
                      <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: active ? 'var(--ink)' : done ? 'var(--accent)' : 'var(--ink-3)', letterSpacing: '0.04em', textTransform: 'uppercase' }}>{s.label}</span>
                    </div>
                    {i < steps.length - 1 && (
                      <div style={{ flex: 1, height: 1, background: lineColor, marginBottom: 18, marginLeft: 4, marginRight: 4 }} />
                    )}
                  </React.Fragment>
                );
              })}
            </div>

            {/* ── STEP 1: Queue view ── */}
            {step === 0 && (
              <div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 10, marginBottom: 14 }}>
                  {[
                    { label: 'Same Day', count: pendingDeliveries.filter(d => d.delivery_tier === 'standard').length, accent: true },
                    { label: 'Economy',  count: pendingDeliveries.filter(d => d.delivery_tier === 'economy').length,  accent: false },
                    { label: 'Total',    count: pendingCount, accent: false },
                  ].map(({ label, count, accent }) => (
                    <div key={label} className="panel" style={{ padding: '12px 16px' }}>
                      <div className="num" style={{ fontSize: 24, fontWeight: 700, color: accent ? 'var(--accent)' : 'var(--ink)' }}>{count}</div>
                      <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>{label}</div>
                    </div>
                  ))}
                </div>

                {pendingCount > 0 && (
                  <div className="panel" style={{ marginBottom: 14, overflowX: 'auto' }}>
                    <table style={{ width: '100%', minWidth: 700, borderCollapse: 'collapse', fontSize: 12 }}>
                      <thead>
                        <tr style={{ borderBottom: '1px solid var(--hairline)', background: 'var(--surface-2)' }}>
                          {['Order','Type','Pickup','Dropoff','Distance','Amount'].map(h => (
                            <th key={h} style={{ padding: '7px 14px', textAlign: h === 'Distance' || h === 'Amount' ? 'right' : 'left', fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', fontWeight: 500, letterSpacing: '0.05em', textTransform: 'uppercase' }}>{h}</th>
                          ))}
                        </tr>
                      </thead>
                      <tbody>
                        {pendingDeliveries.map(d => (
                          <tr key={d.id} style={{ borderBottom: '1px solid var(--hairline)' }}>
                            <td style={{ padding: '8px 14px' }}><span className="id" style={{ color: 'var(--ink)', fontSize: 11.5 }}>{d.order?.order_number || d.tracking_number}</span></td>
                            <td style={{ padding: '8px 14px' }}>
                              <span className={`chip${d.delivery_tier === 'economy' ? '' : ' accent'}`} style={{ fontSize: 10.5 }}>
                                {d.delivery_tier === 'standard' ? 'Same Day' : d.delivery_tier === 'economy' ? 'Next Day' : 'Flash'}
                              </span>
                            </td>
                            <td style={{ padding: '8px 14px', color: 'var(--ink-2)', whiteSpace: 'nowrap' }}>
                              {d.pickup_address ? (
                                <>
                                  {[d.pickup_address.name, d.pickup_address.sublocality || d.pickup_address.city || d.pickup_address.municipality].filter(Boolean).join(', ')}
                                  {d.order?.stores?.name && <span className="muted" style={{ marginLeft: 5 }}>({d.order.stores.name})</span>}
                                </>
                              ) : '—'}
                            </td>
                            <td style={{ padding: '8px 14px', color: 'var(--ink-2)', whiteSpace: 'nowrap' }}>
                              {d.delivery_address ? (
                                <>
                                  {[d.delivery_address.name, d.delivery_address.sublocality || d.delivery_address.city || d.delivery_address.municipality].filter(Boolean).join(', ')}
                                  {d.order?.buyer?.username && <span className="muted" style={{ marginLeft: 5 }}>(@{d.order.buyer.username})</span>}
                                </>
                              ) : '—'}
                            </td>
                            <td style={{ padding: '8px 14px', textAlign: 'right', fontFamily: 'var(--font-mono)', fontSize: 11.5, color: 'var(--ink-3)' }}>
                              {d.distance_km != null ? `${d.distance_km} km` : '—'}
                            </td>
                            <td style={{ padding: '8px 14px', textAlign: 'right', fontFamily: 'var(--font-mono)', fontSize: 11.5, fontWeight: 600, color: 'var(--ink)' }}>
                              {d.order?.total_amount != null ? currency(d.order.total_amount) : '—'}
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}

                {pendingCount > 0 && (
                  <div className="panel" style={{ padding: 14, marginBottom: 14 }}>
                    <PendingMap pending={pendingDeliveries} />
                  </div>
                )}

                {/* ── Automated dispatch (simulate cron) ── */}
                {pendingCount > 0 && (() => {
                  const handleRunCron = async () => {
                    setCronBusy(true); setCronResult(null); setCronError('');
                    try {
                      const res = await fetch(
                        'https://qluphzlbbzvwxzrsjwnv.supabase.co/functions/v1/dispatch-cron',
                        {
                          method: 'POST',
                          headers: { 'Content-Type': 'application/json' },
                          body: JSON.stringify({ tier: cronTier }),
                        }
                      );
                      const data = await res.json();
                      if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
                      setCronResult(data);
                      await doRefreshDispatch();
                      await doRefreshPlanned();
                      setTab('planned');
                    } catch (e) {
                      setCronError(e.message);
                    }
                    setCronBusy(false);
                  };

                  return (
                    <div className="panel" style={{ padding: 16, marginBottom: 14 }}>
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
                        <div>
                          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 3 }}>Automated dispatch</div>
                          <div style={{ fontSize: 12, color: 'var(--ink-2)' }}>
                            Simulate the scheduled cron — clusters pending deliveries into planned routes via ORS
                          </div>
                        </div>
                        <span className="chip dot accent" style={{ fontSize: 10, flexShrink: 0, marginLeft: 12 }}>Auto</span>
                      </div>
                      <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                        <div style={{ display: 'flex', background: 'var(--surface-2)', border: '1px solid var(--hairline)', borderRadius: 5, overflow: 'hidden', flexShrink: 0 }}>
                          {['standard', 'economy'].map(t => (
                            <button key={t} onClick={() => setCronTier(t)} style={{
                              padding: '5px 14px', border: 'none', cursor: 'pointer', fontSize: 11.5, fontWeight: 550,
                              background: cronTier === t ? 'var(--accent)' : 'transparent',
                              color: cronTier === t ? '#fff' : 'var(--ink-3)',
                              transition: 'all 0.15s',
                            }}>
                              {t === 'standard' ? 'Same Day' : 'Economy'}
                            </button>
                          ))}
                        </div>
                        <button
                          className="btn primary"
                          style={{ height: 34, fontSize: 12.5 }}
                          disabled={cronBusy}
                          onClick={handleRunCron}
                        >
                          {cronBusy ? '⏳ Planning routes…' : '▶ Run dispatch now'}
                        </button>
                        {cronResult && (
                          <span style={{ fontSize: 11.5, color: 'var(--accent)', fontFamily: 'var(--font-mono)' }}>
                            ✓ {cronResult.routes_created ?? 0} route{cronResult.routes_created !== 1 ? 's' : ''} planned → check Planned tab
                          </span>
                        )}
                        {cronError && (
                          <span style={{ fontSize: 11.5, color: 'var(--neg)' }}>⚠ {cronError}</span>
                        )}
                      </div>
                    </div>
                  );
                })()}

                <div className="panel" style={{ padding: 16 }}>
                  <AssembleForm pendingCount={pendingCount} onAssembled={doRefreshDispatch} />
                </div>

                {pendingCount === 0 && !loading && (
                  <div className="panel" style={{ padding: 32, textAlign: 'center' }}>
                    <div className="muted" style={{ fontSize: 13 }}>No pending deliveries in queue.</div>
                  </div>
                )}
              </div>
            )}

            {/* ── STEP 2 & 3: Optimize + Dispatch (3-col layout) ── */}
            {step > 0 && stagingRoute && (
              <div className="mob-stack" style={{ display: 'grid', gridTemplateColumns: '300px 1fr 320px', gap: 14, height: 'calc(100vh - 320px)', minHeight: 480 }}>

                {/* LEFT: stop sequence */}
                <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
                  <div className="panel-h">
                    <span>Stop sequence</span>
                    <span className="muted" style={{ fontSize: 11, marginLeft: 'auto' }}>{sStops.length} stops</span>
                  </div>
                  <div style={{ flex: 1, overflow: 'auto', padding: '0 14px 14px' }}>
                    {sStops.length === 0 ? (
                      <div className="muted" style={{ padding: '16px 0', fontSize: 12 }}>No stops yet.</div>
                    ) : sStops.map((s, idx) => {
                      const delivery = s.delivery_id ? sDelivMap[s.delivery_id] : null;
                      const addr = s.address ? fmtAddrShort(s.address) : '—';
                      const isPickup = s.stop_type === 'pickup';
                      return (
                        <div key={s.id} style={{ display: 'grid', gridTemplateColumns: '20px 1fr', gap: 8, padding: '9px 0', borderBottom: idx < sStops.length - 1 ? '1px solid var(--hairline)' : 'none' }}>
                          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                            <div style={{
                              width: 18, height: 18, borderRadius: '50%', display: 'grid', placeItems: 'center', flexShrink: 0,
                              background: isPickup ? '#fef3c7' : '#dcfce7',
                              border: isPickup ? '1.5px solid #f59e0b' : '1.5px solid #16a34a',
                              color: isPickup ? '#92400e' : '#166534',
                              fontFamily: 'var(--font-mono)', fontSize: 9, fontWeight: 700,
                            }}>{idx + 1}</div>
                            {idx < sStops.length - 1 && <div style={{ flex: 1, width: 1, background: 'var(--hairline)', marginTop: 3 }} />}
                          </div>
                          <div style={{ paddingBottom: 2 }}>
                            <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                              <span style={{ fontSize: 11, color: isPickup ? '#b45309' : '#15803d' }}>{isPickup ? '📦' : '🏠'}</span>
                              <span style={{ fontSize: 12, color: 'var(--ink)', fontWeight: 500 }}>{addr}</span>
                            </div>
                            {delivery && <div className="id" style={{ fontSize: 10, marginTop: 2, color: 'var(--ink-3)' }}>{delivery.order?.order_number || delivery.tracking_number}</div>}
                          </div>
                        </div>
                      );
                    })}
                  </div>
                </div>

                {/* CENTER: map */}
                <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
                  <div className="panel-h" style={{ padding: '3px 14px 0', height: 40 }}>
                    <span>{stagingRoute.id.slice(0, 8).toUpperCase()}</span>
                    <span className={`chip dot ${ROUTE_STATUS_META[stagingRoute.status]?.chip || 'warn'}`}>{ROUTE_STATUS_META[stagingRoute.status]?.label || stagingRoute.status}</span>
                    <div className="right">
                      <button className="btn ghost" style={{ height: 24 }} onClick={doRefreshDispatch}><I.refresh size={11} /></button>
                    </div>
                  </div>
                  <RouteMap route={stagingRoute} locationHistory={[]} />
                </div>

                {/* RIGHT: actions */}
                <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
                  <div className="panel-h"><span>Route actions</span></div>

                  {/* Stats */}
                  <div style={{ padding: '12px 14px', borderBottom: '1px solid var(--hairline)', display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 10 }}>
                    <RouteStat label="Stops" value={`${sStops.length}`} />
                    <RouteStat label="Distance" value={fmtDist(stagingRoute.total_distance_m)} />
                    <RouteStat label="GMV" value={currency(sGmv)} />
                    <RouteStat label="Window" value={stagingRoute.dispatch_window || '—'} />
                  </div>

                  <div style={{ flex: 1, overflow: 'auto', padding: 14, display: 'flex', flexDirection: 'column', gap: 16 }}>

                    {/* Optimize step */}
                    <div style={{
                      borderRadius: 8, border: `1.5px solid ${step >= 1 ? 'var(--accent)' : 'var(--hairline)'}`,
                      padding: 14, background: step === 1 ? 'var(--surface-2)' : 'var(--surface)',
                      opacity: step < 1 ? 0.5 : 1,
                    }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
                        <div style={{
                          width: 22, height: 22, borderRadius: '50%', display: 'grid', placeItems: 'center',
                          background: step > 1 ? 'var(--accent)' : 'var(--surface-3)',
                          color: step > 1 ? '#fff' : 'var(--ink-3)', fontSize: 11, fontWeight: 700,
                        }}>{step > 1 ? '✓' : '2'}</div>
                        <span style={{ fontWeight: 600, fontSize: 13, color: 'var(--ink)' }}>Optimize route</span>
                      </div>
                      <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginBottom: 10 }}>
                        Reorder {sStops.length} stops via ORS for shortest road distance.
                        {stagingRoute.total_distance_m ? <span style={{ color: 'var(--accent)', marginLeft: 4 }}>{fmtDist(stagingRoute.total_distance_m)} calculated</span> : null}
                      </div>
                      <button
                        className={`btn${step === 1 ? ' primary' : ''} grow`}
                        style={{ width: '100%' }}
                        disabled={optimizing || dispatching}
                        onClick={handleOptimize}
                      >
                        <I.refresh size={11} />{optimizing ? 'Optimizing…' : step > 1 ? 'Re-optimize' : 'Optimize stops'}
                      </button>
                      {actionError && step === 1 && <div style={{ marginTop: 6, fontSize: 11, color: 'var(--neg)' }}>{actionError}</div>}
                    </div>

                    {/* Dispatch step */}
                    <div style={{
                      borderRadius: 8, border: `1.5px solid ${step >= 2 ? 'var(--accent)' : 'var(--hairline)'}`,
                      padding: 14, background: step === 2 ? 'var(--surface-2)' : 'var(--surface)',
                      opacity: step < 2 ? 0.45 : 1,
                    }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
                        <div style={{
                          width: 22, height: 22, borderRadius: '50%', display: 'grid', placeItems: 'center',
                          background: 'var(--surface-3)', color: 'var(--ink-3)', fontSize: 11, fontWeight: 700,
                        }}>3</div>
                        <span style={{ fontWeight: 600, fontSize: 13, color: step >= 2 ? 'var(--ink)' : 'var(--ink-3)' }}>Assign &amp; dispatch</span>
                      </div>
                      <div style={{ fontSize: 11.5, color: 'var(--ink-3)', marginBottom: 10 }}>
                        Auto-selects the nearest online driver by GPS. Override by choosing a driver below.
                      </div>
                      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                        <select
                          value={dispatchDriver} onChange={e => setDispatchDriver(e.target.value)}
                          disabled={step < 2 || dispatching}
                          style={{ width: '100%', height: 32, fontSize: 12, background: 'var(--surface-2)', border: '1px solid var(--hairline)', borderRadius: 5, color: 'var(--ink)', padding: '0 8px' }}
                        >
                          <option value="">Auto-assign best driver</option>
                          {drivers.map(d => <option key={d.id} value={d.id}>{d.display_name}{d.vehicle_type ? ` · ${d.vehicle_type}` : ''}</option>)}
                        </select>
                        <button
                          className="btn primary grow"
                          style={{ width: '100%' }}
                          disabled={step < 2 || dispatching || optimizing}
                          onClick={handleOptimizeAndDispatch}
                        >
                          <I.truck size={11} />{dispatching ? 'Optimizing & dispatching…' : 'Optimize & dispatch'}
                        </button>
                      </div>
                      {actionError && step === 2 && <div style={{ marginTop: 6, fontSize: 11, color: 'var(--neg)' }}>{actionError}</div>}
                    </div>

                    {/* Delete route — returns stops to pending queue */}
                    <div style={{ borderTop: '1px solid var(--hairline)', paddingTop: 14, marginTop: 4 }}>
                      <button
                        className="btn"
                        style={{ width: '100%', color: 'var(--neg)', borderColor: 'var(--neg, #ef4444)', fontSize: 12 }}
                        disabled={dispatching || optimizing}
                        onClick={() => {
                          if (confirm('Delete this route? All stops will return to the pending queue.')) {
                            handleDeleteRoute(stagingRoute?.id);
                          }
                        }}
                      >
                        Delete route &amp; return to queue
                      </button>
                    </div>

                  </div>
                </div>

              </div>
            )}
          </div>
        );
      })()}

      {/* ── DISPATCH: Active tab (dispatched routes only) ── */}
      {deliveryType === 'dispatch' && tab === 'active' && (() => {
        const activeRoutes = routes.filter(r => r.status === 'dispatched');
        const activeRoute = activeRoutes.find(r => r.id === selectedId) || activeRoutes[0] || null;
        const aDriverName = activeRoute?.driver?.display_name || '—';
        const aProg = activeRoute?.progress || null;
        const aDoneStops = aProg?.completed_stops ?? 0;
        const aTotalStops = activeRoute?.total_stops || 0;
        const aGmv = (activeRoute?.deliveries || []).reduce((s, d) => s + Number(d.order?.total_amount || 0), 0);
        const aStops = activeRoute?.stops || [];
        const aFirstPendingIdx = aStops.findIndex(s => s.status === 'pending');
        const aDelivMap = Object.fromEntries((activeRoute?.deliveries || []).map(d => [d.id, d]));

        return (
          <div className="mob-stack" style={{ display: 'grid', gridTemplateColumns: '300px 1fr 340px', gap: 14, height: 'calc(100vh - 260px)', minHeight: 520 }}>
            {/* LEFT */}
            <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              <div className="panel-h">
                <span>Active routes</span>
                <div className="right"><I.refresh size={13} className="muted" style={{ cursor: 'pointer' }} onClick={doRefreshDispatch} /></div>
              </div>
              <div style={{ flex: 1, overflow: 'auto' }}>
                {loading && activeRoutes.length === 0 ? (
                  <div className="muted" style={{ padding: 16, fontSize: 12 }}>Loading…</div>
                ) : activeRoutes.length === 0 ? (
                  <div className="muted" style={{ padding: 16, fontSize: 12 }}>No dispatched routes yet.</div>
                ) : activeRoutes.map(r => {
                  const sel = r.id === selectedId;
                  const rDone = r.progress?.completed_stops ?? 0;
                  const rTotal = r.total_stops || 0;
                  return (
                    <div key={r.id} onClick={() => setSelectedId(r.id)} style={{
                      padding: '12px 14px', borderBottom: '1px solid var(--hairline)',
                      background: sel ? 'var(--surface-2)' : 'transparent',
                      cursor: 'pointer', position: 'relative',
                    }}>
                      {sel && <div style={{ position: 'absolute', left: 0, top: 8, bottom: 8, width: 2, background: 'var(--accent)' }} />}
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                        <span className="id" style={{ color: 'var(--ink)' }}>{r.id.slice(0, 8).toUpperCase()}</span>
                        <span className="chip dot pos">Dispatched</span>
                        <span className="muted num" style={{ marginLeft: 'auto', fontSize: 10.5 }}>{r.dispatch_window}</span>
                      </div>
                      <div style={{ marginTop: 6, fontSize: 12.5, color: 'var(--ink)', fontWeight: 500 }}>{r.driver?.display_name || '—'}</div>
                      <div className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)', marginTop: 1 }}>
                        {rDone}/{rTotal} stops · {fmtDist(r.total_distance_m)}
                      </div>
                      <div style={{ marginTop: 8, height: 3, background: 'var(--surface-3)', borderRadius: 2, overflow: 'hidden' }}>
                        <div style={{ width: `${rTotal > 0 ? (rDone / rTotal) * 100 : 0}%`, height: '100%', background: 'var(--accent)' }} />
                      </div>
                    </div>
                  );
                })}
              </div>
              <div style={{ padding: '10px 14px', borderTop: '1px solid var(--hairline)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)' }}>Pending queue</span>
                <span className={`chip dot${pendingCount > 0 ? ' warn' : ''}`}>{pendingCount} unassigned</span>
              </div>
            </div>

            {/* CENTER */}
            <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              {!activeRoute ? (
                <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <span className="muted" style={{ fontSize: 12 }}>No active routes</span>
                </div>
              ) : (
                <>
                  <div className="panel-h" style={{ padding: '3px 14px 0', height: 40 }}>
                    <span>{activeRoute.id.slice(0, 8).toUpperCase()} · {aDriverName}</span>
                    <div className="right">
                      <button className="btn ghost" style={{ height: 24 }} onClick={doRefreshDispatch}><I.refresh size={11} />Refresh</button>
                    </div>
                  </div>
                  <RouteMap route={activeRoute} locationHistory={[]} />
                </>
              )}
            </div>

            {/* RIGHT */}
            <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              {!activeRoute ? (
                <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <span className="muted" style={{ fontSize: 12 }}>Select a route</span>
                </div>
              ) : (
                <>
                  <div className="panel-h"><span>Route detail</span></div>
                  <div style={{ padding: 14, borderBottom: '1px solid var(--hairline)' }}>
                    <div className="row gap-3" style={{ marginBottom: 14 }}>
                      <div className="avatar" style={{ width: 36, height: 36, fontSize: 12 }}>{initials(aDriverName)}</div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontWeight: 550, color: 'var(--ink)', fontSize: 13.5 }}>{aDriverName}</div>
                        <div className="id">{activeRoute.vehicle_type || '—'} · {activeRoute.driver?.phone || '—'}</div>
                      </div>
                      <Donut value={aTotalStops > 0 ? aDoneStops / aTotalStops : 0} size={42} stroke={5} />
                    </div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 10 }}>
                      <RouteStat label="Progress" value={`${aDoneStops}/${aTotalStops} stops`} />
                      <RouteStat label="Distance" value={fmtDist(activeRoute.total_distance_m)} />
                      <RouteStat label="GMV" value={currency(aGmv)} />
                      <RouteStat label="Dispatched" value={activeRoute.dispatched_at ? fmtTime(activeRoute.dispatched_at) : '—'} />
                    </div>
                  </div>
                  <div style={{ flex: 1, overflow: 'auto' }}>
                    <div style={{ padding: '10px 14px 6px' }}>
                      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase' }}>Stop sequence</div>
                    </div>
                    <div style={{ padding: '0 14px 14px' }}>
                      {aStops.map((s, idx) => {
                        const isDone = s.status === 'completed' || s.status === 'skipped';
                        const isSkipped = s.status === 'skipped';
                        const isCur = idx === aFirstPendingIdx;
                        const addr = s.address ? fmtAddrShort(s.address) : '—';
                        const delivery = s.delivery_id ? aDelivMap[s.delivery_id] : null;
                        const arrived = s.actual_arrival || s.completed_at;
                        const eta = s.estimated_arrival;
                        const deltaMin = (arrived && eta) ? Math.round((new Date(arrived) - new Date(eta)) / 60000) : null;
                        const deltaColor = deltaMin === null ? null : Math.abs(deltaMin) <= 5 ? '#16a34a' : deltaMin <= 15 ? '#d97706' : '#dc2626';
                        return (
                          <div key={s.id} style={{ display: 'grid', gridTemplateColumns: '24px 1fr auto', gap: 8, padding: '10px 0', borderBottom: idx < aStops.length - 1 ? '1px solid var(--hairline)' : 'none' }}>
                            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                              <div style={{
                                width: 18, height: 18, borderRadius: '50%', display: 'grid', placeItems: 'center', flexShrink: 0,
                                background: isDone ? 'var(--surface-2)' : isCur ? 'var(--accent)' : 'var(--surface)',
                                border: isDone ? '1px solid var(--hairline-2)' : isCur ? 'none' : '1px solid var(--hairline-2)',
                                color: isDone ? 'var(--ink-3)' : isCur ? 'var(--paper)' : 'var(--ink-2)',
                                fontFamily: 'var(--font-mono)', fontSize: 9.5, fontWeight: 600,
                              }}>
                                {isDone ? <I.check size={10} /> : idx + 1}
                              </div>
                              {idx < aStops.length - 1 && <div style={{ flex: 1, width: 1, background: 'var(--hairline)', marginTop: 3 }} />}
                            </div>
                            <div style={{ minWidth: 0, paddingBottom: 2 }}>
                              <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 3 }}>
                                <span style={{ fontSize: 12.5, color: isDone ? 'var(--ink-3)' : 'var(--ink)', textDecoration: isSkipped ? 'line-through' : 'none', fontWeight: isCur ? 550 : 400 }}>{addr}</span>
                                {delivery && <span className="id" style={{ fontSize: 10, color: 'var(--ink-3)' }}>{delivery.order?.order_number || delivery.tracking_number}</span>}
                              </div>
                              <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                                <span className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)' }}>{s.stop_type === 'pickup' ? '📦' : '🏠'} {s.stop_type}</span>
                                {eta && <span className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)' }}>ETA {fmtTime(eta)}</span>}
                                {arrived && <span style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', color: 'var(--ink-2)' }}>↓ {fmtTime(arrived)}</span>}
                                {deltaMin !== null && <span style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', color: deltaColor }}>{deltaMin === 0 ? 'on time' : (deltaMin > 0 ? '+' : '') + deltaMin + 'm'}</span>}
                              </div>
                              {isCur && <div style={{ marginTop: 3, fontSize: 10.5, color: 'var(--accent-ink)', fontFamily: 'var(--font-mono)' }}>en route</div>}
                            </div>
                            <div style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'flex-end', paddingTop: 2 }}>
                              {isCur && <span className="chip accent dot">now</span>}
                              {isSkipped && <span className="chip warn dot">skip</span>}
                              {isDone && !isSkipped && <span className="chip pos dot">done</span>}
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  </div>
                  <div style={{ padding: '10px 14px', borderTop: '1px solid var(--hairline)' }}>
                    {pendingCount > 0 && (
                      <button className="btn grow" style={{ width: '100%' }} disabled={addingMore} onClick={handleAddMore}>
                        <I.plus size={11} />{addingMore ? 'Adding…' : `Add ${pendingCount} pending`}
                      </button>
                    )}
                    {(addError || actionError) && <div style={{ marginTop: 6, fontSize: 11.5, color: 'var(--neg)' }}>{addError || actionError}</div>}
                  </div>
                </>
              )}
            </div>
          </div>
        );
      })()}

      {/* ── DISPATCH: Planned tab ── */}
      {deliveryType === 'dispatch' && tab === 'planned' && (() => {
        if (!plannedFetched) {
          return (
            <div className="panel" style={{ padding: 32, textAlign: 'center', maxWidth: 400 }}>
              <button className="btn primary" onClick={doRefreshPlanned}><I.refresh size={12} />Load planned routes</button>
            </div>
          );
        }
        if (loadingPlanned) return <div className="muted" style={{ padding: 24, fontSize: 12 }}>Loading…</div>;
        if (plannedRoutes.length === 0) {
          return (
            <div className="panel" style={{ padding: 32, textAlign: 'center', maxWidth: 500 }}>
              <div style={{ fontSize: 14, color: 'var(--ink)', marginBottom: 8 }}>No planned routes</div>
              <div className="muted" style={{ fontSize: 12 }}>Routes appear here after the cron fires. You can also trigger manually via the edge function.</div>
              <button className="btn" style={{ marginTop: 14 }} onClick={doRefreshPlanned}><I.refresh size={11} />Refresh</button>
            </div>
          );
        }

        // Group planned routes by tier + cut_time
        const groups = [];
        const seen = new Set();
        plannedRoutes.forEach(r => {
          const key = `${r.tier || 'standard'}::${r.cut_time || r.created_at?.slice(0, 13)}`;
          if (!seen.has(key)) {
            seen.add(key);
            groups.push({ key, tier: r.tier || 'standard', cut_time: r.cut_time, routes: [] });
          }
          groups.find(g => g.key === key).routes.push(r);
        });

        // Dispatch all routes in a group using ORS auction
        const handleDispatchGroup = async (groupRoutes) => {
          setPlannedError('');
          const locatedDrivers = await getLocatedDrivers();
          if (!locatedDrivers.length) {
            // No drivers with GPS — offer manual assignment for first route in group
            const allDrivers = await getAllOnlineDrivers();
            if (!allDrivers.length) {
              setPlannedError('No online drivers found. Ask a driver to go online before dispatching.');
              return;
            }
            setManualDispatch({ routeIds: groupRoutes.map(r => r.id), drivers: allDrivers });
            setManualDriverId('');
            return;
          }
          for (const r of groupRoutes) {
            const geocodedStops = (r.stops || []).filter(s => s.latitude && s.longitude).sort((a, b) => (a.sequence || 0) - (b.sequence || 0));
            if (geocodedStops.length < 2) continue;
            setDispatchingPlanned(prev => ({ ...prev, [r.id]: true }));
            try {
              const results = await Promise.all(
                locatedDrivers.map(async driver => {
                  try {
                    const result = await runOrsOptimize(geocodedStops, driver.lng, driver.lat);
                    return { driver, result };
                  } catch { return null; }
                })
              );
              const valid = results.filter(Boolean).sort((a, b) => a.result.totalDist - b.result.totalDist);
              if (!valid.length) throw new Error('ORS failed for all drivers');
              const { driver: bestDriver, result: bestResult } = valid[0];
              console.log(
                `[dispatch] route ${r.id.slice(0,8)} → driver "${bestDriver.name}" (${bestDriver.vehicle}) ` +
                `${(bestResult.totalDist/1000).toFixed(1)} km. Others:`,
                valid.slice(1).map(v => `${v.driver.name} ${(v.result.totalDist/1000).toFixed(1)}km`).join(', ') || 'none'
              );
              setPlannedError(`Assigning to ${bestDriver.name} (${(bestResult.totalDist/1000).toFixed(1)} km)…`);
              const stopSeqs = bestResult.orderedStops.map((s, i) => ({ stop_id: s.id, sequence: i + 1 }));
              const { error: seqErr } = await sb.rpc('apply_osrm_sequence', {
                p_route_id: r.id, p_stop_sequences: stopSeqs,
                p_polyline: bestResult.polyline, p_total_distance: bestResult.totalDist, p_total_duration: bestResult.totalDur,
              });
              if (seqErr) throw new Error(seqErr.message);
              const { data: dispRes, error: dispErr } = await sb.rpc('dispatch_route', { p_route_id: r.id, p_driver_id: bestDriver.id });
              if (dispErr || !dispRes?.success) throw new Error(dispRes?.message || dispErr?.message || 'Dispatch failed');
            } catch (e) {
              setPlannedError(`Route ${r.id.slice(0, 8).toUpperCase()}: ${e.message}`);
              setDispatchingPlanned(prev => ({ ...prev, [r.id]: false }));
              return;
            }
            setDispatchingPlanned(prev => ({ ...prev, [r.id]: false }));
          }
          setPlannedError('');
          await doRefreshPlanned();
          await doRefreshDispatch();
          setTab('active');
        };

        // Manual dispatch handler (no GPS drivers available)
        const handleManualDispatch = async () => {
          if (!manualDriverId || !manualDispatch) return;
          setManualDispatching(true);
          setPlannedError('');
          try {
            for (const routeId of manualDispatch.routeIds) {
              const { data: dispRes, error: dispErr } = await sb.rpc('dispatch_route', { p_route_id: routeId, p_driver_id: manualDriverId });
              if (dispErr || !dispRes?.success) throw new Error(dispRes?.message || dispErr?.message || 'Dispatch failed');
            }
            setManualDispatch(null);
            await doRefreshPlanned();
            await doRefreshDispatch();
            setTab('active');
          } catch (e) {
            setPlannedError(`Manual dispatch failed: ${e.message}`);
          }
          setManualDispatching(false);
        };

        // Re-optimize a single planned route without dispatching
        const handleReoptimizePlanned = async (r) => {
          const geocodedStops = (r.stops || []).filter(s => s.latitude && s.longitude).sort((a, b) => (a.sequence || 0) - (b.sequence || 0));
          if (geocodedStops.length < 2) { setPlannedError('Not enough geocoded stops'); return; }
          setDispatchingPlanned(prev => ({ ...prev, [r.id]: true }));
          try {
            const { orderedStops, polyline, totalDist, totalDur } = await runOrsOptimize(geocodedStops, 85.324, 27.7172);
            const stopSeqs = orderedStops.map((s, i) => ({ stop_id: s.id, sequence: i + 1 }));
            const { error } = await sb.rpc('apply_osrm_sequence', {
              p_route_id: r.id, p_stop_sequences: stopSeqs,
              p_polyline: polyline, p_total_distance: totalDist, p_total_duration: totalDur,
            });
            if (error) throw new Error(error.message);
          } catch (e) {
            setPlannedError(`Re-optimize failed: ${e.message}`);
          }
          setDispatchingPlanned(prev => ({ ...prev, [r.id]: false }));
          await doRefreshPlanned();
          setPlannedSelId(r.id);
        };

        const anyDispatching = Object.values(dispatchingPlanned).some(Boolean);

        return (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <div className="muted" style={{ fontSize: 12 }}>
                {plannedRoutes.length} planned route{plannedRoutes.length !== 1 ? 's' : ''} — review and dispatch when ready
              </div>
              <button className="btn ghost" style={{ height: 28 }} onClick={doRefreshPlanned}><I.refresh size={11} />Refresh</button>
            </div>

            {plannedError && (
              <div style={{
                padding: '8px 12px', borderRadius: 6, fontSize: 12,
                background: plannedError.startsWith('Assigning') ? 'var(--accent-bg, #eff6ff)' : 'var(--neg-bg, #fef2f2)',
                border: `1px solid ${plannedError.startsWith('Assigning') ? 'var(--accent)' : 'var(--neg)'}`,
                color: plannedError.startsWith('Assigning') ? 'var(--accent)' : 'var(--neg)',
              }}>
                {plannedError}
              </div>
            )}

            {/* Manual driver assignment panel */}
            {manualDispatch && (
              <div className="panel" style={{ padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 10 }}>
                <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink)' }}>Manual driver assignment</div>
                <div className="muted" style={{ fontSize: 11.5 }}>
                  No online drivers with GPS found. Pick a driver to assign manually — the current stop sequence will be used as-is.
                </div>
                <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                  <select
                    value={manualDriverId}
                    onChange={e => setManualDriverId(e.target.value)}
                    style={{ flex: 1, minWidth: 180, height: 32, fontSize: 12, border: '1px solid var(--hairline)', borderRadius: 6, padding: '0 8px', background: 'var(--surface)' }}
                  >
                    <option value="">Select driver…</option>
                    {manualDispatch.drivers.map(d => (
                      <option key={d.id} value={d.id}>
                        {d.name} · {d.vehicle}{d.lat ? '' : ' (no GPS)'}
                      </option>
                    ))}
                  </select>
                  <button
                    className="btn primary"
                    style={{ height: 32, fontSize: 12 }}
                    disabled={!manualDriverId || manualDispatching}
                    onClick={handleManualDispatch}
                  >
                    {manualDispatching ? 'Dispatching…' : 'Dispatch'}
                  </button>
                  <button
                    className="btn ghost"
                    style={{ height: 32, fontSize: 12 }}
                    onClick={() => { setManualDispatch(null); setManualDriverId(''); }}
                  >
                    Cancel
                  </button>
                </div>
              </div>
            )}

            {/* Group cards */}
            {groups.map(g => {
              const totalStops = g.routes.reduce((s, r) => s + (r.total_stops || r.stops?.length || 0), 0);
              const totalDistKm = g.routes.reduce((s, r) => s + (r.total_distance_m || 0), 0) / 1000;
              const totalGmv = g.routes.reduce((s, r) => s + (r.deliveries || []).reduce((a, d) => a + Number(d.order?.total_amount || 0), 0), 0);
              const tierLabel = g.tier === 'economy' ? 'Economy' : 'Standard';
              const cutLabel = g.cut_time ? new Date(g.cut_time).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: true, timeZone: 'Asia/Kathmandu' }) : '—';
              const groupBusy = g.routes.some(r => dispatchingPlanned[r.id]);

              return (
                <div key={g.key} className="panel" style={{ overflow: 'hidden' }}>
                  {/* Group header */}
                  <div style={{
                    padding: '12px 16px', borderBottom: '1px solid var(--hairline)',
                    background: 'var(--surface-2)',
                    display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap',
                  }}>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                        <span style={{ fontWeight: 650, fontSize: 13.5, color: 'var(--ink)' }}>
                          {tierLabel} run · {cutLabel} cut
                        </span>
                        <span className={`chip dot ${g.tier === 'economy' ? '' : 'accent'}`} style={{ fontSize: 10 }}>{tierLabel}</span>
                      </div>
                      <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap' }}>
                        <span className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)' }}>{g.routes.length} route{g.routes.length !== 1 ? 's' : ''}</span>
                        <span className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)' }}>{totalStops} stops</span>
                        <span className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)' }}>{totalDistKm.toFixed(1)} km combined</span>
                        <span className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)' }}>{currency(totalGmv)} GMV</span>
                      </div>
                    </div>
                    <button
                      className="btn primary"
                      style={{ height: 34, fontSize: 12 }}
                      disabled={anyDispatching}
                      onClick={() => handleDispatchGroup(g.routes)}
                    >
                      <I.truck size={11} />
                      {groupBusy ? 'Dispatching…' : `Dispatch all ${g.routes.length}`}
                    </button>
                  </div>

                  {/* Individual routes */}
                  <div style={{ display: 'flex', flexDirection: 'column' }}>
                    {g.routes.map((r, ri) => {
                      const rStops = r.stops || [];
                      const rGmv = (r.deliveries || []).reduce((s, d) => s + Number(d.order?.total_amount || 0), 0);
                      const isSel = r.id === plannedSelId;
                      const rBusy = !!dispatchingPlanned[r.id];

                      return (
                        <div key={r.id} style={{ borderBottom: ri < g.routes.length - 1 ? '1px solid var(--hairline)' : 'none' }}>
                          {/* Route row */}
                          <div
                            onClick={() => setPlannedSelId(isSel ? null : r.id)}
                            style={{
                              padding: '10px 16px', cursor: 'pointer',
                              background: isSel ? 'var(--surface-2)' : 'transparent',
                              display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap',
                              position: 'relative',
                            }}
                          >
                            {isSel && <div style={{ position: 'absolute', left: 0, top: 6, bottom: 6, width: 2, background: 'var(--accent)' }} />}
                            <div style={{ flex: 1, minWidth: 0 }}>
                              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3 }}>
                                <span className="id" style={{ color: 'var(--ink)', fontSize: 11.5 }}>{r.id.slice(0, 8).toUpperCase()}</span>
                                <span className="chip dot accent" style={{ fontSize: 10 }}>Planned</span>
                              </div>
                              <div style={{ fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--ink-2)' }}>
                                {rStops.length} stops · {fmtDist(r.total_distance_m)} · {currency(rGmv)}
                              </div>
                            </div>
                            <div style={{ display: 'flex', gap: 6, flexShrink: 0 }}>
                              <button
                                className="btn ghost"
                                style={{ height: 28, fontSize: 11 }}
                                disabled={rBusy || anyDispatching}
                                onClick={e => { e.stopPropagation(); handleReoptimizePlanned(r); }}
                              >
                                <I.refresh size={10} />{rBusy ? '…' : 'Re-optimize'}
                              </button>
                              <button
                                className="btn ghost"
                                style={{ height: 28, fontSize: 11 }}
                                onClick={e => {
                                  e.stopPropagation();
                                  const sortedStops = (r.stops || []).slice().sort((a, b) => (a.sequence ?? 0) - (b.sequence ?? 0));
                                  const payload = {
                                    route: { id: r.id, tier: r.tier, cut_time: r.cut_time, total_distance_m: r.total_distance_m, status: r.status },
                                    stops: sortedStops.map(s => ({
                                      id: s.id, sequence: s.sequence, stop_type: s.stop_type,
                                      lat: s.latitude, lng: s.longitude, address: s.address,
                                      delivery_id: s.delivery_id,
                                    })),
                                    deliveries: r.deliveries || [],
                                  };
                                  navigator.clipboard.writeText(JSON.stringify(payload, null, 2)).then(() => {
                                    setCopiedRouteId(r.id);
                                    setTimeout(() => setCopiedRouteId(id => id === r.id ? null : id), 1800);
                                  });
                                }}
                              >
                                {copiedRouteId === r.id ? '✓ Copied' : 'Copy raw'}
                              </button>
                              <button
                                className="btn"
                                style={{ height: 28, fontSize: 11 }}
                                disabled={anyDispatching}
                                onClick={e => { e.stopPropagation(); handleDispatchGroup([r]); }}
                              >
                                <I.truck size={10} />{rBusy ? 'Dispatching…' : 'Dispatch'}
                              </button>
                            </div>
                          </div>

                          {/* Expanded: map + stops */}
                          {isSel && (
                            <div className="mob-stack" style={{ display: 'grid', gridTemplateColumns: '1fr 280px', borderTop: '1px solid var(--hairline)', height: 320 }}>
                              <RouteMap route={r} locationHistory={[]} />
                              <div style={{ borderLeft: '1px solid var(--hairline)', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
                                <div style={{ padding: '8px 12px', borderBottom: '1px solid var(--hairline)', fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>
                                  Stop sequence · {rStops.length}
                                </div>
                                <div style={{ flex: 1, overflow: 'auto', padding: '0 12px 12px' }}>
                                  {rStops.map((s, idx) => {
                                    const isPickup = s.stop_type === 'pickup';
                                    const addr = s.address ? fmtAddrShort(s.address) : '—';
                                    return (
                                      <div key={s.id} style={{ display: 'grid', gridTemplateColumns: '18px 1fr', gap: 6, padding: '7px 0', borderBottom: idx < rStops.length - 1 ? '1px solid var(--hairline)' : 'none' }}>
                                        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                                          <div style={{
                                            width: 16, height: 16, borderRadius: '50%', display: 'grid', placeItems: 'center', flexShrink: 0,
                                            background: isPickup ? '#fef3c7' : '#dcfce7',
                                            border: isPickup ? '1.5px solid #f59e0b' : '1.5px solid #16a34a',
                                            color: isPickup ? '#92400e' : '#166534',
                                            fontFamily: 'var(--font-mono)', fontSize: 8, fontWeight: 700,
                                          }}>{idx + 1}</div>
                                          {idx < rStops.length - 1 && <div style={{ flex: 1, width: 1, background: 'var(--hairline)', marginTop: 2 }} />}
                                        </div>
                                        <div style={{ paddingBottom: 2 }}>
                                          <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                                            <span style={{ fontSize: 10, color: isPickup ? '#b45309' : '#15803d' }}>{isPickup ? '📦' : '🏠'}</span>
                                            <span style={{ fontSize: 11.5, color: 'var(--ink)', fontWeight: 500 }}>{addr}</span>
                                          </div>
                                        </div>
                                      </div>
                                    );
                                  })}
                                </div>
                              </div>
                            </div>
                          )}
                        </div>
                      );
                    })}
                  </div>
                </div>
              );
            })}
          </div>
        );
      })()}

      {deliveryType === 'dispatch' && tab === 'completed' && (
        !completedFetched ? (
          <div className="panel" style={{ padding: 32, textAlign: 'center', maxWidth: 400 }}>
            <button className="btn primary" onClick={doRefreshCompleted}><I.refresh size={12} />Load completed routes</button>
          </div>
        ) : loadingCompleted ? (
          <div className="muted" style={{ padding: 24, fontSize: 12 }}>Loading…</div>
        ) : completedRoutes.length === 0 ? (
          <div className="panel" style={{ padding: 24, textAlign: 'center', maxWidth: 400 }}>
            <div className="muted" style={{ fontSize: 13 }}>No completed routes</div>
          </div>
        ) : (
          <div className="mob-stack" style={{ display: 'grid', gridTemplateColumns: '300px 1fr 340px', gap: 14, height: 'calc(100vh - 260px)', minHeight: 520 }}>
            <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              <div className="panel-h">
                <span>Completed routes</span>
                <button className="btn ghost" style={{ height: 24 }} onClick={doRefreshCompleted}><I.refresh size={11} /></button>
              </div>
              <div style={{ flex: 1, overflow: 'auto' }}>
                {completedRoutes.map(r => {
                  const sel = r.id === completedSelId;
                  const meta = ROUTE_STATUS_META[r.status] || { label: r.status, chip: 'neg' };
                  return (
                    <div key={r.id} onClick={() => setCompletedSelId(r.id)} style={{
                      padding: '12px 14px', borderBottom: '1px solid var(--hairline)',
                      background: sel ? 'var(--surface-2)' : 'transparent',
                      cursor: 'pointer', position: 'relative',
                    }}>
                      {sel && <div style={{ position: 'absolute', left: 0, top: 8, bottom: 8, width: 2, background: 'var(--accent)' }} />}
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                        <span className="id" style={{ color: 'var(--ink)' }}>{r.id.slice(0, 8).toUpperCase()}</span>
                        <span className={`chip dot ${meta.chip}`}>{meta.label}</span>
                        <span className="muted num" style={{ marginLeft: 'auto', fontSize: 10.5 }}>{r.dispatch_window}</span>
                      </div>
                      <div style={{ marginTop: 6, fontSize: 12.5, color: 'var(--ink)', fontWeight: 500 }}>{r.driver?.display_name || '—'}</div>
                      <div className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)', marginTop: 1 }}>
                        {r.total_stops} stops · {fmtDist(r.total_distance_m)} · {fmtDate(r.completed_at || r.updated_at)}
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
            <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              {!completedRoute ? (
                <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <span className="muted" style={{ fontSize: 12 }}>Select a route</span>
                </div>
              ) : (
                <>
                  <div className="panel-h" style={{ padding: '3px 14px 0', height: 40 }}>
                    <span>{completedRoute.id.slice(0, 8).toUpperCase()} · {completedRoute.driver?.display_name || '—'}</span>
                    <span className={`chip dot ${ROUTE_STATUS_META[completedRoute.status]?.chip || 'pos'}`}>
                      {ROUTE_STATUS_META[completedRoute.status]?.label || completedRoute.status}
                    </span>
                  </div>
                  <RouteMap route={completedRoute} locationHistory={[]} showDriverPath={true} />
                </>
              )}
            </div>
            <div className="panel" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              {!completedRoute ? (
                <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <span className="muted" style={{ fontSize: 12 }}>Select a route</span>
                </div>
              ) : (
                <>
                  <div className="panel-h"><span>Route detail</span></div>
                  <div style={{ padding: 14, borderBottom: '1px solid var(--hairline)' }}>
                    <div className="row gap-3">
                      <div className="avatar" style={{ width: 36, height: 36, fontSize: 12 }}>{initials(completedRoute.driver?.display_name || '?')}</div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontWeight: 550, color: 'var(--ink)', fontSize: 13.5 }}>{completedRoute.driver?.display_name || '—'}</div>
                        <div className="id">{completedRoute.driver?.phone || '—'}</div>
                      </div>
                    </div>
                    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 10, marginTop: 14 }}>
                      <RouteStat label="Completed" value={fmtDate(completedRoute.completed_at || completedRoute.updated_at)} />
                      <RouteStat label="Dispatched" value={completedRoute.dispatched_at ? fmtTime(completedRoute.dispatched_at) : '—'} />
                      <RouteStat label="Window" value={completedRoute.dispatch_window || '—'} />
                      <RouteStat label="Distance" value={fmtDist(completedRoute.total_distance_m)} />
                      <RouteStat label="Duration" value={fmtDuration(completedRoute.total_duration_s)} />
                      <RouteStat label="GMV" value={currency(completedGmv)} />
                    </div>
                  </div>
                  <div style={{ flex: 1, overflow: 'auto' }}>
                    {completedRoute.stops.length > 0 && (
                      <>
                        <div style={{ padding: '10px 14px 6px' }}>
                          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase' }}>
                            Stop sequence ({completedRoute.stops.length})
                          </div>
                        </div>
                        <div style={{ padding: '0 14px 14px' }}>
                          {completedRoute.stops.map((s, idx) => {
                            const isSkipped = s.status === 'skipped';
                            const arrived = s.actual_arrival || s.completed_at;
                            const eta = s.estimated_arrival;
                            const deltaMin = (arrived && eta) ? Math.round((new Date(arrived) - new Date(eta)) / 60000) : null;
                            const deltaColor = deltaMin === null ? null : Math.abs(deltaMin) <= 5 ? '#16a34a' : deltaMin <= 15 ? '#d97706' : '#dc2626';
                            const prevArrived = idx > 0 ? (completedRoute.stops[idx-1].actual_arrival || completedRoute.stops[idx-1].completed_at) : null;
                            const legMin = (arrived && prevArrived) ? Math.round((new Date(arrived) - new Date(prevArrived)) / 60000) : null;
                            const addr = s.address ? fmtAddrShort(s.address) : '—';
                            return (
                              <div key={s.id} style={{ display: 'grid', gridTemplateColumns: '24px 1fr', gap: 8, padding: '10px 0', borderBottom: idx < completedRoute.stops.length - 1 ? '1px solid var(--hairline)' : 'none' }}>
                                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
                                  <div style={{
                                    width: 18, height: 18, borderRadius: '50%', display: 'grid', placeItems: 'center', flexShrink: 0,
                                    background: 'var(--surface-2)', border: '1px solid var(--hairline-2)',
                                    color: isSkipped ? 'var(--ink-3)' : 'var(--accent)',
                                    fontFamily: 'var(--font-mono)', fontSize: 9.5, fontWeight: 600,
                                  }}>
                                    {isSkipped ? '–' : <I.check size={10} />}
                                  </div>
                                  {idx < completedRoute.stops.length - 1 && (
                                    <div style={{ flex: 1, width: 1, background: 'var(--hairline)', marginTop: 3 }} />
                                  )}
                                </div>
                                <div style={{ minWidth: 0, paddingBottom: 2 }}>
                                  <div style={{ fontSize: 12.5, color: isSkipped ? 'var(--ink-3)' : 'var(--ink)', textDecoration: isSkipped ? 'line-through' : 'none', marginBottom: 3 }}>{addr}</div>
                                  <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
                                    <span className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)' }}>{s.stop_type === 'pickup' ? '📦' : '🏠'} {s.stop_type}</span>
                                    {arrived && <span style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', color: 'var(--ink-2)' }}>↓ {fmtTime(arrived)}</span>}
                                    {eta && <span className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)' }}>ETA {fmtTime(eta)}</span>}
                                    {deltaMin !== null && <span style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)', color: deltaColor }}>{deltaMin === 0 ? 'on time' : (deltaMin > 0 ? '+' : '') + deltaMin + 'm'}</span>}
                                    {legMin !== null && legMin > 0 && <span className="muted" style={{ fontSize: 10.5, fontFamily: 'var(--font-mono)' }}>{legMin}m leg</span>}
                                  </div>
                                </div>
                              </div>
                            );
                          })}
                        </div>
                      </>
                    )}
                    {completedRoute.deliveries.length > 0 && (
                      <div style={{ padding: '10px 14px', borderTop: completedRoute.stops.length > 0 ? '1px solid var(--hairline)' : 'none' }}>
                        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 8 }}>
                          Deliveries ({completedRoute.deliveries.length})
                        </div>
                        {completedRoute.deliveries.map(d => (
                          <div key={d.id} style={{ display: 'flex', gap: 8, padding: '6px 0', borderBottom: '1px solid var(--hairline)', alignItems: 'baseline' }}>
                            <span className="id" style={{ color: 'var(--ink)', fontSize: 11 }}>{d.tracking_number || d.id.slice(0, 8).toUpperCase()}</span>
                            <span className="muted" style={{ fontSize: 11, flex: 1 }}>{fmtAddrShort(d.pickup_address)} → {fmtAddrShort(d.delivery_address)}</span>
                            <span className="num" style={{ fontSize: 11.5, whiteSpace: 'nowrap' }}>{currency(d.order?.total_amount)}</span>
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                </>
              )}
            </div>
          </div>
        )
      )}

      {/* ── FLASH tabs ── */}
      {deliveryType === 'flash' && tab === 'new' && <FlashNewTab />}
      {deliveryType === 'flash' && tab === 'active' && <FlashActiveTab />}
      {deliveryType === 'flash' && tab === 'completed' && <FlashCompletedTab />}
    </div>
  );
};

window.DeliveryPage = DispatchPage;
