// booking.jsx — multi-step same-day booking wizard
const { useState: useStateBk, useMemo: useMemoBk, useEffect: useEffectBk } = React;

const STEP_LABELS = { service: "Service", addresses: "Addresses", time: "Pickup time", airfreight: "Air freight", details: "Details", notify: "Notify", review: "Review" };
const STD_KEYS = ["service", "addresses", "time", "details", "notify", "review"];
const NF_KEYS = ["service", "addresses", "time", "airfreight", "details", "notify", "review"];

function now15() { const d = new Date(); let m = Math.ceil(d.getMinutes() / 15) * 15; let h = d.getHours(); if (m === 60) { m = 0; h = (h + 1) % 24; } return String(h).padStart(2, "0") + ":" + String(m).padStart(2, "0"); }
function fmt12(t) { const m = /^(\d{1,2}):(\d{2})/.exec(t || ""); if (!m) return ""; let h = +m[1]; const ap = h < 12 ? "AM" : "PM"; h = (h % 12) || 12; return h + ":" + m[2] + " " + ap; }

function serviceTimeWarning(serviceId, time) {
  if (!time) return null;
  const hr = parseInt(String(time).slice(0, 2), 10);
  if (isNaN(hr)) return null;
  if (serviceId === "direct" && hr >= 16) return "Direct (fastest) service booked after 4 PM may not complete today — consider an earlier ready time or a slower service tier.";
  if (serviceId === "premium" && hr >= 17) return "Premium service booked this late in the day may roll to the next business day.";
  return null;
}

function DraftsResume({ drafts, onResume, onDelete, currency, savedNote }) {
  return (
    <Card pad={20} style={{ marginBottom: 16, borderColor: "var(--accent)", background: "var(--accent-soft)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 4 }}>
        <Icon name="history" size={17} color="var(--accent-700)" />
        <span style={{ fontSize: 15, fontWeight: 700, color: "var(--fg-strong)" }}>Saved bookings</span>
        <Badge tone="accent">{drafts.length}</Badge>
      </div>
      <div style={{ fontSize: 12.5, color: "var(--fg-body)", marginBottom: 12 }}>{savedNote ? "Saved — pick it up any time. It won't be processed until you place it." : "Bookings you saved to finish later. Resume to review and place — they aren't processed until placed."}</div>
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {drafts.map(d => (
          <div key={d.id} style={{ display: "flex", alignItems: "center", gap: 12, background: "var(--surface)", border: "1px solid var(--border)", borderRadius: "var(--r-md)", padding: "11px 13px" }}>
            <span style={{ width: 34, height: 34, borderRadius: 9, flex: "none", background: d.deliveryType === "nextflight" ? "var(--brand-soft)" : "var(--bg-mist)", color: "var(--brand)", display: "inline-flex", alignItems: "center", justifyContent: "center" }}><Icon name={d.deliveryType === "nextflight" ? "plane" : "truck"} size={16} /></span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--fg-strong)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{(d.from || "—")} → {(d.to || "—")}</div>
              <div style={{ fontSize: 11.5, color: "var(--fg-mute)" }}>Saved {new Date(d.savedAt).toLocaleDateString("en-AU", { day: "numeric", month: "short" })} · {d.deliveryType === "nextflight" ? "Next Flight" : "Standard"}{d.total ? " · " + window.FX.money(d.total, currency) : ""}</div>
            </div>
            <Button variant="primary" size="sm" iconRight="arrow-right" onClick={() => onResume(d)}>Resume</Button>
            <button onClick={() => onDelete(d.id)} title="Discard" style={{ background: "none", border: "1px solid var(--border)", borderRadius: 8, width: 32, height: 32, display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--fg-mute)", cursor: "pointer" }}><Icon name="x" size={15} /></button>
          </div>
        ))}
      </div>
    </Card>
  );
}

function Stepper({ steps, step, onJump, maxReached }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 0, marginBottom: 28, flexWrap: "wrap" }}>
      {steps.map((s, i) => {
        const done = i < step, active = i === step, reachable = i <= maxReached;
        return (
          <React.Fragment key={s}>
            <button onClick={() => reachable && onJump(i)} style={{
              display: "inline-flex", alignItems: "center", gap: 8, background: "transparent", border: "none",
              padding: "4px 2px", cursor: reachable ? "pointer" : "default",
            }}>
              <span style={{
                width: 26, height: 26, borderRadius: "50%", flex: "none", display: "inline-flex", alignItems: "center", justifyContent: "center",
                fontSize: 12.5, fontWeight: 700, fontFamily: "var(--font-mono)",
                background: done ? "var(--brand)" : active ? "var(--accent)" : "var(--bg-mist-2)",
                color: done || active ? "#fff" : "var(--fg-mute)", transition: "all 160ms ease",
              }}>{done ? <Icon name="check" size={14} /> : i + 1}</span>
              <span style={{ fontSize: 13, fontWeight: active ? 600 : 500, color: active ? "var(--fg-strong)" : done ? "var(--fg-body)" : "var(--fg-faint)" }}>{s}</span>
            </button>
            {i < steps.length - 1 && <span style={{ width: 22, height: 2, background: i < step ? "var(--brand)" : "var(--border)", margin: "0 8px", borderRadius: 2 }} />}
          </React.Fragment>
        );
      })}
    </div>
  );
}

function Booking({ addressBook, currency, rateMult, onPlaced, nav, accounts, activeAccount, seedQuote, drafts = [], onSaveDraft, onDeleteDraft }) {
  const [step, setStep] = useStateBk(0);
  const [maxReached, setMaxReached] = useStateBk(0);
  const [placed, setPlaced] = useStateBk(null);

  const resumeDraft = (seedQuote && seedQuote.resumeDraft) || null;
  const src = resumeDraft || seedQuote || {};

  const seededStops = (resumeDraft && resumeDraft.stops) ? resumeDraft.stops
    : (src.from ? [{ ...window.FX.emptyAddr(), suburb: src.from, postcode: src.fromPc || "" }, { ...window.FX.emptyAddr(), suburb: src.to, postcode: src.toPc || "" }] : [window.FX.emptyAddr(), window.FX.emptyAddr()]);
  const [items, setItems] = useStateBk((src.items && src.items.length) ? src.items : [window.FX.blankItem()]);
  const [stops, setStops] = useStateBk(seededStops);
  const [date, setDate] = useStateBk((resumeDraft && resumeDraft.date) || window.FX.todayISO());
  const [time, setTime] = useStateBk(resumeDraft ? "" : now15());
  const [serviceId, setServiceId] = useStateBk(src.serviceId || "standard");
  const [isReturn, setIsReturn] = useStateBk(!!src.isReturn);
  const [accountId, setAccountId] = useStateBk((resumeDraft && resumeDraft.accountId) || (activeAccount && activeAccount.id) || "acc1");
  const [ref1, setRef1] = useStateBk((resumeDraft && resumeDraft.ref1) || "");
  const [ref2, setRef2] = useStateBk((resumeDraft && resumeDraft.ref2) || "");
  const [notify, setNotify] = useStateBk((resumeDraft && resumeDraft.notify) || { pickupOn: true, pickupSms: true, pickupEmail: true, recipOn: true, recipSms: true, recipEmail: true, returnOn: true, returnSms: true, returnEmail: true, extra: [] });
  const [decl, setDecl] = useStateBk((resumeDraft && resumeDraft.decl) || { dg: null, dgType: "", desc: "", length: "", width: "", height: "", weight: "", qty: "1", agree: false, dgPackages: "1", dgNetQty: "", dgEmergency: "", dgShipperDecl: false, noDgAck: false, declaredBy: "" });
  const setD = (k, val) => setDecl(prev => ({ ...prev, [k]: val }));
  const [deliveryType, setDeliveryType] = useStateBk((resumeDraft && resumeDraft.deliveryType) || "standard");
  const [resuming, setResuming] = useStateBk(!!resumeDraft);
  const [savedNote, setSavedNote] = useStateBk(false);
  const auto = useMemoBk(() => window.FX.autoVehicleForItems(items), [items]);
  const vehicleId = auto.vehicleId;
  const itemTot = useMemoBk(() => window.FX.itemTotals(items), [items]);
  const hasItems = itemTot.kg > 0;

  const account = (accounts || window.FX.ACCOUNTS).find(a => a.id === accountId) || (accounts || window.FX.ACCOUNTS)[0];
  const pickup = stops[0];
  const dropoff = stops[stops.length - 1];
  const puState = window.FX.suburbState(pickup.suburb);
  const doState = window.FX.suburbState(dropoff.suburb);
  const routeInterstate = !!(puState && doState && puState !== doState);
  const isInterstate = deliveryType === "nextflight";
  const stepKeys = isInterstate ? NF_KEYS : STD_KEYS;
  const steps = stepKeys.map(k => STEP_LABELS[k]);
  const curKey = stepKeys[Math.min(step, stepKeys.length - 1)];
  useEffectBk(() => { if (routeInterstate) setDeliveryType("nextflight"); }, [routeInterstate]);
  useEffectBk(() => { if (isInterstate && isReturn) setIsReturn(false); }, [isInterstate]);
  useEffectBk(() => { setStep(s => Math.min(s, stepKeys.length - 1)); setMaxReached(m => Math.min(m, stepKeys.length - 1)); }, [isInterstate]);
  const setStop = (i, val) => setStops(prev => prev.map((s, idx) => (idx === i ? val : s)));
  const addStop = () => setStops(prev => [...prev, window.FX.emptyAddr()]);
  const removeStop = (i) => setStops(prev => prev.filter((_, idx) => idx !== i));
  const stopComplete = (s) => !!(s && s.suburb && s.contact);
  const allStopsComplete = stops.every(stopComplete);

  const km = useMemoBk(() => {
    if (!allStopsComplete) return null;
    let total = 0;
    for (let i = 0; i < stops.length - 1; i++) { const d = window.FX.distanceKm(stops[i].suburb, stops[i + 1].suburb); if (d == null) return null; total += d; }
    return total;
  }, [stops, allStopsComplete]);
  const q = useMemoBk(() => vehicleId ? window.FX.quote({ vehicleId, km: km || 0, serviceId, isReturn, rateMult }) : null, [vehicleId, km, serviceId, isReturn, rateMult]);

  function goNext() { const n = Math.min(step + 1, steps.length - 1); setStep(n); setMaxReached(m => Math.max(m, n)); }
  function goBack() { setStep(s => Math.max(0, s - 1)); }
  function jump(i) { setStep(i); }
  function resetForm() { setStep(0); setMaxReached(0); setResuming(false); setItems([window.FX.blankItem()]); setStops([window.FX.emptyAddr(), window.FX.emptyAddr()]); setDate(window.FX.todayISO()); setTime(now15()); setServiceId("standard"); setIsReturn(false); setRef1(""); setRef2(""); setDeliveryType("standard"); setNotify({ pickupOn: true, pickupSms: true, pickupEmail: true, recipOn: true, recipSms: true, recipEmail: true, returnOn: true, returnSms: true, returnEmail: true, extra: [] }); setDecl({ dg: null, dgType: "", desc: "", length: "", width: "", height: "", weight: "", qty: "1", agree: false, dgPackages: "1", dgNetQty: "", dgEmergency: "", dgShipperDecl: false, noDgAck: false, declaredBy: "" }); }
  function saveForLater() {
    const draft = { id: resumeDraft ? resumeDraft.id : "D-" + Date.now(), savedAt: new Date().toISOString(), deliveryType, items, stops, date, serviceId, isReturn, accountId, ref1, ref2, notify, decl, from: pickup.suburb, to: dropoff.suburb, total: q ? q.total : 0 };
    onSaveDraft && onSaveDraft(draft);
    resetForm(); setSavedNote(true); window.scrollTo({ top: 0 });
  }

  const dgAssessment = (decl.dg === "yes" && decl.dgType) ? window.FX.dgAssess(decl.dgType, decl.dgPackages || "1") : null;
  const declReady = decl.dg === "no"
    ? !!decl.noDgAck
    : decl.dg === "yes" && !!decl.dgType && !!(decl.dgEmergency || "").trim() && decl.dgShipperDecl && !!dgAssessment && dgAssessment.status === "accept";
  const airFreightReady = !!decl.desc.trim() && !!(decl.declaredBy || "").trim() && declReady && decl.agree;
  const stdDeclReady = decl.dg === "no" ? !!decl.noDgAck : (decl.dg === "yes" && !!decl.dgType && !!decl.dgShipperDecl && !!dgAssessment && dgAssessment.status === "accept");
  const canNext = {
    service: hasItems && !!serviceId,
    addresses: allStopsComplete,
    time: !!date && !!time,
    airfreight: airFreightReady,
    details: isInterstate ? true : stdDeclReady, notify: true, review: true,
  }[curKey];
  const svcWarn = serviceTimeWarning(serviceId, time);

  function place() {
    const effReturn = isInterstate ? false : isReturn;
    const booking = {
      tracking: window.FX.genTracking(), vehicleId, serviceId, isReturn: effReturn,
      pickup, dropoff, stops, date, time, km: km || 0, lineItems: items, notify,
      account, ref1, ref2,
      typeId: isInterstate ? "nextflight" : "standard", interstate: isInterstate,
      audit: [{ at: new Date().toISOString(), by: "Customer portal", action: "created", detail: "Booked online" }],
      declaration: isInterstate ? { ...decl, puState, doState } : ((decl.dg === "yes" || decl.dg === "no") ? { dg: decl.dg, dgType: decl.dgType, dgPackages: decl.dgPackages, dgShipperDecl: decl.dgShipperDecl, noDgAck: decl.noDgAck } : null),
      total: q.total, subtotal: q.subtotal, gst: q.gst, oneWay: q.oneWay, returnLeg: q.returnLeg,
      placedAt: new Date().toISOString(),
    };
    setPlaced(booking);
    onPlaced && onPlaced(booking);
    if (resumeDraft && onDeleteDraft) onDeleteDraft(resumeDraft.id);
    window.scrollTo({ top: 0 });
  }

  const showPrice = curKey === "review";

  if (placed) {
    return <Confirmation booking={placed} currency={currency}
      onNewBooking={() => { setPlaced(null); setStep(0); setMaxReached(0); setItems([window.FX.blankItem()]); setStops([window.FX.emptyAddr(), window.FX.emptyAddr()]); setTime(new Date().toTimeString().slice(0, 5)); setServiceId("standard"); setIsReturn(false); setRef1(""); setRef2(""); setDecl({ dg: null, dgType: "", desc: "", length: "", width: "", height: "", weight: "", qty: "1", agree: false, dgPackages: "1", dgNetQty: "", dgEmergency: "", dgShipperDecl: false, noDgAck: false, declaredBy: "" }); }}
      onTrack={() => window.open("Fedex Track.html#t=" + encodeURIComponent(placed.tracking), "_blank")}
      onHistory={() => nav("history")} />;
  }

  return (
    <div className="fade-up">
      <PageHeader eyebrow="New booking" title="Book a same-day delivery" sub="Pick a service and set your addresses. We'll confirm your price at the final step." />
      <Stepper steps={steps} step={step} onJump={jump} maxReached={maxReached} />
      {resuming && (
        <div style={{ display: "flex", gap: 11, alignItems: "flex-start", padding: "12px 15px", background: "var(--accent-soft)", border: "1px solid var(--accent)", borderRadius: "var(--r-md)", marginBottom: 18 }}>
          <Icon name="repeat" size={17} color="var(--accent-700)" style={{ flex: "none", marginTop: 1 }} />
          <span style={{ fontSize: 13.5, color: "var(--fg-body)", lineHeight: 1.5 }}><strong style={{ color: "var(--fg-strong)" }}>Resuming a saved booking.</strong> Step through and confirm each detail — in particular update the <strong>ready date &amp; time</strong> and check the <strong>service level</strong> still suits it before placing.</span>
        </div>
      )}

      <div style={{ display: "grid", gridTemplateColumns: "minmax(0,1fr) 320px", gap: 24, alignItems: "start" }}>
        <div>
          {curKey === "service" && <React.Fragment>
            {!resuming && drafts && drafts.length > 0 && <DraftsResume drafts={drafts} onResume={d => nav("book", { resumeDraft: d })} onDelete={onDeleteDraft} currency={currency} savedNote={savedNote} />}
            <StepService {...{ items, setItems, auto, itemTot, serviceId, setServiceId, km, isReturn, rateMult, currency, showPrice, deliveryType, setDeliveryType, routeInterstate }} />
          </React.Fragment>}
          {curKey === "addresses" && <StepAddresses {...{ stops, setStop, addStop, removeStop, addressBook, km, stopComplete, isReturn, setIsReturn, isInterstate }} />}
          {curKey === "time" && <StepTime {...{ date, setDate, time, setTime, serviceId, resuming, svcWarn }} />}
          {curKey === "airfreight" && <StepAirFreight {...{ decl, setD, puState, doState, dgAssessment, items, itemTot }} />}
          {curKey === "details" && <StepDetails {...{ accounts: accounts || window.FX.ACCOUNTS, accountId, setAccountId, ref1, setRef1, ref2, setRef2, decl, setD, dgAssessment, isInterstate }} />}
          {curKey === "notify" && <StepNotify {...{ notify, setNotify, pickup, dropoff, isReturn }} />}
          {curKey === "review" && <StepReview {...{ vehicleId, pickup, dropoff, stops, date, time, serviceId, isReturn, notify, q, km, currency, account, ref1, ref2, isInterstate, decl, itemTot }} />}

          <div style={{ display: "flex", justifyContent: "space-between", marginTop: 24, gap: 12, flexWrap: "wrap" }}>
            {step > 0 ? <Button variant="ghost" icon="arrow-left" onClick={goBack}>Back</Button> : <span />}
            <div style={{ display: "flex", gap: 10, marginLeft: "auto" }}>
              <Button variant="secondary" icon="history" onClick={saveForLater}>Save &amp; finish later</Button>
              {curKey !== "review"
                ? <Button variant="primary" iconRight="arrow-right" onClick={goNext} disabled={!canNext}>Continue</Button>
                : <Button variant="primary" size="lg" icon="check-circle" onClick={place}>Place booking · {window.FX.money(q ? q.total : 0, currency)}</Button>}
            </div>
          </div>
        </div>

        <SummaryRail {...{ vehicleId, pickup, dropoff, stops, date, time, serviceId, isReturn, q, km, currency, step, account, ref1, isInterstate, showPrice, deliveryType }} />
      </div>
    </div>
  );
}

/* ---------- Step 1: Service (size + tier) ---------- */
function StepService({ items, setItems, auto, itemTot, serviceId, setServiceId, km, isReturn, rateMult, currency, showPrice, deliveryType, setDeliveryType, routeInterstate }) {
  const vehicleId = auto.vehicleId;
  const vSel = window.FX.VEHICLES.find(x => x.id === vehicleId);
  return (
    <Card pad={26}>
      <StepTitle n="01" title="What are you sending?" sub="Choose how it travels, then add each item with its size and weight — we choose the right vehicle for you." />

      <div style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-strong)", marginBottom: 10 }}>Delivery type</div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 11, marginBottom: 8 }}>
        {[
          { id: "standard", icon: "truck", title: "Standard courier", sub: "Same-day, door to door by road — within your city." },
          { id: "nextflight", icon: "plane", title: "Next Flight", sub: "Interstate air freight — on the next available flight." },
        ].map(o => {
          const active = deliveryType === o.id;
          return (
            <button key={o.id} onClick={() => setDeliveryType(o.id)} style={{
              display: "flex", alignItems: "flex-start", gap: 12, textAlign: "left",
              border: "1.5px solid " + (active ? "var(--accent)" : "var(--border)"), borderRadius: "var(--r-lg)",
              background: active ? "var(--accent-soft)" : "var(--surface)", padding: "14px 15px", transition: "all 160ms ease",
            }}>
              <span style={{ width: 38, height: 38, borderRadius: 10, flex: "none", display: "inline-flex", alignItems: "center", justifyContent: "center", background: active ? "var(--accent)" : "var(--brand-soft)", color: active ? "#fff" : "var(--brand)" }}><Icon name={o.icon} size={18} /></span>
              <span style={{ flex: 1, minWidth: 0 }}>
                <span style={{ display: "block", fontWeight: 700, fontSize: 14.5, color: "var(--fg-strong)" }}>{o.title}</span>
                <span style={{ display: "block", fontSize: 12, color: "var(--fg-mute)", marginTop: 2, lineHeight: 1.35 }}>{o.sub}</span>
              </span>
              {active && <Icon name="check-circle" size={18} color="var(--accent)" />}
            </button>
          );
        })}
      </div>
      {deliveryType === "nextflight" && !routeInterstate && (
        <div style={{ display: "flex", gap: 8, alignItems: "flex-start", padding: "9px 12px", background: "var(--brand-soft)", borderRadius: "var(--r-sm)", marginBottom: 8 }}>
          <Icon name="info" size={14} color="var(--brand)" style={{ flex: "none", marginTop: 1 }} />
          <span style={{ fontSize: 12.5, color: "var(--fg-body)" }}>At the address step, pick a pickup and delivery in different states — e.g. Sydney → Melbourne. You'll complete the air-freight declaration before review.</span>
        </div>
      )}

      <div style={{ height: 14 }} />
      <div style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-strong)", marginBottom: 10 }}>Items</div>
      <ItemsEditor items={items} setItems={setItems} />

      <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 14, padding: "12px 14px", borderRadius: "var(--r-md)", background: auto.over ? "var(--warn-soft)" : "var(--brand-soft)" }}>
        <span style={{ width: 38, height: 38, borderRadius: 10, flex: "none", background: auto.over ? "var(--warn)" : "var(--brand)", color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center" }}><Icon name={auto.over ? "truck-big" : (vSel ? vSel.icon : "package")} size={18} /></span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 10, fontFamily: "var(--font-mono)", letterSpacing: "0.6px", textTransform: "uppercase", color: auto.over ? "#8a5a00" : "var(--brand)" }}>Vehicle · selected for you</div>
          <div style={{ fontSize: 14, fontWeight: 700, color: "var(--fg-strong)" }}>{auto.over ? "Taxi truck (we'll call you)" : (vSel ? vSel.name : "—")} <span style={{ fontWeight: 400, color: "var(--fg-mute)", fontSize: 12.5 }}>· {itemTot.kg} kg · {itemTot.m3} m³</span></div>
        </div>
      </div>

      <div style={{ height: 22 }} />

      <div style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-strong)", marginBottom: 4 }}>Service tier</div>
      <div style={{ fontSize: 12.5, color: "var(--fg-mute)", marginBottom: 12 }}>{vehicleId ? "Faster tiers deliver within a tighter window." : "Select a size above, then choose how fast you need it."}</div>
      <div style={{ display: "flex", flexDirection: "column", gap: 11 }}>
        {window.FX.SERVICES.map(s => {
          const active = s.id === serviceId;
          const price = vehicleId ? window.FX.quote({ vehicleId, km: km || 0, serviceId: s.id, isReturn, rateMult }).total : null;
          const code = vehicleId ? window.FX.serviceCode(s.id, vehicleId) : null;
          return (
            <button key={s.id} onClick={() => setServiceId(s.id)} style={{
              display: "flex", alignItems: "center", gap: 15, textAlign: "left", width: "100%",
              border: "1.5px solid " + (active ? "var(--accent)" : "var(--border)"), borderRadius: "var(--r-lg)",
              background: active ? "var(--accent-soft)" : "var(--surface)", padding: "16px 18px", transition: "all 160ms ease",
            }}>
              <span style={{ width: 22, height: 22, borderRadius: "50%", flex: "none", border: "2px solid " + (active ? "var(--accent)" : "var(--border-strong)"), display: "inline-flex", alignItems: "center", justifyContent: "center" }}>
                {active && <span style={{ width: 10, height: 10, borderRadius: "50%", background: "var(--accent)" }} />}
              </span>
              <span style={{ flex: 1 }}>
                <span style={{ display: "flex", alignItems: "center", gap: 9, flexWrap: "wrap" }}>
                  <span style={{ fontWeight: 700, fontSize: 15.5, color: "var(--fg-strong)" }}>{s.name}{vehicleId ? " " + window.FX.VEHICLES.find(x => x.id === vehicleId).name : ""}</span>
                  {code && <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 600, letterSpacing: "0.5px", color: active ? "var(--accent-700)" : "var(--brand)", background: active ? "rgba(255,255,255,0.6)" : "var(--brand-soft)", padding: "2px 7px", borderRadius: 5 }}>{code}</span>}
                  {s.tag && <Badge tone={s.id === "direct" ? "accent" : "brand"}>{s.tag}</Badge>}
                </span>
                <span style={{ display: "block", fontSize: 13, color: "var(--fg-mute)", marginTop: 3 }}>{s.window}</span>
              </span>
              <span style={{ textAlign: "right", flex: "none" }}>
                {showPrice && <span style={{ display: "block", fontWeight: 700, fontSize: 16, color: "var(--fg-strong)" }}>{price != null ? window.FX.money(price, currency) : "—"}</span>}
                <span style={{ display: "block", fontFamily: "var(--font-mono)", fontSize: 12.5, fontWeight: 600, color: "var(--accent-700)", marginTop: showPrice ? 2 : 0 }}>{s.eta}</span>
              </span>
            </button>
          );
        })}
      </div>
    </Card>
  );
}

/* ---------- Step 2: Addresses (multi-leg) ---------- */
function StepAddresses({ stops, setStop, addStop, removeStop, addressBook, km, isReturn, setIsReturn, isInterstate }) {
  return (
    <Card pad={26}>
      <StepTitle n="02" title="Pickup & drop-off" sub="Enter addresses directly, or pull one from your address book. Add more legs for multi-stop runs." />
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        {stops.map((s, i) => {
          const isFirst = i === 0, isLast = i === stops.length - 1;
          const role = isFirst ? "Pickup from" : (stops.length > 2 ? `Drop-off ${i}` : "Deliver to");
          const accent = isFirst ? "var(--brand)" : "var(--accent)";
          const removable = i > 0 && stops.length > 2;
          const legKm = (!isLast && s.suburb && stops[i + 1].suburb) ? window.FX.distanceKm(s.suburb, stops[i + 1].suburb) : null;
          return (
            <React.Fragment key={i}>
              <AddressField value={s} onChange={v => setStop(i, v)} addressBook={addressBook} role={role} accent={accent} index={i} onRemove={removable ? () => removeStop(i) : undefined} />
              {!isLast && (
                <div style={{ display: "flex", justifyContent: "center", alignItems: "center", gap: 8, margin: "-2px 0" }}>
                  <span style={{ width: 2, height: 16, background: "var(--border-strong)", borderRadius: 2 }} />
                  {legKm != null && <Badge tone="brand"><Icon name="navigation" size={11} /> {legKm} km</Badge>}
                  <span style={{ width: 2, height: 16, background: "var(--border-strong)", borderRadius: 2 }} />
                </div>
              )}
            </React.Fragment>
          );
        })}
      </div>
      <button onClick={addStop} style={{ marginTop: 14, display: "flex", alignItems: "center", justifyContent: "center", gap: 8, width: "100%", padding: "12px", background: "var(--surface)", border: "1px dashed var(--border-strong)", borderRadius: "var(--r-md)", color: "var(--brand)", fontSize: 14, fontWeight: 500 }}>
        <Icon name="plus" size={16} /> Add another leg
      </button>
      {km != null && <div style={{ marginTop: 14, display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "var(--fg-mute)" }}><Icon name="navigation" size={14} color="var(--brand)" /> Total distance <strong style={{ color: "var(--fg-strong)" }}>{km} km</strong> across {stops.length - 1} leg{stops.length - 1 > 1 ? "s" : ""}</div>}
      {!isInterstate && (
        <div style={{ marginTop: 16, borderTop: "1px solid var(--border)", paddingTop: 16 }}>
          <button onClick={() => setIsReturn(!isReturn)} style={{ display: "flex", gap: 12, alignItems: "flex-start", width: "100%", textAlign: "left", background: isReturn ? "var(--accent-soft)" : "var(--surface)", border: "1.5px solid " + (isReturn ? "var(--accent)" : "var(--border)"), borderRadius: "var(--r-md)", padding: "13px 15px", transition: "all 140ms ease" }}>
            <span style={{ width: 22, height: 22, borderRadius: 6, flex: "none", marginTop: 1, border: "1.5px solid " + (isReturn ? "var(--accent)" : "var(--border-strong)"), background: isReturn ? "var(--accent)" : "transparent", display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{isReturn && <Icon name="check" size={14} color="#fff" />}</span>
            <span style={{ flex: 1 }}>
              <span style={{ display: "block", fontSize: 14, fontWeight: 600, color: "var(--fg-strong)" }}>Make this a return trip</span>
              <span style={{ display: "block", fontSize: 12.5, color: "var(--fg-mute)", marginTop: 2 }}>After delivering, the driver returns to the pickup point. The return leg is discounted 15%.</span>
            </span>
          </button>
        </div>
      )}
    </Card>
  );
}

/* ---------- Step 3: Time (15-minute intervals, 24 h) ---------- */
function StepTime({ date, setDate, time, setTime, serviceId, resuming, svcWarn }) {
  const parts = (time && /^\d{2}:\d{2}$/.test(time)) ? time.split(":") : ["", ""];
  const h = parts[0], mn = parts[1];
  const setH = nh => setTime(nh + ":" + (mn || "00"));
  const setM = nm => setTime((h || "09") + ":" + nm);
  const hourOpts = Array.from({ length: 24 }, (_, i) => ({ value: String(i).padStart(2, "0"), label: (((i % 12) || 12) + ":00 " + (i < 12 ? "AM" : "PM")) }));
  return (
    <Card pad={26}>
      <StepTitle n="03" title="When is it ready for pickup?" sub="Set the date and ready time — pickups run 24 hours a day, in 15-minute steps." />
      {resuming && (
        <div style={{ display: "flex", gap: 9, alignItems: "flex-start", padding: "10px 13px", background: "var(--accent-soft)", borderRadius: "var(--r-sm)", marginBottom: 16 }}>
          <Icon name="info" size={14} color="var(--accent-700)" style={{ flex: "none", marginTop: 1 }} />
          <span style={{ fontSize: 12.5, color: "var(--fg-body)", lineHeight: 1.45 }}>This is a saved booking — set a fresh ready date and time for when it will actually be collected.</span>
        </div>
      )}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
        <Field label="Pickup date"><TextInput type="date" value={date} onChange={setDate} min={window.FX.todayISO()} /></Field>
        <Field label="Ready time">
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <div style={{ flex: 1, minWidth: 0 }}><Select value={h} onChange={setH} placeholder="Select hour" options={hourOpts} /></div>
            <div style={{ display: "flex", gap: 4, flex: "none" }}>
              {["00", "15", "30", "45"].map(x => {
                const on = mn === x;
                return <button key={x} onClick={() => setM(x)} style={{ padding: "9px 11px", borderRadius: "var(--r-sm)", fontFamily: "var(--font-mono)", fontSize: 13, fontWeight: 600, border: "1.5px solid " + (on ? "var(--accent)" : "var(--border)"), background: on ? "var(--accent-soft)" : "var(--surface)", color: on ? "var(--accent-700)" : "var(--fg-body)", transition: "all 140ms ease" }}>:{x}</button>;
              })}
            </div>
          </div>
        </Field>
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 14, flexWrap: "wrap" }}>
        <button onClick={() => setTime(now15())} style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "7px 13px", borderRadius: "var(--r-pill)", fontWeight: 600, fontSize: 12.5, border: "1.5px solid var(--border-strong)", background: "var(--surface)", color: "var(--fg-body)" }}><Icon name="zap" size={13} color="var(--accent)" /> Ready now</button>
        {time && <span style={{ fontSize: 13, color: "var(--fg-mute)" }}>Ready for pickup at <strong style={{ color: "var(--fg-strong)" }}>{fmt12(time)}</strong> · {window.FX.fmtDate(date)}</span>}
      </div>
      {svcWarn && (
        <div style={{ display: "flex", gap: 9, alignItems: "flex-start", padding: "11px 13px", background: "var(--warn-soft)", borderRadius: "var(--r-sm)", marginTop: 16 }}>
          <Icon name="alert-triangle" size={15} color="#a36a00" style={{ flex: "none", marginTop: 1 }} />
          <span style={{ fontSize: 12.5, color: "#8a5a00", lineHeight: 1.45 }}>{svcWarn}</span>
        </div>
      )}
    </Card>
  );
}

/* ---------- Step 4 (interstate): Next Flight air-freight declarations ---------- */
function StepAirFreight({ decl, setD, puState, doState, dgAssessment, items, itemTot }) {
  const dgYes = decl.dg === "yes";
  const dep = window.FX.AIRPORTS[puState], arr = window.FX.AIRPORTS[doState];
  const mins = dep && arr ? window.FX.routeMins(dep.code, arr.code) : null;
  return (
    <Card pad={26}>
      <StepTitle n="04" title="Next Flight declaration" sub="This shipment crosses state lines, so it flies on the next available flight. Tell us what's inside and complete the air-freight declarations below." />

      <div style={{ borderRadius: "var(--r-md)", overflow: "hidden", border: "1px solid var(--border)", marginBottom: 22 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 13, padding: 14, background: "var(--brand)", color: "#fff" }}>
          <span style={{ width: 40, height: 40, borderRadius: 11, flex: "none", display: "inline-flex", alignItems: "center", justifyContent: "center", background: "rgba(255,255,255,0.16)" }}><Icon name="plane" size={20} /></span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 14.5 }}>Interstate · Next Flight air freight</div>
            <div style={{ fontSize: 12.5, opacity: 0.85 }}>Books onto the next available flight — same day, airport to airport, with a courier at each end.</div>
          </div>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr auto 1fr", gap: 10, alignItems: "center", padding: "13px 16px", background: "var(--brand-soft)" }}>
          <div>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.7px", textTransform: "uppercase", color: "var(--fg-mute)" }}>From · {puState}</div>
            <div style={{ fontSize: 13.5, fontWeight: 700, color: "var(--fg-strong)" }}><span style={{ fontFamily: "var(--font-mono)", color: "var(--brand)" }}>{dep ? dep.code : "—"}</span> {dep ? dep.name : ""}</div>
          </div>
          <div style={{ textAlign: "center" }}>
            <Icon name="plane" size={15} color="var(--accent)" />
            {mins != null && <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-mute)", whiteSpace: "nowrap" }}>~{Math.floor(mins / 60)}h{mins % 60 ? " " + (mins % 60) + "m" : ""} in air</div>}
          </div>
          <div style={{ textAlign: "right" }}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.7px", textTransform: "uppercase", color: "var(--fg-mute)" }}>To · {doState}</div>
            <div style={{ fontSize: 13.5, fontWeight: 700, color: "var(--fg-strong)" }}><span style={{ fontFamily: "var(--font-mono)", color: "var(--brand)" }}>{arr ? arr.code : "—"}</span> {arr ? arr.name : ""}</div>
          </div>
        </div>
      </div>

      <div style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-strong)", marginBottom: 12 }}>What are you sending?</div>
      {itemTot && itemTot.count > 0 && (
        <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 13px", background: "var(--bg-mist)", borderRadius: "var(--r-sm)", marginBottom: 14, flexWrap: "wrap" }}>
          <Icon name="package" size={15} color="var(--brand)" />
          <span style={{ fontSize: 12.5, color: "var(--fg-body)" }}>{(items || []).map(it => `${Math.max(1, parseInt(it.qty, 10) || 1)}× ${it.type}${it.l && it.w && it.h ? ` ${it.l}×${it.w}×${it.h} cm` : ""}${it.weight ? ` · ${it.weight} kg` : ""}`).join("   ·   ")}</span>
          <span style={{ marginLeft: "auto", fontFamily: "var(--font-mono)", fontSize: 11.5, color: "var(--fg-mute)" }}>{itemTot.count} item{itemTot.count === 1 ? "" : "s"} · {itemTot.kg} kg — from step 1</span>
        </div>
      )}
      <Field label={<span>Description of goods <span style={{ color: "var(--danger)" }}>*</span></span>} hint="A plain-English description of the item(s) is required for the air manifest — sizes and weights are taken from step 1.">
        <TextInput value={decl.desc} onChange={v => setD("desc", v)} placeholder="e.g. Printed brochures — 2 cartons" />
      </Field>

      <div style={{ borderTop: "1px solid var(--border)", marginTop: 22, paddingTop: 20 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
          <Icon name="alert-triangle" size={18} color="var(--accent-700)" />
          <span style={{ fontSize: 16, fontWeight: 700, color: "var(--fg-strong)" }}>Dangerous goods</span>
        </div>
        <div style={{ fontSize: 14, color: "var(--fg-body)", marginBottom: 12 }}>Does your shipment contain any dangerous goods? <span style={{ color: "var(--danger)" }}>*</span></div>
        <div style={{ display: "flex", gap: 10, maxWidth: 300 }}>
          {[["no", "No"], ["yes", "Yes"]].map(([val, lbl]) => {
            const on = decl.dg === val;
            return (
              <button key={val} onClick={() => setD("dg", val)} style={{
                flex: 1, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 9, padding: "12px 14px", borderRadius: "var(--r-md)",
                border: "1.5px solid " + (on ? "var(--accent)" : "var(--border-strong)"), background: on ? "var(--accent-soft)" : "var(--surface)",
                color: on ? "var(--accent-700)" : "var(--fg-body)", fontSize: 14.5, fontWeight: 600, transition: "all 140ms ease",
              }}>
                <span style={{ width: 18, height: 18, borderRadius: "50%", flex: "none", border: "2px solid " + (on ? "var(--accent)" : "var(--border-strong)"), display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{on && <span style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--accent)" }} />}</span>
                {lbl}
              </button>
            );
          })}
        </div>

        {dgYes && (
          <div className="fade-up" style={{ marginTop: 16 }}>
            <Field label={<span>Type of dangerous goods <span style={{ color: "var(--danger)" }}>*</span></span>}>
              <Select value={decl.dgType} onChange={v => setD("dgType", v)} placeholder="Please select" options={window.FX.DANGEROUS_GOODS} />
            </Field>
            <div style={{ display: "grid", gridTemplateColumns: "110px 1fr 1fr", gap: 12, marginTop: 14 }}>
              <Field label={<span>Packages <span style={{ color: "var(--danger)" }}>*</span></span>}><TextInput type="number" value={decl.dgPackages} onChange={v => setD("dgPackages", v)} mono /></Field>
              <Field label="Net quantity per package"><TextInput value={decl.dgNetQty} onChange={v => setD("dgNetQty", v)} placeholder="e.g. 2.5 kg / 100 Wh" mono /></Field>
              <Field label={<span>24-hr emergency contact <span style={{ color: "var(--danger)" }}>*</span></span>}><TextInput value={decl.dgEmergency} onChange={v => setD("dgEmergency", v)} placeholder="+61 4XX XXX XXX" mono /></Field>
            </div>
            {dgAssessment && (
              dgAssessment.status === "accept" ? (
                <div style={{ display: "flex", gap: 9, marginTop: 14, padding: "11px 13px", background: "color-mix(in srgb, var(--success, #1f8a5b), white 92%)", border: "1px solid var(--success, #1f8a5b)", borderRadius: "var(--r-sm)", lineHeight: 1.45 }}>
                  <Icon name="check-circle" size={15} color="var(--success, #1f8a5b)" style={{ flex: "none", marginTop: 1 }} />
                  <span style={{ fontSize: 12.5, color: "var(--fg-body)" }}><strong style={{ color: "var(--success, #1f8a5b)" }}>Within limited quantities — accepted for air transport.</strong> {dgAssessment.reason}</span>
                </div>
              ) : (
                <div style={{ display: "flex", gap: 9, marginTop: 14, padding: "11px 13px", background: "color-mix(in srgb, var(--danger), white 93%)", border: "1px solid var(--danger)", borderRadius: "var(--r-sm)", lineHeight: 1.45 }}>
                  <Icon name="alert-triangle" size={15} color="var(--danger)" style={{ flex: "none", marginTop: 1 }} />
                  <span style={{ fontSize: 12.5, color: "var(--fg-body)" }}><strong style={{ color: "var(--danger)" }}>This can't be booked online.</strong> {dgAssessment.reason} Call Customer Service on <strong>1300 131 150</strong> to have this shipment checked for travel.</span>
                </div>
              )
            )}
            <button onClick={() => setD("dgShipperDecl", !decl.dgShipperDecl)} style={{ display: "flex", gap: 12, alignItems: "flex-start", marginTop: 14, background: decl.dgShipperDecl ? "var(--brand-soft)" : "var(--surface)", border: "1.5px solid " + (decl.dgShipperDecl ? "var(--brand)" : "var(--border)"), borderRadius: "var(--r-md)", padding: "13px 14px", textAlign: "left", width: "100%", transition: "all 140ms ease" }}>
              <span style={{ width: 22, height: 22, borderRadius: 6, flex: "none", marginTop: 1, border: "1.5px solid " + (decl.dgShipperDecl ? "var(--brand)" : "var(--border-strong)"), background: decl.dgShipperDecl ? "var(--brand)" : "transparent", display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{decl.dgShipperDecl && <Icon name="check" size={14} color="#fff" />}</span>
              <span style={{ fontSize: 13, color: "var(--fg-body)", lineHeight: 1.55 }}><strong>Shipper's declaration.</strong> I declare that the contents of this consignment are fully and accurately described above by proper shipping name, and are classified, packaged, marked and labelled, and in all respects in proper condition for transport by air under the IATA Dangerous Goods Regulations and the Australian ADG Code. <span style={{ color: "var(--danger)" }}>*</span></span>
            </button>
          </div>
        )}

        {decl.dg === "no" && (
          <button className="fade-up" onClick={() => setD("noDgAck", !decl.noDgAck)} style={{ display: "flex", gap: 12, alignItems: "flex-start", marginTop: 16, background: decl.noDgAck ? "var(--brand-soft)" : "var(--surface)", border: "1.5px solid " + (decl.noDgAck ? "var(--brand)" : "var(--border)"), borderRadius: "var(--r-md)", padding: "13px 14px", textAlign: "left", width: "100%", transition: "all 140ms ease" }}>
            <span style={{ width: 22, height: 22, borderRadius: 6, flex: "none", marginTop: 1, border: "1.5px solid " + (decl.noDgAck ? "var(--brand)" : "var(--border-strong)"), background: decl.noDgAck ? "var(--brand)" : "transparent", display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{decl.noDgAck && <Icon name="check" size={14} color="#fff" />}</span>
            <span style={{ fontSize: 13, color: "var(--fg-body)", lineHeight: 1.55 }}>I declare this shipment contains <strong>no dangerous or prohibited goods</strong> — including hidden dangerous goods such as aerosols, perfumes, lithium batteries or devices containing them, and dry ice. <span style={{ color: "var(--danger)" }}>*</span></span>
          </button>
        )}
      </div>

      <div style={{ borderTop: "1px solid var(--border)", marginTop: 22, paddingTop: 20 }}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 150px", gap: 12, marginBottom: 14 }}>
          <Field label={<span>Declared by (full name) <span style={{ color: "var(--danger)" }}>*</span></span>} hint="The person making this declaration, as the shipper or their authorised agent.">
            <TextInput value={decl.declaredBy} onChange={v => setD("declaredBy", v)} placeholder="e.g. Priya Sharma" />
          </Field>
          <Field label="Date"><TextInput value={window.FX.fmtDate(window.FX.todayISO())} onChange={() => {}} readOnly mono /></Field>
        </div>
        <button onClick={() => setD("agree", !decl.agree)} style={{ display: "flex", gap: 12, alignItems: "flex-start", background: decl.agree ? "var(--brand-soft)" : "var(--surface)", border: "1.5px solid " + (decl.agree ? "var(--brand)" : "var(--border)"), borderRadius: "var(--r-md)", padding: "14px 15px", textAlign: "left", width: "100%", transition: "all 140ms ease" }}>
          <span style={{ width: 22, height: 22, borderRadius: 6, flex: "none", marginTop: 1, border: "1.5px solid " + (decl.agree ? "var(--brand)" : "var(--border-strong)"), background: decl.agree ? "var(--brand)" : "transparent", display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{decl.agree && <Icon name="check" size={14} color="#fff" />}</span>
          <span style={{ fontSize: 13.5, color: "var(--fg-body)", lineHeight: 1.5 }}>
            I declare the contents are accurately described and correctly packaged for air transport, and I accept the <a href="#" onClick={e => e.preventDefault()} style={{ color: "var(--accent-700)", fontWeight: 600 }}>Next Flight air freight terms &amp; conditions</a>, including air-cargo security and dangerous-goods obligations. <span style={{ color: "var(--danger)" }}>*</span>
          </span>
        </button>
        {(() => {
          const missing = [];
          if (!decl.desc.trim()) missing.push("description of goods");
          if (decl.dg == null) missing.push("dangerous-goods answer");
          if (decl.dg === "no" && !decl.noDgAck) missing.push("no-DG declaration");
          if (decl.dg === "yes") {
            if (!decl.dgType) missing.push("DG type");
            if (!(decl.dgEmergency || "").trim()) missing.push("24-hr emergency contact");
            if (!decl.dgShipperDecl) missing.push("shipper's declaration");
            if (dgAssessment && dgAssessment.status !== "accept") missing.push("Customer Service check — can't continue online");
          }
          if (!(decl.declaredBy || "").trim()) missing.push("declarant name");
          if (!decl.agree) missing.push("terms acceptance");
          return missing.length ? <div style={{ fontSize: 12, color: "var(--fg-mute)", marginTop: 12 }}>Still needed to continue: {missing.join(" · ")}.</div> : null;
        })()}
      </div>
    </Card>
  );
}

/* ---------- Step 4: Return ---------- */
function StepReturn({ isReturn, setIsReturn, pickup, dropoff }) {
  return (
    <Card pad={26}>
      <StepTitle n="04" title="Return trip" sub="Need the driver to come back? Add a return leg at a 15% discount." />
      <div style={{ display: "flex", flexDirection: "column", gap: 11 }}>
        {[{ v: false, t: "One-way delivery", d: "Driver completes the drop-off and the job is done." },
          { v: true, t: "Return trip", d: "After delivering, the driver returns to the pickup point." }].map(o => {
          const active = isReturn === o.v;
          return (
            <button key={String(o.v)} onClick={() => setIsReturn(o.v)} style={{
              display: "flex", alignItems: "center", gap: 14, textAlign: "left", width: "100%",
              border: "1.5px solid " + (active ? "var(--accent)" : "var(--border)"), borderRadius: "var(--r-lg)",
              background: active ? "var(--accent-soft)" : "var(--surface)", padding: "16px 18px", transition: "all 160ms ease",
            }}>
              <span style={{ width: 40, height: 40, borderRadius: 11, flex: "none", display: "inline-flex", alignItems: "center", justifyContent: "center", background: active ? "var(--accent)" : "var(--brand-soft)", color: active ? "#fff" : "var(--brand)" }}>
                <Icon name={o.v ? "repeat" : "arrow-right"} size={20} />
              </span>
              <span style={{ flex: 1 }}>
                <span style={{ display: "block", fontWeight: 700, fontSize: 15.5, color: "var(--fg-strong)" }}>{o.t}</span>
                <span style={{ display: "block", fontSize: 13, color: "var(--fg-mute)", marginTop: 3 }}>{o.d}</span>
              </span>
              {active && <Icon name="check-circle" size={20} color="var(--accent)" />}
            </button>
          );
        })}
      </div>
      {isReturn && pickup && dropoff && (
        <div style={{ marginTop: 16, padding: 14, background: "var(--brand-soft)", borderRadius: "var(--r-md)", display: "flex", alignItems: "center", gap: 10, fontSize: 13.5, color: "var(--brand)" }}>
          <Icon name="repeat" size={16} />
          <span>Return route: <strong>{dropoff.suburb}</strong> back to <strong>{pickup.suburb}</strong></span>
        </div>
      )}
    </Card>
  );
}

/* ---------- Step 6: Details (account + references) ---------- */
function StepDetails({ accounts, accountId, setAccountId, ref1, setRef1, ref2, setRef2, decl, setD, dgAssessment, isInterstate }) {
  const dgBlockedStd = decl && decl.dg === "yes" && dgAssessment && dgAssessment.status === "blocked";
  return (
    <Card pad={26}>
      <StepTitle n="05" title="Account & references" sub="Choose which account to bill, and add your own reference numbers for this delivery." />
      <div style={{ fontSize: 13, fontWeight: 500, color: "var(--fg-strong)", marginBottom: 9 }}>Billing account</div>
      <div style={{ display: "flex", flexDirection: "column", gap: 9, marginBottom: 22 }}>
        {accounts.map(a => {
          const active = a.id === accountId;
          return (
            <button key={a.id} onClick={() => setAccountId(a.id)} style={{
              display: "flex", alignItems: "center", gap: 13, textAlign: "left", width: "100%",
              border: "1.5px solid " + (active ? "var(--accent)" : "var(--border)"), borderRadius: "var(--r-lg)",
              background: active ? "var(--accent-soft)" : "var(--surface)", padding: "14px 16px", transition: "all 160ms ease",
            }}>
              <span style={{ width: 22, height: 22, borderRadius: "50%", flex: "none", border: "2px solid " + (active ? "var(--accent)" : "var(--border-strong)"), display: "inline-flex", alignItems: "center", justifyContent: "center" }}>
                {active && <span style={{ width: 10, height: 10, borderRadius: "50%", background: "var(--accent)" }} />}
              </span>
              <span style={{ width: 38, height: 38, borderRadius: 10, flex: "none", display: "inline-flex", alignItems: "center", justifyContent: "center", background: "var(--brand-soft)", color: "var(--brand)" }}><Icon name="wallet" size={18} /></span>
              <span style={{ flex: 1, minWidth: 0 }}>
                <span style={{ display: "block", fontWeight: 600, fontSize: 14.5, color: "var(--fg-strong)" }}>{a.name}</span>
                <span style={{ display: "block", fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-mute)", marginTop: 2 }}>{a.number} · {a.type}</span>
              </span>
            </button>
          );
        })}
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <Field label="Reference number" hint="Your PO, order or job number"><TextInput value={ref1} onChange={setRef1} placeholder="e.g. PO-48213" mono /></Field>
        <Field label="Second reference" hint="Optional"><TextInput value={ref2} onChange={setRef2} placeholder="e.g. Cost centre 2200" mono /></Field>
      </div>

      {!isInterstate && decl && (
        <div style={{ marginTop: 22, borderTop: "1px solid var(--border)", paddingTop: 20 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 5 }}>
            <Icon name="alert-triangle" size={17} color="var(--accent-700)" />
            <span style={{ fontSize: 16, fontWeight: 700, color: "var(--fg-strong)" }}>Dangerous goods</span>
            <span style={{ color: "var(--danger)" }}>*</span>
          </div>
          <div style={{ fontSize: 14, color: "var(--fg-body)", marginBottom: 12 }}>Does your shipment contain any dangerous goods?</div>
          <div style={{ display: "flex", gap: 10, maxWidth: 300 }}>
            {[["no", "No"], ["yes", "Yes"]].map(([val, lbl]) => {
              const on = decl.dg === val;
              return (
                <button key={val} onClick={() => setD("dg", val)} style={{ flex: 1, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 9, padding: "12px 14px", borderRadius: "var(--r-md)", border: "1.5px solid " + (on ? "var(--accent)" : "var(--border-strong)"), background: on ? "var(--accent-soft)" : "var(--surface)", color: on ? "var(--accent-700)" : "var(--fg-body)", fontSize: 14.5, fontWeight: 600, transition: "all 140ms ease" }}>
                  <span style={{ width: 18, height: 18, borderRadius: "50%", flex: "none", border: "2px solid " + (on ? "var(--accent)" : "var(--border-strong)"), display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{on && <span style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--accent)" }} />}</span>
                  {lbl}
                </button>
              );
            })}
          </div>

          {decl.dg === "no" && (
            <button className="fade-up" onClick={() => setD("noDgAck", !decl.noDgAck)} style={{ display: "flex", gap: 12, alignItems: "flex-start", marginTop: 14, background: decl.noDgAck ? "var(--brand-soft)" : "var(--surface)", border: "1.5px solid " + (decl.noDgAck ? "var(--brand)" : "var(--border)"), borderRadius: "var(--r-md)", padding: "13px 14px", textAlign: "left", width: "100%", transition: "all 140ms ease" }}>
              <span style={{ width: 22, height: 22, borderRadius: 6, flex: "none", marginTop: 1, border: "1.5px solid " + (decl.noDgAck ? "var(--brand)" : "var(--border-strong)"), background: decl.noDgAck ? "var(--brand)" : "transparent", display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{decl.noDgAck && <Icon name="check" size={14} color="#fff" />}</span>
              <span style={{ fontSize: 13, color: "var(--fg-body)", lineHeight: 1.55 }}>I declare this shipment contains <strong>no dangerous or prohibited goods</strong> — including hidden dangerous goods such as aerosols, perfumes, lithium batteries or devices containing them, and dry ice. <span style={{ color: "var(--danger)" }}>*</span></span>
            </button>
          )}

          {decl.dg === "yes" && (
            <div className="fade-up" style={{ marginTop: 14 }}>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 110px", gap: 12 }}>
                <Field label={<span>Type of dangerous goods <span style={{ color: "var(--danger)" }}>*</span></span>}><Select value={decl.dgType} onChange={v => setD("dgType", v)} placeholder="Please select" options={window.FX.DANGEROUS_GOODS} /></Field>
                <Field label={<span>Packages <span style={{ color: "var(--danger)" }}>*</span></span>}><TextInput type="number" value={decl.dgPackages} onChange={v => setD("dgPackages", v)} mono /></Field>
              </div>
              {decl.dgType && dgAssessment && (
                dgAssessment.status === "accept" ? (
                  <div style={{ display: "flex", gap: 9, marginTop: 12, padding: "11px 13px", background: "color-mix(in srgb, var(--success, #1f8a5b), white 92%)", border: "1px solid var(--success, #1f8a5b)", borderRadius: "var(--r-sm)", lineHeight: 1.45 }}>
                    <Icon name="check-circle" size={15} color="var(--success, #1f8a5b)" style={{ flex: "none", marginTop: 1 }} />
                    <span style={{ fontSize: 12.5, color: "var(--fg-body)" }}><strong style={{ color: "var(--success, #1f8a5b)" }}>Within accepted quantities.</strong> {dgAssessment.reason}</span>
                  </div>
                ) : (
                  <div style={{ display: "flex", gap: 9, marginTop: 12, padding: "11px 13px", background: "color-mix(in srgb, var(--danger), white 93%)", border: "1px solid var(--danger)", borderRadius: "var(--r-sm)", lineHeight: 1.45 }}>
                    <Icon name="alert-triangle" size={15} color="var(--danger)" style={{ flex: "none", marginTop: 1 }} />
                    <span style={{ fontSize: 12.5, color: "var(--fg-body)" }}><strong style={{ color: "var(--danger)" }}>This can't be booked online.</strong> {dgAssessment.reason} Call Customer Service on <strong>1300 131 150</strong>.</span>
                  </div>
                )
              )}
              <button onClick={() => setD("dgShipperDecl", !decl.dgShipperDecl)} style={{ display: "flex", gap: 12, alignItems: "flex-start", marginTop: 12, background: decl.dgShipperDecl ? "var(--brand-soft)" : "var(--surface)", border: "1.5px solid " + (decl.dgShipperDecl ? "var(--brand)" : "var(--border)"), borderRadius: "var(--r-md)", padding: "13px 14px", textAlign: "left", width: "100%", transition: "all 140ms ease" }}>
                <span style={{ width: 22, height: 22, borderRadius: 6, flex: "none", marginTop: 1, border: "1.5px solid " + (decl.dgShipperDecl ? "var(--brand)" : "var(--border-strong)"), background: decl.dgShipperDecl ? "var(--brand)" : "transparent", display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{decl.dgShipperDecl && <Icon name="check" size={14} color="#fff" />}</span>
                <span style={{ fontSize: 13, color: "var(--fg-body)", lineHeight: 1.55 }}>I declare the contents are accurately described and are packaged, marked and labelled in proper condition for transport under the applicable dangerous-goods regulations. <span style={{ color: "var(--danger)" }}>*</span></span>
              </button>
            </div>
          )}
        </div>
      )}
    </Card>
  );
}

/* ---------- Step 7: Notify ---------- */
function StepNotify({ notify, setNotify, pickup, dropoff, isReturn }) {
  const toggle = (k) => setNotify({ ...notify, [k]: !notify[k] });
  const masterToggle = (k) => setNotify({ ...notify, [k]: notify[k] === false ? true : false });
  const [xName, setXName] = useStateBk("");
  const [xEmail, setXEmail] = useStateBk("");
  const [xPhone, setXPhone] = useStateBk("");
  const emailOk = !xEmail.trim() || /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(xEmail.trim());
  const canAdd = !!(xEmail.trim() || xPhone.trim()) && emailOk;
  const addPerson = () => { if (!canAdd) return; setNotify({ ...notify, extra: [...(notify.extra || []), { name: xName.trim(), email: xEmail.trim(), phone: xPhone.trim() }] }); setXName(""); setXEmail(""); setXPhone(""); };
  const removePerson = (i) => setNotify({ ...notify, extra: (notify.extra || []).filter((_, idx) => idx !== i) });
  const Row = ({ who, contact, onK, smsK, emailK }) => {
    const on = notify[onK] !== false;
    return (
    <div style={{ border: "1px solid var(--border)", borderRadius: "var(--r-lg)", padding: 16, opacity: on ? 1 : 0.72 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 11, marginBottom: on ? 13 : 0 }}>
        <Icon name="user" size={16} color="var(--brand)" />
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={{ fontWeight: 600, fontSize: 14.5, color: "var(--fg-strong)" }}>{who}</div>
          <div style={{ fontSize: 12, color: "var(--fg-mute)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{contact && contact.contact ? contact.contact : "—"}{on ? "" : " · notifications off"}</div>
        </div>
        <button onClick={() => masterToggle(onK)} title={on ? "Turn notifications off" : "Turn notifications on"} style={{ flex: "none", background: "none", border: "none", cursor: "pointer", padding: 0, display: "inline-flex" }}>
          <span style={{ width: 40, height: 23, borderRadius: 999, display: "inline-block", background: on ? "var(--brand)" : "var(--bg-mist-2)", position: "relative", transition: "all 160ms ease" }}>
            <span style={{ position: "absolute", top: 2, left: on ? 19 : 2, width: 19, height: 19, borderRadius: "50%", background: "#fff", transition: "all 160ms ease" }} />
          </span>
        </button>
      </div>
      {on && (
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
          <NotifyToggle icon="message-square" label="SMS" sub={contact && contact.phone ? contact.phone : "Text updates"} on={notify[smsK]} onClick={() => toggle(smsK)} />
          <NotifyToggle icon="mail" label="Email" sub="Status updates" on={notify[emailK]} onClick={() => toggle(emailK)} />
        </div>
      )}
    </div>
    );
  };
  return (
    <Card pad={26}>
      <StepTitle n="06" title="Notifications" sub="Turn notifications on or off for each contact, and choose whether they get SMS, email, or both." />
      <div style={{ display: "flex", flexDirection: "column", gap: 13 }}>
        <Row who="Pickup contact" contact={pickup} onK="pickupOn" smsK="pickupSms" emailK="pickupEmail" />
        <Row who="Recipient" contact={dropoff} onK="recipOn" smsK="recipSms" emailK="recipEmail" />
        {isReturn && <Row who="Return contact" contact={pickup} onK="returnOn" smsK="returnSms" emailK="returnEmail" />}
      </div>

      <div style={{ marginTop: 18, borderTop: "1px solid var(--border)", paddingTop: 18 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 4 }}>
          <Icon name="user-plus" size={16} color="var(--brand)" />
          <span style={{ fontWeight: 600, fontSize: 14.5, color: "var(--fg-strong)" }}>Also notify someone else</span>
        </div>
        <div style={{ fontSize: 12.5, color: "var(--fg-mute)", marginBottom: 12 }}>Add another person — a manager, the receiver's assistant — by email, mobile, or both. They'll get the same status updates for this booking.</div>

        {(notify.extra || []).length > 0 && (
          <div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 12 }}>
            {notify.extra.map((p, i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 13px", background: "var(--bg-mist)", borderRadius: "var(--r-md)" }}>
                <span style={{ width: 30, height: 30, borderRadius: "50%", flex: "none", background: "var(--brand)", color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", fontWeight: 700, fontSize: 11 }}>{(p.name || p.email || p.phone || "?").replace(/[^A-Za-z0-9]/g, "").slice(0, 2).toUpperCase() || "?"}</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--fg-strong)" }}>{p.name || "Extra contact"}</div>
                  <div style={{ fontSize: 12, color: "var(--fg-mute)", fontFamily: "var(--font-mono)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{[p.email, p.phone].filter(Boolean).join(" · ")}</div>
                </div>
                <span style={{ display: "inline-flex", gap: 7, flex: "none", color: "var(--brand)" }}>
                  {p.email && <Icon name="mail" size={15} />}
                  {p.phone && <Icon name="message-square" size={15} />}
                </span>
                <button onClick={() => removePerson(i)} title="Remove" style={{ flex: "none", width: 26, height: 26, borderRadius: "50%", border: "none", background: "var(--surface)", color: "var(--fg-mute)", display: "inline-flex", alignItems: "center", justifyContent: "center", cursor: "pointer" }}><Icon name="x" size={13} /></button>
              </div>
            ))}
          </div>
        )}

        <div style={{ display: "grid", gridTemplateColumns: "1fr 1.25fr 1fr auto", gap: 9, alignItems: "end" }}>
          <Field label="Name (optional)"><TextInput value={xName} onChange={setXName} placeholder="e.g. Ops manager" /></Field>
          <Field label="Email"><TextInput value={xEmail} onChange={setXEmail} placeholder="name@company.com.au" /></Field>
          <Field label="Mobile (SMS)"><TextInput value={xPhone} onChange={setXPhone} placeholder="+61 4XX XXX XXX" mono /></Field>
          <Button variant="secondary" icon="plus" disabled={!canAdd} onClick={addPerson}>Add</Button>
        </div>
        {!emailOk && <div style={{ fontSize: 11.5, color: "var(--danger)", marginTop: 7 }}>That email doesn't look right — check it and try again.</div>}
      </div>
    </Card>
  );
}
function NotifyToggle({ icon, label, sub, on, onClick }) {
  return (
    <button onClick={onClick} style={{
      display: "flex", alignItems: "center", gap: 11, textAlign: "left", width: "100%",
      border: "1.5px solid " + (on ? "var(--brand)" : "var(--border)"), borderRadius: "var(--r-md)",
      background: on ? "var(--brand-soft)" : "var(--surface)", padding: "12px 14px", transition: "all 140ms ease",
    }}>
      <span style={{ width: 34, height: 34, borderRadius: 9, flex: "none", display: "inline-flex", alignItems: "center", justifyContent: "center", background: on ? "var(--brand)" : "var(--bg-mist)", color: on ? "#fff" : "var(--fg-mute)" }}>
        <Icon name={icon} size={17} />
      </span>
      <span style={{ flex: 1, minWidth: 0 }}>
        <span style={{ display: "block", fontWeight: 600, fontSize: 14, color: "var(--fg-strong)" }}>{label}</span>
        <span style={{ display: "block", fontSize: 11.5, color: "var(--fg-mute)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{sub}</span>
      </span>
      <span style={{ width: 38, height: 22, borderRadius: 999, flex: "none", background: on ? "var(--brand)" : "var(--bg-mist-2)", position: "relative", transition: "all 160ms ease" }}>
        <span style={{ position: "absolute", top: 2, left: on ? 18 : 2, width: 18, height: 18, borderRadius: "50%", background: "#fff", transition: "all 160ms ease", boxShadow: "var(--shadow-xs)" }} />
      </span>
    </button>
  );
}

/* ---------- Step 8: Review ---------- */
function StepReview({ vehicleId, pickup, dropoff, stops, date, time, serviceId, isReturn, notify, q, km, currency, account, ref1, ref2, isInterstate, decl, itemTot }) {
  const v = window.FX.VEHICLES.find(x => x.id === vehicleId);
  const s = window.FX.SERVICES.find(x => x.id === serviceId);
  const puState = window.FX.suburbState(pickup.suburb);
  const doState = window.FX.suburbState(dropoff.suburb);
  const dgLabel = decl && decl.dgType ? (window.FX.DANGEROUS_GOODS.find(d => d.value === decl.dgType) || {}).label : "";
  const ap1 = window.FX.AIRPORTS[puState], ap2 = window.FX.AIRPORTS[doState];
  const chans = [];
  const pOn = notify.pickupOn !== false, rOn = notify.recipOn !== false, retOn = notify.returnOn !== false;
  if (pOn && notify.pickupSms) chans.push("Pickup SMS"); if (pOn && notify.pickupEmail) chans.push("Pickup email");
  if (rOn && notify.recipSms) chans.push("Recipient SMS"); if (rOn && notify.recipEmail) chans.push("Recipient email");
  if (isReturn && retOn && notify.returnSms) chans.push("Return SMS"); if (isReturn && retOn && notify.returnEmail) chans.push("Return email");
  const Line = ({ label, children }) => (
    <div style={{ display: "flex", justifyContent: "space-between", gap: 16, padding: "11px 0", borderTop: "1px solid var(--border)" }}>
      <span style={{ fontSize: 13.5, color: "var(--fg-mute)" }}>{label}</span>
      <span style={{ fontSize: 13.5, color: "var(--fg-strong)", fontWeight: 500, textAlign: "right" }}>{children}</span>
    </div>
  );
  return (
    <Card pad={26}>
      <StepTitle n="07" title="Review & confirm" sub="Check everything below, then place your booking." />
      <div style={{ display: "flex", alignItems: "center", gap: 13, padding: 14, background: "var(--brand-soft)", borderRadius: "var(--r-md)", marginBottom: 6 }}>
        <VehicleGlyph icon={v.icon} active />
        <div style={{ flex: 1 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontWeight: 700, fontSize: 15.5, color: "var(--fg-strong)" }}>{s.name} {v.name}</span>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 600, color: "var(--accent-700)", background: "var(--accent-soft)", padding: "2px 7px", borderRadius: 5 }}>{window.FX.serviceCode(serviceId, vehicleId)}</span>
          </div>
          <div style={{ fontSize: 13, color: "var(--fg-mute)" }}>{pickup.suburb} → {dropoff.suburb} · {km} km{isReturn ? " · return" : ""}</div>
        </div>
      </div>
      <div style={{ marginTop: 8 }}>
        <Line label="Account">{account ? account.name : "—"} · <span className="mono" style={{ fontSize: 12.5 }}>{account ? account.number : ""}</span></Line>
        {stops.map((st, i) => {
          const role = i === 0 ? "Pickup" : (stops.length > 2 ? `Drop-off ${i}` : "Drop-off");
          return (
            <React.Fragment key={i}>
              <Line label={role}>{(st.company || st.contact || st.label || "—")} · {st.suburb}{i === 0 ? ` · ${window.FX.fmtDate(date)} ${time}` : ""}</Line>
              {st.instructions && <Line label={(i === 0 ? "Pickup" : "Delivery") + " notes"}>{st.instructions}</Line>}
            </React.Fragment>
          );
        })}
        <Line label="Service">{s.name} {v.name} · <span className="mono">{window.FX.serviceCode(serviceId, vehicleId)}</span> · {s.eta}</Line>
        {isInterstate ? (
          <React.Fragment>
            <Line label="Delivery">Next Flight air freight · <span className="mono">{ap1 ? ap1.code : puState}</span> {ap1 ? ap1.city : ""} → <span className="mono">{ap2 ? ap2.code : doState}</span> {ap2 ? ap2.city : ""}</Line>
            <Line label="Goods">{decl.desc || "—"}</Line>
            {itemTot && itemTot.count > 0 && <Line label="Items">{itemTot.count} item{itemTot.count === 1 ? "" : "s"} · {itemTot.kg} kg</Line>}
            <Line label="Dangerous goods">{decl.dg === "yes" ? (dgLabel || "Declared") : "None — incl. hidden DG"}</Line>
            {decl.dg === "yes" && <Line label="DG detail">{decl.dgPackages || "1"} pkg{String(decl.dgPackages || "1") === "1" ? "" : "s"}{decl.dgNetQty ? ` · ${decl.dgNetQty} net each` : ""} · 24-hr contact {decl.dgEmergency || "—"}</Line>}
            {decl.declaredBy && <Line label="Declared by">{decl.declaredBy} · {window.FX.fmtDate(window.FX.todayISO())}</Line>}
          </React.Fragment>
        ) : (
          <React.Fragment>
            <Line label="Return trip">{isReturn ? "Yes — 15% discounted" : "No"}</Line>
            <Line label="Dangerous goods">{decl.dg === "yes" ? (dgLabel || "Declared") : "None — incl. hidden DG"}</Line>
          </React.Fragment>
        )}
        {(ref1 || ref2) && <Line label="References">{[ref1, ref2].filter(Boolean).join(" · ")}</Line>}
        <Line label="Notifications">{chans.length ? chans.join(" · ") : "None"}</Line>
        {notify.extra && notify.extra.length > 0 && <Line label="Also notified">{notify.extra.map(p => p.name || p.email || p.phone).join(" · ")}</Line>}
      </div>
      <FinePrint />
    </Card>
  );
}

/* ---------- Legal fine print (shown below the booking at placement) ---------- */
function FinePrint() {
  const paras = window.FX.BOOKING_DISCLAIMER || [];
  const url = "tnt.com/surcharges";
  const ps = { margin: 0, fontSize: 11.5, lineHeight: 1.55, color: "var(--fg-mute)" };
  return (
    <div style={{ marginTop: 22, paddingTop: 16, borderTop: "1px solid var(--border)", display: "flex", flexDirection: "column", gap: 8 }}>
      {paras.map((p, i) => {
        if (p.includes(url)) {
          const parts = p.split(url);
          return <p key={i} style={ps}>{parts[0]}<a href={"https://" + url} target="_blank" rel="noopener" style={{ color: "var(--accent-700)", textDecoration: "underline" }}>{url}</a>{parts[1]}</p>;
        }
        return <p key={i} style={ps}>{p}</p>;
      })}
    </div>
  );
}

/* ---------- Shared bits ---------- */
function StepTitle({ n, title, sub }) {
  return (
    <div style={{ marginBottom: 20 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, fontWeight: 600, color: "var(--accent-700)", letterSpacing: "1px" }}>{n}</span>
        <h2 style={{ margin: 0, fontSize: 21, fontWeight: 700, letterSpacing: "-0.5px", color: "var(--fg-strong)" }}>{title}</h2>
      </div>
      {sub && <p style={{ margin: "7px 0 0", fontSize: 14, color: "var(--fg-mute)" }}>{sub}</p>}
    </div>
  );
}

function SummaryRail({ vehicleId, pickup, dropoff, stops, date, time, serviceId, isReturn, q, km, currency, account, ref1, isInterstate, showPrice, deliveryType }) {
  const v = vehicleId && window.FX.VEHICLES.find(x => x.id === vehicleId);
  const s = window.FX.SERVICES.find(x => x.id === serviceId);
  const filled = (stops || []).filter(x => x && x.suburb);
  const routeStr = filled.length >= 2 ? filled.map(x => x.suburb).join(" → ") : "Set addresses";
  return (
    <div style={{ position: "sticky", top: 24 }}>
      <Card pad={0} style={{ overflow: "hidden" }}>
        <div style={{ background: "var(--brand)", color: "#fff", padding: "18px 20px" }}>
          <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "1.4px", opacity: 0.7, textTransform: "uppercase" }}>{showPrice ? "Total" : "Your booking"}</div>
          {showPrice ? (
            <React.Fragment>
              <div style={{ display: "flex", alignItems: "baseline", gap: 8, marginTop: 6 }}>
                <span style={{ fontSize: 38, fontWeight: 900, letterSpacing: "-1.5px" }}>{q ? window.FX.money(q.total, currency) : "—"}</span>
              </div>
              <div style={{ fontSize: 12, opacity: 0.7, marginTop: 2 }}>incl. GST{isReturn ? " · return included" : ""}</div>
            </React.Fragment>
          ) : (
            <div style={{ display: "flex", alignItems: "flex-start", gap: 10, marginTop: 8 }}>
              <Icon name="calculator" size={18} color="#fff" style={{ flex: "none", marginTop: 2, opacity: 0.9 }} />
              <span style={{ fontSize: 13.5, fontWeight: 500, lineHeight: 1.4, opacity: 0.92 }}>Your price is calculated once every option is set — you'll see it at review.</span>
            </div>
          )}
        </div>
        <div style={{ padding: "16px 20px" }}>
          <SumRow icon={v ? v.icon : "package"} label="Size" value={v ? v.name : "Not selected"} />
          <SumRow icon="map-pin" label="Route" value={routeStr} mono />
          <SumRow icon="navigation" label="Distance" value={km != null ? km + " km" : "—"} />
          <SumRow icon="clock" label="Pickup" value={time ? `${window.FX.fmtDate(date)} · ${time}` : "Not set"} />
          <SumRow icon="zap" label="Service" value={v ? `${s.name} (${window.FX.serviceCode(serviceId, v.id)})` : s.name} />
          <SumRow icon={deliveryType === "nextflight" ? "plane" : "truck"} label="Type" value={deliveryType === "nextflight" ? "Next Flight air" : "Standard courier"} />
          {account && <SumRow icon="wallet" label="Account" value={account.name} />}
          {ref1 && <SumRow icon="info" label="Ref" value={ref1} mono />}
          {showPrice && q && (
            <div style={{ marginTop: 12, paddingTop: 12, borderTop: "1px dashed var(--border)" }}>
              <MiniLine label="One-way" value={window.FX.money(q.oneWay, currency)} />
              {isReturn && <MiniLine label="Return (−15%)" value={window.FX.money(q.returnLeg, currency)} />}
              <MiniLine label="GST (10%)" value={window.FX.money(q.gst, currency)} />
            </div>
          )}
        </div>
      </Card>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 14, padding: "0 4px", fontSize: 12, color: "var(--fg-mute)" }}>
        <Icon name="shield-check" size={15} color="var(--success)" /> Price locked at booking · no surge fees
      </div>
    </div>
  );
}
function SumRow({ icon, label, value, mono }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 11, padding: "7px 0" }}>
      <Icon name={icon} size={16} color="var(--fg-faint)" />
      <span style={{ fontSize: 13, color: "var(--fg-mute)", flex: "none", width: 64 }}>{label}</span>
      <span style={{ fontSize: 13, fontWeight: 500, color: "var(--fg-strong)", textAlign: "right", flex: 1, fontFamily: mono ? "var(--font-mono)" : "var(--font-sans)" }}>{value}</span>
    </div>
  );
}
function MiniLine({ label, value }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", padding: "4px 0", fontSize: 13 }}>
      <span style={{ color: "var(--fg-mute)" }}>{label}</span>
      <span style={{ color: "var(--fg-body)", fontWeight: 500 }}>{value}</span>
    </div>
  );
}

Object.assign(window, { Booking });
