// Shippers Connection — load board for shippers to post and find
// consolidation partners. v1 = post + browse; matching algorithms +
// carrier booking + cargo-value insurance flow are subsequent batches.
//
// Schema lives in sql/shipper_connection.sql (apply via Supabase SQL
// editor before this page can write). Auth-gated — magic-link sign-in
// is required so RLS can enforce auth.email() ownership of rows.

const { useState: useStateSC, useEffect: useEffectSC, useMemo: useMemoSC } = React;

// Equipment types with plain-English descriptions. Categories follow how
// LTL/FTL operators actually classify equipment day-to-day. New shippers
// hover/select to see what each type means before they commit.
const EQUIPMENT_TYPES = [
  { id: "dry_van",       label: "Dry van",
    desc: "Standard 53′ enclosed trailer. No vents, no temperature control. Most common general-freight equipment." },
  { id: "vented_van",    label: "Vented van",
    desc: "Dry van with passive air vents on the roof/walls. Not refrigerated. Used for produce that needs airflow but not cold — potatoes, onions, citrus." },
  { id: "insulated_van", label: "Insulated van",
    desc: "Dry van with insulated walls but no active cooling. Protects against temperature extremes without the cost of a reefer." },
  { id: "reefer",        label: "Reefer / frozen (-10° to 0°F)",
    desc: "Active refrigeration held below freezing. Ice cream, frozen meat, frozen prepared foods, frozen seafood. Most demanding load — temperature deviation alarms required." },
  { id: "reefer_fresh",  label: "Reefer / fresh (33-40°F)",
    desc: "Active refrigeration above freezing. Fresh produce, dairy, fresh meat and fish, beverages. The most common reefer category by volume." },
  { id: "reefer_temp",   label: "Reefer / temp-controlled (50-65°F)",
    desc: "Climate-controlled cargo. Wine, chocolate, pharmaceuticals, fine art, electronics. Heat protection in summer, freeze protection in winter." },
  { id: "flatbed",       label: "Flatbed",
    desc: "Open 48′ deck, no walls or roof. Tarpable. Building materials, machinery, steel, anything that doesn't fit through a back door." },
  { id: "step_deck",     label: "Step deck (drop deck)",
    desc: "Two-level deck. Lower main deck handles cargo up to about 10′ tall, giving more clearance under bridges than a flatbed." },
  { id: "rgn",           label: "RGN / lowboy",
    desc: "Removable gooseneck. Center well drops near ground level for very tall or heavy machinery. Permits often required." },
  { id: "conestoga",     label: "Conestoga",
    desc: "Flatbed with a rolling tarp system. Side-load access like a flatbed, weather-protected like a dry van." },
  { id: "tanker",        label: "Tanker",
    desc: "Liquid bulk — food grade, chemical, or fuel. No pallets. Specialized cleaning between loads." },
  { id: "oversized",     label: "Oversized / OD",
    desc: "Loads exceeding standard equipment size or weight. Permits, escort vehicles, and route planning required." },
  { id: "partial",       label: "Partial / LTL",
    desc: "Less than a full truckload. Multiple shippers share a trailer. Usually charged by linear feet plus pallet count plus freight class." },
  { id: "box_truck",     label: "Box truck (24-26′ straight truck)",
    desc: "Class 6/7 straight truck for local or regional LTL. Often used for residential or light-commercial deliveries." },
];

// Haversine distance between two lat/lng pairs, in miles.
function milesBetween(lat1, lng1, lat2, lng2) {
  if (lat1 == null || lng1 == null || lat2 == null || lng2 == null) return null;
  const R = 3959; // miles
  const toRad = (d) => d * Math.PI / 180;
  const dLat = toRad(lat2 - lat1);
  const dLng = toRad(lng2 - lng1);
  const a = Math.sin(dLat / 2) ** 2
          + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLng / 2) ** 2;
  return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}

// =============================================================
// ADDRESS INPUT — company name + street + zip + a Verify button.
// Verification hits OpenStreetMap's free Nominatim geocoder; if the
// address resolves, we save the lat/lng and mark verified. If not,
// we surface a polite "couldn't verify — save anyway?" so the user
// isn't blocked (e.g. private docks, military bases, new builds
// don't always resolve in OSM yet).
// =============================================================
function AddressInput({ label, metroHint, value, onChange }) {
  const [busy, setBusy] = useStateSC(false);
  const [status, setStatus] = useStateSC(value?.verified ? "ok" : "idle");
  const [statusMsg, setStatusMsg] = useStateSC(value?.verified ? "Address verified" : "");

  function patch(p) {
    const next = { ...value, ...p };
    // Editing address fields invalidates a prior verification
    if (("address" in p || "zip" in p || "company" in p)) {
      next.verified = false;
      if (status === "ok") {
        setStatus("idle");
        setStatusMsg("");
      }
    }
    onChange(next);
  }

  async function verify() {
    const parts = [
      value.address,
      metroHint ? metroHint : null,
      value.zip,
      "USA",
    ].filter(Boolean).join(", ");
    if (!parts || parts.length < 6) {
      setStatus("warn");
      setStatusMsg("Enter at least a street address before verifying.");
      return;
    }
    setBusy(true);
    setStatus("checking");
    setStatusMsg("Checking the address…");
    try {
      const url = `https://nominatim.openstreetmap.org/search?format=json&limit=1&addressdetails=0&q=${encodeURIComponent(parts)}`;
      const res = await fetch(url, {
        headers: { "Accept": "application/json" },
      });
      const json = await res.json();
      if (Array.isArray(json) && json.length > 0 && json[0].lat && json[0].lon) {
        const r = json[0];
        onChange({
          ...value,
          verified: true,
          lat: parseFloat(r.lat),
          lng: parseFloat(r.lon),
          display_name: r.display_name,
        });
        setStatus("ok");
        setStatusMsg(`Verified · ${r.display_name.slice(0, 80)}${r.display_name.length > 80 ? "…" : ""}`);
      } else {
        setStatus("warn");
        setStatusMsg("Couldn't verify this exact address. You can still save it — drivers will use the metro + your notes.");
      }
    } catch (e) {
      setStatus("warn");
      setStatusMsg("Verification service is busy. You can still save the address.");
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="ai-block">
      <div className="ai-row ai-row-2">
        <label className="sc-field">
          <span>{label} company / facility name</span>
          <input type="text" value={value.company || ""}
                 onChange={(e) => patch({ company: e.target.value })}
                 placeholder="e.g. Acme Distribution Center" />
        </label>
        <label className="sc-field">
          <span>{label} ZIP</span>
          <input type="text" value={value.zip || ""}
                 onChange={(e) => patch({ zip: e.target.value })}
                 placeholder="ZIP" maxLength={10} />
        </label>
      </div>
      <label className="sc-field">
        <span>{label} street address</span>
        <input type="text" value={value.address || ""}
               onChange={(e) => patch({ address: e.target.value })}
               placeholder="1234 Industrial Way, Suite 5" />
      </label>
      <div className="ai-verify-row">
        <button type="button" className="ai-verify-btn"
                onClick={verify} disabled={busy || !value.address}>
          {busy ? "Checking…" : value.verified ? "✓ Re-verify" : "Verify address"}
        </button>
        {status !== "idle" && (
          <span className={`ai-status ai-status-${status}`}>{statusMsg}</span>
        )}
      </div>
    </div>
  );
}

// =============================================================
// CARGO BUILDER — visual top-down trailer floor where the user
// clicks to add pallets. Each pallet is a draggable rectangle on
// the floor; weight is editable per pallet; the summary tracks
// floor utilization, total weight, and a capacity verdict against
// a standard 53' dry van (or whatever equipment is selected).
//
// Why this exists: typing "21" into a Pallets field is fine for
// power users, but a visual builder is faster, more accurate, and
// more memorable for a new shipper. The component owns the pallet
// list internally and reports {total_pallets, total_weight_lbs,
// pallets[]} up to the form whenever something changes.
// =============================================================

// Equipment dimensions in inches (length × width × height) and
// max payload in lbs. Used to compute capacity verdicts.
const EQUIP_DIMS = {
  dry_van:       { l: 636, w: 102, h: 110, max_lbs: 44000, label: "53' dry van" },
  vented_van:    { l: 636, w: 102, h: 110, max_lbs: 44000, label: "53' vented van" },
  insulated_van: { l: 636, w: 102, h: 110, max_lbs: 43000, label: "53' insulated van" },
  reefer:        { l: 636, w: 100, h: 105, max_lbs: 42000, label: "53' reefer (frozen)" },
  reefer_fresh:  { l: 636, w: 100, h: 105, max_lbs: 42000, label: "53' reefer (fresh)" },
  reefer_temp:   { l: 636, w: 100, h: 105, max_lbs: 42000, label: "53' reefer (temp)" },
  flatbed:       { l: 576, w: 102, h: null, max_lbs: 48000, label: "48' flatbed" },
  step_deck:     { l: 624, w: 102, h: null, max_lbs: 48000, label: "48' step deck" },
  rgn:           { l: 348, w: 102, h: null, max_lbs: 80000, label: "29' RGN well" },
  conestoga:     { l: 576, w: 102, h: null, max_lbs: 48000, label: "48' Conestoga" },
  tanker:        { l: null, w: null, h: null, max_lbs: 50000, label: "Tanker" },
  oversized:     { l: 636, w: 102, h: 110, max_lbs: 44000, label: "Oversized" },
  partial:       { l: 636, w: 102, h: 110, max_lbs: 20000, label: "Partial / LTL" },
  box_truck:     { l: 312, w: 96,  h: 96,  max_lbs: 12000, label: "26' box truck" },
};

// Pallet presets — width × length in inches, default weight in lbs.
// Euro pallets (48×32 / 800×1200mm) dropped — they're a European
// convention rarely used in US freight. Custom is now interactive:
// clicking it opens a dimensions dialog.
const PALLET_PRESETS = {
  standard: { w: 48, l: 40, weight: 1500, label: "Standard", sub: "48\" × 40\" GMA" },
  half:     { w: 24, l: 40, weight: 750,  label: "Half",     sub: "24\" × 40\"" },
  custom:   { w: 48, l: 48, weight: 2000, label: "Custom",   sub: "Set the dimensions", interactive: true },
};

// Greedy 2D bin-packing for top-down trailer floor.
// Trailers are long and narrow, so we pack rows left-to-right
// across the width, then advance down the length.
function layoutPallets(pallets, equipDims) {
  if (!equipDims || !equipDims.w || !equipDims.l) return { placements: [], totalLength: 0, overflow: false };
  const truckW = equipDims.w;
  const truckL = equipDims.l;
  const placements = [];
  let rowY = 0;
  let rowX = 0;
  let rowMaxL = 0;
  let overflow = false;

  for (const p of pallets) {
    if (rowX + p.w > truckW) {
      // start new row
      rowY += rowMaxL;
      rowX = 0;
      rowMaxL = 0;
    }
    if (rowY + p.l > truckL) overflow = true;
    placements.push({ ...p, x: rowX, y: rowY, overflow: rowY + p.l > truckL });
    rowX += p.w;
    rowMaxL = Math.max(rowMaxL, p.l);
  }
  return { placements, totalLength: rowY + rowMaxL, overflow };
}

function CargoBuilder({ equipment, value, onChange }) {
  const [pallets, setPallets] = useStateSC(value?.pallets || []);
  const [activeId, setActiveId] = useStateSC(null);
  const [customOpen, setCustomOpen] = useStateSC(false);
  const [customW, setCustomW] = useStateSC("48");
  const [customL, setCustomL] = useStateSC("48");
  const [customWeight, setCustomWeight] = useStateSC("2000");

  const equipDims = EQUIP_DIMS[equipment] || EQUIP_DIMS.dry_van;
  const { placements, totalLength, overflow } = useMemoSC(
    () => layoutPallets(pallets, equipDims),
    [pallets, equipDims]
  );

  const totalWeight = useMemoSC(
    () => pallets.reduce((sum, p) => sum + (Number(p.weight) || 0), 0),
    [pallets]
  );

  const truckUsable = equipDims.l && equipDims.w;
  const linearFt = truckUsable ? Math.min(totalLength, equipDims.l) / 12 : 0;
  const truckLengthFt = truckUsable ? equipDims.l / 12 : 0;
  const floorPct = truckUsable && equipDims.l ? Math.min(100, (totalLength / equipDims.l) * 100) : 0;
  const weightPct = equipDims.max_lbs ? Math.min(100, (totalWeight / equipDims.max_lbs) * 100) : 0;
  const overweight = totalWeight > equipDims.max_lbs;

  // Notify parent of changes
  useEffectSC(() => {
    onChange && onChange({
      total_pallets: pallets.length,
      total_weight_lbs: totalWeight,
      pallets,
    });
  }, [pallets, totalWeight]);

  function addPallet(presetKey) {
    const p = PALLET_PRESETS[presetKey];
    if (p.interactive) {
      setCustomOpen(true);
      return;
    }
    setPallets(prev => [
      ...prev,
      { id: `p_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
        type: presetKey, w: p.w, l: p.l, weight: p.weight },
    ]);
  }
  function commitCustom() {
    const w = Math.max(1, Math.min(120, parseInt(customW, 10) || 0));
    const l = Math.max(1, Math.min(636, parseInt(customL, 10) || 0));
    const wt = Math.max(0, parseInt(customWeight, 10) || 0);
    setPallets(prev => [
      ...prev,
      { id: `p_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
        type: "custom", w, l, weight: wt },
    ]);
    setCustomOpen(false);
  }
  function removePallet(id) {
    setPallets(prev => prev.filter(p => p.id !== id));
    if (activeId === id) setActiveId(null);
  }
  function updatePallet(id, patch) {
    setPallets(prev => prev.map(p => (p.id === id ? { ...p, ...patch } : p)));
  }
  function clearAll() {
    if (pallets.length && confirm("Remove all pallets and start over?")) setPallets([]);
  }

  // Verdict copy
  let verdictText, verdictKind;
  if (pallets.length === 0) {
    verdictText = `Add pallets to see how they fit in a ${equipDims.label}`;
    verdictKind = "neutral";
  } else if (overflow && overweight) {
    verdictText = `Won't fit — over length AND weight. Consider splitting across two trucks.`;
    verdictKind = "warn";
  } else if (overflow) {
    verdictText = `Doesn't fit a ${equipDims.label} — needs a longer trailer or fewer pallets`;
    verdictKind = "warn";
  } else if (overweight) {
    verdictText = `Over the ${equipDims.max_lbs.toLocaleString()} lb limit for ${equipDims.label}`;
    verdictKind = "warn";
  } else {
    verdictText = `Fits in a ${equipDims.label} · ${linearFt.toFixed(1)} of ${truckLengthFt} linear ft used`;
    verdictKind = "ok";
  }

  return (
    <div className="cb-wrap">
      <div className="cb-head">
        <div>
          <div className="cb-eyebrow">Build the load</div>
          <p className="cb-sub">Click a pallet type to add it to the trailer.</p>
        </div>
        {pallets.length > 0 && (
          <button type="button" className="cb-clear" onClick={clearAll}>Clear all</button>
        )}
      </div>

      {/* Pallet palette */}
      <div className="cb-palette">
        {Object.entries(PALLET_PRESETS).map(([key, p]) => (
          <button key={key} type="button" className="cb-add"
                  onClick={() => addPallet(key)}>
            <div className="cb-add-icon">
              <svg viewBox={`0 0 ${p.w} ${p.l}`} preserveAspectRatio="xMidYMid meet" width="40" height="40">
                <rect x="0" y="0" width={p.w} height={p.l} rx="2"
                      fill="oklch(0.85 0.04 60)" stroke="oklch(0.45 0.06 60)" strokeWidth="2" />
                <line x1="0" y1={p.l/3} x2={p.w} y2={p.l/3} stroke="oklch(0.45 0.06 60)" strokeWidth="1.5" />
                <line x1="0" y1={2*p.l/3} x2={p.w} y2={2*p.l/3} stroke="oklch(0.45 0.06 60)" strokeWidth="1.5" />
              </svg>
            </div>
            <div className="cb-add-text">
              <div className="cb-add-name">{p.label}</div>
              <div className="cb-add-sub">{p.sub}</div>
            </div>
            <div className="cb-add-plus">+</div>
          </button>
        ))}
      </div>

      {customOpen && (
        <div className="cb-custom-bg" onClick={(e) => { if (e.target === e.currentTarget) setCustomOpen(false); }}>
          <div className="cb-custom">
            <button type="button" className="cb-custom-x"
                    onClick={() => setCustomOpen(false)} aria-label="Close">×</button>
            <h3 className="cb-custom-h">Custom pallet</h3>
            <p className="cb-custom-sub">Enter the footprint and weight in inches and pounds.</p>
            <div className="cb-custom-grid">
              <label className="cb-field">
                <span>Width (inches)</span>
                <input type="number" min="1" max="120" value={customW}
                       onChange={(e) => setCustomW(e.target.value)} autoFocus />
              </label>
              <label className="cb-field">
                <span>Length (inches)</span>
                <input type="number" min="1" max="636" value={customL}
                       onChange={(e) => setCustomL(e.target.value)} />
              </label>
              <label className="cb-field cb-field-full">
                <span>Weight (lbs)</span>
                <input type="number" min="0" step="50" value={customWeight}
                       onChange={(e) => setCustomWeight(e.target.value)} />
              </label>
            </div>
            <div className="cb-custom-foot">
              <button type="button" className="cb-clear"
                      onClick={() => setCustomOpen(false)}>Cancel</button>
              <button type="button" className="cb-custom-add"
                      onClick={commitCustom}>Add to trailer →</button>
            </div>
          </div>
        </div>
      )}

      {/* Trailer floor visualization */}
      {truckUsable ? (
        <div className="cb-truck-wrap">
          <div className="cb-truck-label">
            <span className="cb-truck-label-tip">Cab</span>
            <span className="cb-truck-label-mid">{equipDims.label} · top-down</span>
            <span className="cb-truck-label-tip">Doors</span>
          </div>
          <div className="cb-truck-stage">
            <svg viewBox={`-4 -4 ${equipDims.l + 8} ${equipDims.w + 8}`}
                 className={`cb-truck-svg ${overflow ? "is-overflow" : ""}`}
                 preserveAspectRatio="none">
              {/* Trailer floor */}
              <rect x="0" y="0" width={equipDims.l} height={equipDims.w}
                    rx="6" fill="oklch(0.96 0.005 60)"
                    stroke="oklch(0.55 0.02 60)" strokeWidth="2" />
              {/* Floor markings — every 10 feet */}
              {Array.from({ length: Math.floor(equipDims.l / 120) }, (_, i) => (
                <line key={i} x1={(i + 1) * 120} y1="0" x2={(i + 1) * 120} y2={equipDims.w}
                      stroke="oklch(0.85 0.005 60)" strokeWidth="0.7" strokeDasharray="3 4" />
              ))}
              {/* Cab arrow */}
              <polygon points={`-3,${equipDims.w/2 - 6} 1,${equipDims.w/2} -3,${equipDims.w/2 + 6}`}
                       fill="oklch(0.55 0.02 60)" />
              {/* Pallets */}
              {placements.map((p, idx) => (
                <g key={p.id} className={`cb-pallet ${activeId === p.id ? "is-active" : ""} ${p.overflow ? "is-overflow" : ""}`}
                   onClick={(e) => { e.stopPropagation(); setActiveId(p.id); }}>
                  <rect x={p.x} y={p.y} width={p.w} height={p.l} rx="2"
                        fill={p.overflow ? "oklch(0.85 0.10 25)" : "oklch(0.78 0.08 250)"}
                        stroke={p.overflow ? "oklch(0.50 0.18 25)" : "oklch(0.40 0.16 250)"}
                        strokeWidth={activeId === p.id ? 3 : 1.5} />
                  <text x={p.x + p.w/2} y={p.y + p.l/2 + 4}
                        textAnchor="middle" fontSize="14" fontWeight="700"
                        fill={p.overflow ? "oklch(0.30 0.18 25)" : "oklch(0.25 0.16 250)"}>
                    {idx + 1}
                  </text>
                </g>
              ))}
            </svg>
          </div>
        </div>
      ) : (
        <div className="cb-no-truck">
          {equipDims.label} doesn't have a standard floor visualization. Use the per-pallet list below.
        </div>
      )}

      {/* Capacity bars + verdict */}
      <div className="cb-stats">
        <div className="cb-stat">
          <div className="cb-stat-row">
            <span className="cb-stat-label">Floor</span>
            <span className="cb-stat-val">
              {linearFt.toFixed(1)} / {truckLengthFt} ft · {Math.round(floorPct)}%
            </span>
          </div>
          <div className="cb-bar">
            <div className="cb-bar-fill"
                 style={{ width: `${floorPct}%`,
                          background: overflow ? "oklch(0.55 0.18 25)" : "oklch(0.50 0.16 250)" }} />
          </div>
        </div>
        <div className="cb-stat">
          <div className="cb-stat-row">
            <span className="cb-stat-label">Weight</span>
            <span className="cb-stat-val">
              {totalWeight.toLocaleString()} / {equipDims.max_lbs.toLocaleString()} lbs · {Math.round(weightPct)}%
            </span>
          </div>
          <div className="cb-bar">
            <div className="cb-bar-fill"
                 style={{ width: `${weightPct}%`,
                          background: overweight ? "oklch(0.55 0.18 25)" : "oklch(0.50 0.16 145)" }} />
          </div>
        </div>
      </div>

      <div className={`cb-verdict cb-verdict-${verdictKind}`}>
        {verdictKind === "ok" && <span className="cb-check">✓</span>}
        {verdictKind === "warn" && <span className="cb-x">!</span>}
        <span>{verdictText}</span>
      </div>

      {/* Pallet list with per-pallet weight + remove */}
      {pallets.length > 0 && (
        <ul className="cb-list">
          {pallets.map((p, idx) => {
            const preset = PALLET_PRESETS[p.type];
            return (
              <li key={p.id} className={`cb-list-item ${activeId === p.id ? "is-active" : ""}`}
                  onClick={() => setActiveId(p.id)}>
                <span className="cb-list-n">#{idx + 1}</span>
                <span className="cb-list-name">
                  {preset?.label || "Pallet"}
                  <span className="cb-list-dim">{p.w}″ × {p.l}″</span>
                </span>
                <label className="cb-list-weight">
                  <input type="number" min="0" step="50" value={p.weight}
                         onClick={(e) => e.stopPropagation()}
                         onChange={(e) => updatePallet(p.id, { weight: parseInt(e.target.value, 10) || 0 })} />
                  <span>lbs</span>
                </label>
                <button type="button" className="cb-list-x"
                        onClick={(e) => { e.stopPropagation(); removePallet(p.id); }}
                        aria-label="Remove pallet">×</button>
              </li>
            );
          })}
        </ul>
      )}
    </div>
  );
}

// =============================================================
// POST-A-LOAD FORM
// =============================================================
function PostLoadForm({ user, cities, onPosted, initialDraft }) {
  const [busy, setBusy] = useStateSC(false);
  const [err, setErr] = useStateSC(null);
  const [showAdv, setShowAdv] = useStateSC(false);

  // Convert ISO timestamp → "YYYY-MM-DDTHH:MM" for datetime-local inputs
  function toDtLocal(iso) {
    if (!iso) return "";
    const d = new Date(iso);
    if (isNaN(d.getTime())) return "";
    const pad = (n) => String(n).padStart(2, "0");
    return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
  }
  // Find a metro id from a city/state pair (drafts store name+state, not id)
  function metroIdFor(name, state) {
    const c = (cities || []).find(c =>
      c.name === name && c.state === state);
    return c ? c.id : "";
  }
  const d = initialDraft || null;

  const editingId = d?.id || null;

  const [originId, setOriginId]   = useStateSC(d ? metroIdFor(d.origin_city, d.origin_state) : "");
  const [destId, setDestId]       = useStateSC(d ? metroIdFor(d.dest_city, d.dest_state) : "");
  const [equipment, setEquipment] = useStateSC(d?.equipment_type || "dry_van");
  const [pickupAt, setPickupAt]   = useStateSC(d ? toDtLocal(d.pickup_earliest) : "");
  const [deliveryAt, setDeliveryAt] = useStateSC(d ? toDtLocal(d.delivery_earliest) : "");
  const [weight, setWeight]       = useStateSC(d?.weight_lbs ? String(d.weight_lbs) : "");
  const [pallets, setPallets]     = useStateSC(d?.total_pallets != null ? String(d.total_pallets) : "");
  // Resumed drafts default to manual cargo entry — the visual builder's
  // pallet array isn't stored, so we'd lose detail trying to reconstruct it.
  const [cargoMode, setCargoMode] = useStateSC(d ? "manual" : "visual");
  const [cargoState, setCargoState] = useStateSC({ pallets: [], total_pallets: 0, total_weight_lbs: 0 });

  // New: detailed pickup/delivery addresses with verification
  const [originAddr, setOriginAddr] = useStateSC(d ? {
    company: d.origin_company_name || "", address: d.origin_address || "",
    zip: d.origin_zip || "",
    verified: !!d.origin_address_verified,
    lat: d.origin_lat || null, lng: d.origin_lng || null,
  } : { company: "", address: "", zip: "", verified: false, lat: null, lng: null });
  const [destAddr,   setDestAddr]   = useStateSC(d ? {
    company: d.dest_company_name || "", address: d.dest_address || "",
    zip: d.dest_zip || "",
    verified: !!d.dest_address_verified,
    lat: d.dest_lat || null, lng: d.dest_lng || null,
  } : { company: "", address: "", zip: "", verified: false, lat: null, lng: null });

  // New: appointment status per leg
  const [pickupApptStatus, setPickupApptStatus] = useStateSC(d?.pickup_appointment_status || "needs_appointment");
  const [deliveryApptStatus, setDeliveryApptStatus] = useStateSC(d?.delivery_appointment_status || "needs_appointment");

  // New: separate pickup vs delivery notes
  const [pickupNotes, setPickupNotes] = useStateSC(d?.pickup_notes || "");
  const [deliveryNotes, setDeliveryNotes] = useStateSC(d?.delivery_notes || "");

  // New: reference numbers
  const [poNumber, setPoNumber] = useStateSC(d?.po_number || "");
  const [pickupNumber, setPickupNumber] = useStateSC(d?.pickup_number || "");
  const [bolNumber, setBolNumber] = useStateSC(d?.bol_number || "");
  const [cargoVal, setCargoVal]   = useStateSC(d?.cargo_value_usd ? String(d.cargo_value_usd) : "");
  const [rate, setRate]           = useStateSC(d?.rate_offered_usd ? String(d.rate_offered_usd) : "");
  const [tempMin, setTempMin]     = useStateSC(d?.temp_min_f != null ? String(d.temp_min_f) : "");
  const [tempMax, setTempMax]     = useStateSC(d?.temp_max_f != null ? String(d.temp_max_f) : "");
  // Hazmat is not supported on Shippers Connect — fields kept null for the DB.
  const [share, setShare]         = useStateSC(d ? !!d.willing_to_share : true);
  const [shareAddl, setShareAddl] = useStateSC(d?.share_max_addl_pallets != null ? String(d.share_max_addl_pallets) : "");
  const [desc, setDesc]           = useStateSC(d?.cargo_description || "");
  const [notes, setNotes]         = useStateSC(d?.shipper_notes || "");
  const [shipperName, setShipperName]       = useStateSC(d?.shipper_name || user.name || "");
  const [shipperCompany, setShipperCompany] = useStateSC(d?.shipper_company || "");

  function findCity(id) { return cities.find(c => c.id === id); }
  const isReefer = equipment === "reefer" || equipment === "reefer_fresh" || equipment === "reefer_temp";

  async function submit(e, asDraft = false) {
    if (e && e.preventDefault) e.preventDefault();
    setErr(null);
    if (!originId || !destId) {
      setErr("Origin and destination are required, even for a draft.");
      return;
    }
    if (originId === destId) {
      setErr("Origin and destination can't be the same metro.");
      return;
    }
    if (!asDraft) {
      if (!pickupAt) {
        setErr("Pickup time is required to publish.");
        return;
      }
      const palletCount = cargoMode === "visual"
        ? cargoState.total_pallets
        : (parseInt(pallets, 10) || 0);
      if (palletCount < 1) {
        setErr(cargoMode === "visual"
          ? "Add at least one pallet to the trailer before posting."
          : "Pallet count is required (minimum 1).");
        return;
      }
    }
    const origin = findCity(originId);
    const dest = findCity(destId);
    if (!origin || !dest) { setErr("Origin/destination not found."); return; }

    const row = {
      shipper_email: user.email,
      shipper_name: shipperName.trim() || null,
      shipper_company: shipperCompany.trim() || null,
      status: asDraft ? "draft" : "open",
      // Origin
      origin_city: origin.name,
      origin_state: origin.state,
      // Prefer the verified address geocode when present; fall back to metro center.
      origin_lat: originAddr.verified && originAddr.lat ? originAddr.lat : (origin.lat || null),
      origin_lng: originAddr.verified && originAddr.lng ? originAddr.lng : (origin.lng || null),
      origin_address: originAddr.address.trim() || null,
      origin_zip: originAddr.zip.trim() || null,
      origin_company_name: originAddr.company.trim() || null,
      origin_address_verified: !!originAddr.verified,
      origin_geocoded_at: originAddr.verified ? new Date().toISOString() : null,
      // Destination
      dest_city: dest.name,
      dest_state: dest.state,
      dest_lat: destAddr.verified && destAddr.lat ? destAddr.lat : (dest.lat || null),
      dest_lng: destAddr.verified && destAddr.lng ? destAddr.lng : (dest.lng || null),
      dest_address: destAddr.address.trim() || null,
      dest_zip: destAddr.zip.trim() || null,
      dest_company_name: destAddr.company.trim() || null,
      dest_address_verified: !!destAddr.verified,
      dest_geocoded_at: destAddr.verified ? new Date().toISOString() : null,
      // Windows + appointments
      pickup_earliest: pickupAt ? new Date(pickupAt).toISOString() : null,
      delivery_earliest: deliveryAt ? new Date(deliveryAt).toISOString() : null,
      pickup_appointment_status: pickupApptStatus,
      delivery_appointment_status: deliveryApptStatus,
      // Cargo
      equipment_type: equipment,
      weight_lbs: weight ? parseInt(weight, 10) : null,
      total_pallets: pallets ? parseInt(pallets, 10) : null,
      cargo_description: desc.trim() || null,
      cargo_value_usd: cargoVal ? parseInt(cargoVal, 10) : null,
      rate_offered_usd: rate ? parseInt(rate, 10) : null,
      hazmat: false,
      hazmat_class: null,
      temp_min_f: isReefer && tempMin !== "" ? parseInt(tempMin, 10) : null,
      temp_max_f: isReefer && tempMax !== "" ? parseInt(tempMax, 10) : null,
      // Sharing
      willing_to_share: !!share,
      share_max_addl_pallets: share && shareAddl ? parseInt(shareAddl, 10) : null,
      // Notes (split + general)
      pickup_notes: pickupNotes.trim() || null,
      delivery_notes: deliveryNotes.trim() || null,
      shipper_notes: notes.trim() || null,
      // Reference numbers
      po_number: poNumber.trim() || null,
      pickup_number: pickupNumber.trim() || null,
      bol_number: bolNumber.trim() || null,
    };

    setBusy(true);
    try {
      let ok;
      if (editingId) {
        // Resuming a draft — UPDATE the existing row instead of inserting.
        ok = await window.SI_DB.raw.updateAuthed(
          "shipper_loads",
          `id=eq.${encodeURIComponent(editingId)}`,
          row
        );
      } else {
        ok = await window.SI_DB.raw.insertAuthed("shipper_loads", row);
      }
      if (!ok) { setErr("Couldn't post the load. Check the schema is applied or try again."); return; }
      // Reset
      setOriginId(""); setDestId(""); setPickupAt(""); setDeliveryAt("");
      setWeight(""); setPallets(""); setCargoVal(""); setRate("");
      setTempMin(""); setTempMax("");
      setDesc(""); setNotes("");
      setCargoState({ pallets: [], total_pallets: 0, total_weight_lbs: 0 });
      setOriginAddr({ company: "", address: "", zip: "", verified: false, lat: null, lng: null });
      setDestAddr({ company: "", address: "", zip: "", verified: false, lat: null, lng: null });
      setPickupApptStatus("needs_appointment"); setDeliveryApptStatus("needs_appointment");
      setPickupNotes(""); setDeliveryNotes("");
      setPoNumber(""); setPickupNumber(""); setBolNumber("");
      onPosted && onPosted();
    } catch (e) {
      setErr(String(e && e.message || e));
    } finally {
      setBusy(false);
    }
  }

  const originMetroLabel = useMemoSC(() => {
    const c = cities.find(c => c.id === originId);
    return c ? `${c.name}, ${c.state}` : "";
  }, [cities, originId]);
  const destMetroLabel = useMemoSC(() => {
    const c = cities.find(c => c.id === destId);
    return c ? `${c.name}, ${c.state}` : "";
  }, [cities, destId]);

  // Light "section completion" signal for the progress indicator at the top.
  const sectionDone = {
    pickup: !!(originId && pickupAt),
    delivery: !!destId,
    cargo: cargoMode === "visual"
            ? cargoState.total_pallets >= 1
            : (parseInt(pallets, 10) || 0) >= 1,
    money: rate !== "" || cargoVal !== "" || share,
    you: shipperName.trim().length > 0,
  };
  const doneCount = Object.values(sectionDone).filter(Boolean).length;
  const totalSections = Object.keys(sectionDone).length;

  return (
    <form onSubmit={submit} className="sc-form-page">
      {/* Hero header */}
      <header className="sc-form-hero">
        <div className="sc-form-hero-eyebrow">Connection Board · Post a load</div>
        <h2 className="sc-form-hero-h">Where's it going, and what's on the truck?</h2>
        <p className="sc-form-hero-sub">
          Six short sections. Carriers see your post the moment it lands; if
          something matches their next available trailer, you get an email.
        </p>
        <div className="sc-progress">
          <div className="sc-progress-label">
            <span>{doneCount} of {totalSections} ready</span>
          </div>
          <div className="sc-progress-bar">
            <div className="sc-progress-fill"
                 style={{ width: `${(doneCount / totalSections) * 100}%` }} />
          </div>
          <div className="sc-progress-dots">
            {Object.entries(sectionDone).map(([key, done]) => (
              <span key={key} className={`sc-progress-dot ${done ? "is-done" : ""}`} />
            ))}
          </div>
        </div>
      </header>

      {/* SECTION 1 + 2 — Pickup + Delivery side by side */}
      <div className="sc-section-grid">
        <SectionCard n="1" title="Pickup" sub="Where the truck loads."
                     done={sectionDone.pickup}>
          <label className="sc-field">
            <span>Origin metro (lane)</span>
            <select value={originId} onChange={e => setOriginId(e.target.value)} required>
              <option value="">Pick origin…</option>
              {cities.map(c => <option key={c.id} value={c.id}>{c.name}, {c.state}</option>)}
            </select>
          </label>
          <AddressInput label="Pickup" metroHint={originMetroLabel}
                        value={originAddr} onChange={setOriginAddr} />
          <label className="sc-field">
            <span>Pickup window starts</span>
            <input type="datetime-local" value={pickupAt}
              onChange={e => setPickupAt(e.target.value)} required />
          </label>
          <label className="sc-field">
            <span>Pickup appointment</span>
            <select value={pickupApptStatus}
                    onChange={e => setPickupApptStatus(e.target.value)}>
              <option value="needs_appointment">Needs to be made</option>
              <option value="made">Already made (use the time above)</option>
              <option value="no_appointment_needed">No appointment needed</option>
              <option value="first_come_first_served">First come, first served</option>
            </select>
          </label>
          <label className="sc-field">
            <span>Pickup notes (driver instructions)</span>
            <textarea rows={2} value={pickupNotes}
                      onChange={e => setPickupNotes(e.target.value)}
                      placeholder="e.g. Dock 7, ask for Bill, drivers must show TWIC at gate." />
          </label>
        </SectionCard>

        <SectionCard n="2" title="Delivery" sub="Where the truck drops."
                     done={sectionDone.delivery}>
          <label className="sc-field">
            <span>Destination metro (lane)</span>
            <select value={destId} onChange={e => setDestId(e.target.value)} required>
              <option value="">Pick destination…</option>
              {cities.map(c => <option key={c.id} value={c.id}>{c.name}, {c.state}</option>)}
            </select>
          </label>
          <AddressInput label="Delivery" metroHint={destMetroLabel}
                        value={destAddr} onChange={setDestAddr} />
          <label className="sc-field">
            <span>Delivery window starts (optional)</span>
            <input type="datetime-local" value={deliveryAt}
              onChange={e => setDeliveryAt(e.target.value)} />
          </label>
          <label className="sc-field">
            <span>Delivery appointment</span>
            <select value={deliveryApptStatus}
                    onChange={e => setDeliveryApptStatus(e.target.value)}>
              <option value="needs_appointment">Needs to be made</option>
              <option value="made">Already made (use the time above)</option>
              <option value="no_appointment_needed">No appointment needed</option>
              <option value="first_come_first_served">First come, first served</option>
            </select>
          </label>
          <label className="sc-field">
            <span>Delivery notes (driver instructions)</span>
            <textarea rows={2} value={deliveryNotes}
                      onChange={e => setDeliveryNotes(e.target.value)}
                      placeholder="e.g. Receiving open M-F 7-3, no Saturdays, lift gate required." />
          </label>
        </SectionCard>
      </div>

      {/* SECTION 3 — Cargo */}
      <SectionCard n="3" title="Cargo" sub="Equipment and what's on the floor."
                   done={sectionDone.cargo}>
        <label className="sc-field">
          <span>Equipment</span>
          <select value={equipment} onChange={e => setEquipment(e.target.value)}>
            {EQUIPMENT_TYPES.map(t => <option key={t.id} value={t.id}>{t.label}</option>)}
          </select>
        </label>
        {(() => {
          const eq = EQUIPMENT_TYPES.find(t => t.id === equipment);
          return eq?.desc ? <div className="sc-equip-desc">{eq.desc}</div> : null;
        })()}

        {cargoMode === "visual" ? (
          <>
            <CargoBuilder
              equipment={equipment}
              value={cargoState}
              onChange={(s) => {
                setCargoState(s);
                setWeight(s.total_weight_lbs ? String(s.total_weight_lbs) : "");
                setPallets(s.total_pallets ? String(s.total_pallets) : "");
              }} />
            <button type="button" className="sc-mode-link"
                    onClick={() => setCargoMode("manual")}>
              Skip the visual — just type the numbers →
            </button>
          </>
        ) : (
          <>
            <div className="sc-form-grid sc-form-grid-2">
              <label className="sc-field">
                <span>Weight (lbs)</span>
                <input type="number" min="0" step="100" value={weight}
                       onChange={e => setWeight(e.target.value)} />
              </label>
              <label className="sc-field">
                <span>Pallets (min 1)</span>
                <input type="number" min="1" step="1" value={pallets}
                       onChange={e => setPallets(e.target.value)} />
              </label>
            </div>
            <button type="button" className="sc-mode-link"
                    onClick={() => setCargoMode("visual")}>
              ← Build it visually instead
            </button>
          </>
        )}
        <label className="sc-field">
          <span>Cargo description (general — sealed by default)</span>
          <input type="text" value={desc} onChange={e => setDesc(e.target.value)}
            placeholder="e.g. dry food product · packaged paper goods · bulk machinery parts" />
        </label>

        {isReefer && (
          <div className="sc-form-grid sc-form-grid-2" style={{ marginTop: 4 }}>
            <label className="sc-field">
              <span>Temp min (°F)</span>
              <input type="number" value={tempMin} onChange={e => setTempMin(e.target.value)} placeholder="-10 / 32 / 38" />
            </label>
            <label className="sc-field">
              <span>Temp max (°F)</span>
              <input type="number" value={tempMax} onChange={e => setTempMax(e.target.value)} placeholder="0 / 36 / 45" />
            </label>
          </div>
        )}

        <p className="sc-no-hazmat">
          ⚠ <strong>No hazmat freight.</strong> Shippers Connect doesn't currently support
          hazardous materials. If your load needs hazmat placards or a Hazmat-endorsed
          driver, please book through a hazmat-certified broker.
        </p>
      </SectionCard>

      {/* SECTION 4 — Rate & Sharing */}
      <SectionCard n="4" title="Rate & sharing" sub="What you're offering and whether you'd split the truck."
                   done={sectionDone.money}>
        <div className="sc-form-grid sc-form-grid-2">
          <label className="sc-field">
            <span>Rate offered ($)</span>
            <input type="number" min="0" step="50" value={rate}
                   onChange={e => setRate(e.target.value)}
                   placeholder="e.g. 1850" />
          </label>
          <label className="sc-field">
            <span>Cargo value ($) <span className="sc-hint">drives the carrier's cargo-insurance bracket</span></span>
            <input type="number" min="0" step="100" value={cargoVal}
                   onChange={e => setCargoVal(e.target.value)}
                   placeholder="optional" />
          </label>
        </div>

        <label className="sc-share-toggle">
          <input type="checkbox" checked={share} onChange={e => setShare(e.target.checked)} />
          <div>
            <strong>Open to consolidation.</strong>
            <span> Other shippers heading the same way can request to share this truck — split the rate, save on freight, hit the same dock window.</span>
          </div>
        </label>
        {share && (
          <label className="sc-field">
            <span>Open pallets to share (optional)</span>
            <input type="number" min="0" value={shareAddl} onChange={e => setShareAddl(e.target.value)}
              placeholder="How many additional pallets a partner could add" />
          </label>
        )}
      </SectionCard>

      {/* SECTION 5 — References */}
      <SectionCard n="5" title="Reference numbers" sub="Optional, but they help everyone track the load.">
        <div className="sc-form-grid sc-form-grid-3">
          <label className="sc-field">
            <span>PO number</span>
            <input type="text" value={poNumber}
                   onChange={e => setPoNumber(e.target.value)}
                   placeholder="Customer purchase order #" />
          </label>
          <label className="sc-field">
            <span>Pickup number</span>
            <input type="text" value={pickupNumber}
                   onChange={e => setPickupNumber(e.target.value)}
                   placeholder="Shipper's pickup confirmation #" />
          </label>
          <label className="sc-field">
            <span>BOL number (if pre-assigned)</span>
            <input type="text" value={bolNumber}
                   onChange={e => setBolNumber(e.target.value)}
                   placeholder="Bill of Lading #" />
          </label>
        </div>
      </SectionCard>

      {/* SECTION 6 — You */}
      <SectionCard n="6" title="You" sub="So carriers know who they're talking to."
                   done={sectionDone.you}>
        <div className="sc-form-grid sc-form-grid-2">
          <label className="sc-field">
            <span>Your name</span>
            <input type="text" value={shipperName}
                   onChange={e => setShipperName(e.target.value)} />
          </label>
          <label className="sc-field">
            <span>Company</span>
            <input type="text" value={shipperCompany}
                   onChange={e => setShipperCompany(e.target.value)} />
          </label>
        </div>
        <label className="sc-field">
          <span>General notes (anything else — visible on the load card)</span>
          <textarea value={notes} onChange={e => setNotes(e.target.value)} rows={2}
            placeholder="Anything not covered above — special handling, lumper info, etc." />
        </label>
      </SectionCard>

      {err && <div className="sc-err">{err}</div>}

      {/* Sticky submit footer */}
      <div className="sc-form-footer">
        <div className="sc-form-footer-summary">
          {doneCount === totalSections
            ? <span className="sc-form-footer-ok">✓ All set — ready to post</span>
            : <span className="sc-form-footer-pending">{totalSections - doneCount} section{totalSections - doneCount === 1 ? "" : "s"} to go</span>}
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          <button type="button" className="sc-submit-draft" disabled={busy}
                  onClick={(e) => submit(e, true)}>
            Save as draft
          </button>
          <button type="submit" className="sc-submit-big" disabled={busy}>
            {busy ? "Posting…" : "Post the load →"}
          </button>
        </div>
      </div>
    </form>
  );
}

// =============================================================
// SECTION CARD — wraps a form section with a numbered badge,
// serif title, and small subhead. The done={} prop lights the
// badge green when the section's primary inputs are filled.
// =============================================================
function SectionCard({ n, title, sub, done, children }) {
  return (
    <section className={`sc-card-section ${done ? "is-done" : ""}`}>
      <header className="sc-section-head">
        <span className="sc-section-n">{done ? "✓" : n}</span>
        <div>
          <h3 className="sc-section-title">{title}</h3>
          {sub && <p className="sc-section-sub">{sub}</p>}
        </div>
      </header>
      <div className="sc-section-body">{children}</div>
    </section>
  );
}

// =============================================================
// LOAD BOARD BROWSE
// =============================================================
function LoadBoard({ user, cities, refreshKey }) {
  const [loads, setLoads] = useStateSC([]);
  const [loading, setLoading] = useStateSC(true);
  const [filter, setFilter] = useStateSC({
    destCityId: "",
    equipment: "",
    radiusMi: 100,
    onlyShare: false,
    onlyVerified: false,
    apptStatus: "",
    poQuery: "",
  });
  const [interestFor, setInterestFor] = useStateSC(null);

  useEffectSC(() => {
    let alive = true;
    setLoading(true);
    (async () => {
      try {
        const rows = await window.SI_DB.raw.selectAuthed(
          "shipper_loads",
          "select=*&status=in.(open,matched)&order=pickup_earliest.asc&limit=500"
        );
        if (!alive) return;
        setLoads(Array.isArray(rows) ? rows : []);
      } catch {} finally { if (alive) setLoading(false); }
    })();
    return () => { alive = false; };
  }, [refreshKey]);

  const filtered = useMemoSC(() => {
    let out = loads.slice();
    if (filter.equipment) out = out.filter(l => l.equipment_type === filter.equipment);
    if (filter.onlyShare) out = out.filter(l => l.willing_to_share);
    if (filter.onlyVerified) {
      out = out.filter(l => l.origin_address_verified || l.dest_address_verified);
    }
    if (filter.apptStatus) {
      out = out.filter(l =>
        l.pickup_appointment_status === filter.apptStatus ||
        l.delivery_appointment_status === filter.apptStatus);
    }
    if (filter.poQuery && filter.poQuery.trim()) {
      const q = filter.poQuery.trim().toLowerCase();
      out = out.filter(l =>
        (l.po_number && l.po_number.toLowerCase().includes(q)) ||
        (l.pickup_number && l.pickup_number.toLowerCase().includes(q)) ||
        (l.bol_number && l.bol_number.toLowerCase().includes(q)));
    }
    if (filter.destCityId) {
      const city = cities.find(c => c.id === filter.destCityId);
      if (city && city.lat != null && city.lng != null) {
        const r = filter.radiusMi || 100;
        out = out.filter(l => {
          if (l.dest_lat == null || l.dest_lng == null) return false;
          const d = milesBetween(city.lat, city.lng, l.dest_lat, l.dest_lng);
          return d != null && d <= r;
        });
        out.forEach(l => {
          l._distMi = milesBetween(city.lat, city.lng, l.dest_lat, l.dest_lng);
        });
        out.sort((a, b) => (a._distMi ?? 9999) - (b._distMi ?? 9999));
      }
    }
    return out;
  }, [loads, filter, cities]);

  function fmtDate(iso) {
    if (!iso) return "—";
    const d = new Date(iso);
    return d.toLocaleString(undefined, {
      month: "short", day: "numeric", hour: "numeric", minute: "2-digit",
    });
  }
  function fmt$(n) { return n != null ? `$${Number(n).toLocaleString()}` : "—"; }
  function fmtEquip(t) {
    return EQUIPMENT_TYPES.find(e => e.id === t)?.label || t;
  }
  function fmtAppt(s) {
    return ({
      made: "Appt set",
      needs_appointment: "Appt needed",
      no_appointment_needed: "No appt",
      first_come_first_served: "FCFS",
    })[s] || null;
  }
  function apptKind(s) {
    return ({
      made: "ok", needs_appointment: "warn",
      no_appointment_needed: "neutral", first_come_first_served: "neutral",
    })[s] || "neutral";
  }
  const isReeferType = (t) => t === "reefer" || t === "reefer_fresh" || t === "reefer_temp";

  return (
    <div className="sc-board">
      <div className="sc-board-controls">
        <div className="sc-filter-row">
          <label className="sc-filter">
            <span>Near destination</span>
            <select value={filter.destCityId} onChange={e => setFilter(f => ({ ...f, destCityId: e.target.value }))}>
              <option value="">Anywhere</option>
              {cities.map(c => <option key={c.id} value={c.id}>{c.name}, {c.state}</option>)}
            </select>
          </label>
          {filter.destCityId && (
            <label className="sc-filter">
              <span>Radius (mi)</span>
              <select value={filter.radiusMi} onChange={e => setFilter(f => ({ ...f, radiusMi: parseInt(e.target.value, 10) }))}>
                <option value="50">50 mi</option>
                <option value="100">100 mi</option>
                <option value="250">250 mi</option>
                <option value="500">500 mi</option>
              </select>
            </label>
          )}
          <label className="sc-filter">
            <span>Equipment</span>
            <select value={filter.equipment} onChange={e => setFilter(f => ({ ...f, equipment: e.target.value }))}>
              <option value="">Any</option>
              {EQUIPMENT_TYPES.map(t => <option key={t.id} value={t.id}>{t.label}</option>)}
            </select>
          </label>
          <label className="sc-filter">
            <span>Appointment</span>
            <select value={filter.apptStatus}
                    onChange={e => setFilter(f => ({ ...f, apptStatus: e.target.value }))}>
              <option value="">Any</option>
              <option value="made">Appointment set</option>
              <option value="needs_appointment">Needs appointment</option>
              <option value="no_appointment_needed">No appointment</option>
              <option value="first_come_first_served">First come, first served</option>
            </select>
          </label>
          <label className="sc-filter">
            <span>Search PO / pickup / BOL</span>
            <input type="text" value={filter.poQuery}
                   onChange={e => setFilter(f => ({ ...f, poQuery: e.target.value }))}
                   placeholder="e.g. PO-2026-04825"
                   style={{ fontFamily: "inherit", fontSize: 14, padding: "6px 10px",
                            borderRadius: 4, border: "1px solid var(--rule)",
                            background: "var(--paper)", minWidth: 180 }} />
          </label>
          <label className="sc-filter sc-filter-check">
            <input type="checkbox" checked={filter.onlyShare}
              onChange={e => setFilter(f => ({ ...f, onlyShare: e.target.checked }))} />
            <span>Open to consolidation only</span>
          </label>
          <label className="sc-filter sc-filter-check">
            <input type="checkbox" checked={filter.onlyVerified}
              onChange={e => setFilter(f => ({ ...f, onlyVerified: e.target.checked }))} />
            <span>Verified addresses only ✓</span>
          </label>
        </div>
        <div className="sc-board-count">
          {loading ? "Loading…" : `${filtered.length} load${filtered.length === 1 ? "" : "s"}`}
        </div>
      </div>

      {!loading && filtered.length === 0 && (
        <div className="sc-empty">
          {loads.length === 0
            ? "No loads on the board yet. Be the first to post."
            : "No loads match those filters."}
        </div>
      )}

      <ul className="sc-list">
        {filtered.map(l => (
          <li key={l.id} className="sc-card">
            <div className="sc-card-route">
              <div className="sc-card-leg">
                {l.origin_company_name && (
                  <div className="sc-card-co">
                    {l.origin_company_name}
                    {l.origin_address_verified && <span className="sc-verified" title="Address verified">✓</span>}
                  </div>
                )}
                <div className="sc-card-city">{l.origin_city}, {l.origin_state}</div>
                <div className="sc-card-when">
                  Pickup {fmtDate(l.pickup_earliest)}
                  {fmtAppt(l.pickup_appointment_status) && (
                    <span className={`sc-appt sc-appt-${apptKind(l.pickup_appointment_status)}`}>
                      {fmtAppt(l.pickup_appointment_status)}
                    </span>
                  )}
                </div>
              </div>
              <div className="sc-card-arrow">→</div>
              <div className="sc-card-leg">
                {l.dest_company_name && (
                  <div className="sc-card-co">
                    {l.dest_company_name}
                    {l.dest_address_verified && <span className="sc-verified" title="Address verified">✓</span>}
                  </div>
                )}
                <div className="sc-card-city">
                  {l.dest_city}, {l.dest_state}
                  {l._distMi != null && (
                    <span className="sc-dist">{Math.round(l._distMi)}mi</span>
                  )}
                </div>
                <div className="sc-card-when">
                  {l.delivery_earliest ? `Deliver ${fmtDate(l.delivery_earliest)}` : "Delivery flexible"}
                  {fmtAppt(l.delivery_appointment_status) && (
                    <span className={`sc-appt sc-appt-${apptKind(l.delivery_appointment_status)}`}>
                      {fmtAppt(l.delivery_appointment_status)}
                    </span>
                  )}
                </div>
              </div>
            </div>
            <div className="sc-card-meta">
              <span className="sc-tag sc-tag-equip">{fmtEquip(l.equipment_type)}</span>
              {l.willing_to_share && <span className="sc-tag sc-tag-share">Open to share</span>}
              {isReeferType(l.equipment_type) && (l.temp_min_f != null || l.temp_max_f != null) && (
                <span className="sc-tag">{l.temp_min_f ?? "?"}°–{l.temp_max_f ?? "?"}°F</span>
              )}
              <span className="sc-tag-soft">{l.weight_lbs ? `${l.weight_lbs.toLocaleString()} lbs` : "wt n/a"}</span>
              {l.total_pallets != null && <span className="sc-tag-soft">{l.total_pallets} pallets</span>}
              <span className="sc-tag-soft">Rate {fmt$(l.rate_offered_usd)}</span>
              <span className="sc-tag-soft">Value {fmt$(l.cargo_value_usd)}</span>
              {l.po_number && <span className="sc-tag sc-tag-ref">PO {l.po_number}</span>}
            </div>
            {(l.pickup_notes || l.delivery_notes || l.shipper_notes) && (
              <div className="sc-card-notes-block">
                {l.pickup_notes && (
                  <div className="sc-card-note-row">
                    <span className="sc-card-note-label">Pickup</span>
                    <span className="sc-card-note-text">{l.pickup_notes}</span>
                  </div>
                )}
                {l.delivery_notes && (
                  <div className="sc-card-note-row">
                    <span className="sc-card-note-label">Delivery</span>
                    <span className="sc-card-note-text">{l.delivery_notes}</span>
                  </div>
                )}
                {l.shipper_notes && (
                  <div className="sc-card-note-row">
                    <span className="sc-card-note-label">Notes</span>
                    <span className="sc-card-note-text">{l.shipper_notes}</span>
                  </div>
                )}
              </div>
            )}
            <div className="sc-card-foot">
              <span className="sc-shipper">
                {l.shipper_company || l.shipper_name || l.shipper_email}
              </span>
              <button className="sc-interest-btn" onClick={() => setInterestFor(l)}>
                Reach out →
              </button>
            </div>
          </li>
        ))}
      </ul>

      {interestFor && (
        <InterestModal load={interestFor} user={user}
          onClose={() => setInterestFor(null)} />
      )}
    </div>
  );
}

// =============================================================
// MY LOADS — load owner sees their posted loads, who's reached out,
// and can change status (cancel, mark booked, mark completed, repost).
// =============================================================
function MyLoads({ user, refreshKey, onChanged, onEditDraft }) {
  const [loads, setLoads] = useStateSC([]);
  const [loading, setLoading] = useStateSC(true);
  const [interests, setInterests] = useStateSC({}); // {load_id: [interest, ...]}
  const [expanded, setExpanded] = useStateSC({});   // {load_id: bool}
  const [busyId, setBusyId] = useStateSC(null);
  const [filter, setFilter] = useStateSC("active"); // active | all | history

  useEffectSC(() => {
    let alive = true;
    setLoading(true);
    (async () => {
      try {
        const email = encodeURIComponent(user.email);
        const rows = await window.SI_DB.raw.selectAuthed(
          "shipper_loads",
          `select=*&shipper_email=eq.${email}&order=created_at.desc&limit=200`
        );
        if (!alive) return;
        const list = Array.isArray(rows) ? rows : [];
        setLoads(list);

        // Pull interests for all my loads in one query.
        if (list.length) {
          const ids = list.map(l => l.id).join(",");
          const ints = await window.SI_DB.raw.selectAuthed(
            "shipper_load_interests",
            `select=*&load_id=in.(${ids})&order=created_at.desc&limit=500`
          );
          if (!alive) return;
          const grouped = {};
          (Array.isArray(ints) ? ints : []).forEach(i => {
            (grouped[i.load_id] = grouped[i.load_id] || []).push(i);
          });
          setInterests(grouped);
        } else {
          setInterests({});
        }
      } catch {} finally { if (alive) setLoading(false); }
    })();
    return () => { alive = false; };
  }, [refreshKey, user.email]);

  async function setStatus(loadId, status) {
    setBusyId(loadId);
    try {
      const ok = await window.SI_DB.raw.updateAuthed(
        "shipper_loads",
        `id=eq.${encodeURIComponent(loadId)}`,
        { status }
      );
      if (ok) {
        setLoads(ls => ls.map(l => l.id === loadId ? { ...l, status } : l));
        onChanged && onChanged();
      }
    } finally { setBusyId(null); }
  }

  function fmtDate(iso) {
    if (!iso) return "—";
    return new Date(iso).toLocaleString(undefined, {
      month: "short", day: "numeric", hour: "numeric", minute: "2-digit",
    });
  }
  function fmtDateOnly(iso) {
    if (!iso) return "—";
    return new Date(iso).toLocaleString(undefined, { month: "short", day: "numeric" });
  }
  function fmt$(n) { return n != null ? `$${Number(n).toLocaleString()}` : "—"; }
  function fmtEquip(t) { return EQUIPMENT_TYPES.find(e => e.id === t)?.label || t; }
  function fmtApptMyl(s) {
    return ({
      made: "Appt set",
      needs_appointment: "Appt needed",
      no_appointment_needed: "No appt",
      first_come_first_served: "FCFS",
    })[s] || null;
  }
  function apptKindMyl(s) {
    return ({
      made: "ok", needs_appointment: "warn",
      no_appointment_needed: "neutral", first_come_first_served: "neutral",
    })[s] || "neutral";
  }

  const ACTIVE = new Set(["open", "matched", "booked"]);
  const HISTORY = new Set(["completed", "canceled", "expired"]);
  const DRAFTS  = new Set(["draft"]);
  const filtered = loads.filter(l => {
    if (filter === "drafts")  return DRAFTS.has(l.status);
    if (filter === "active")  return ACTIVE.has(l.status);
    if (filter === "history") return HISTORY.has(l.status);
    return true;
  });

  const counts = {
    drafts: loads.filter(l => DRAFTS.has(l.status)).length,
    active: loads.filter(l => ACTIVE.has(l.status)).length,
    history: loads.filter(l => HISTORY.has(l.status)).length,
    all: loads.length,
  };

  return (
    <div className="sc-board">
      <div className="sc-board-controls">
        <div className="sc-myl-tabs">
          <button className={`sc-myl-tab ${filter === "drafts" ? "is-on" : ""}`}
            onClick={() => setFilter("drafts")}>Drafts <span className="sc-myl-n">{counts.drafts}</span></button>
          <button className={`sc-myl-tab ${filter === "active" ? "is-on" : ""}`}
            onClick={() => setFilter("active")}>Active <span className="sc-myl-n">{counts.active}</span></button>
          <button className={`sc-myl-tab ${filter === "history" ? "is-on" : ""}`}
            onClick={() => setFilter("history")}>History <span className="sc-myl-n">{counts.history}</span></button>
          <button className={`sc-myl-tab ${filter === "all" ? "is-on" : ""}`}
            onClick={() => setFilter("all")}>All <span className="sc-myl-n">{counts.all}</span></button>
        </div>
        <div className="sc-board-count">
          {loading ? "Loading…" : `${filtered.length} load${filtered.length === 1 ? "" : "s"}`}
        </div>
      </div>

      {!loading && filtered.length === 0 && (
        <div className="sc-empty">
          {loads.length === 0
            ? "You haven't posted a load yet. Use the Post tab to add your first."
            : `No ${filter} loads.`}
        </div>
      )}

      <ul className="sc-list">
        {filtered.map(l => {
          const ints = interests[l.id] || [];
          const isOpen = expanded[l.id];
          const isBusy = busyId === l.id;
          return (
            <li key={l.id} className={`sc-card sc-myl-card sc-status-${l.status}`}>
              <div className="sc-myl-head">
                <span className={`sc-status-pill sc-status-pill-${l.status}`}>{l.status}</span>
                <span className="sc-myl-posted">Posted {fmtDateOnly(l.created_at)}</span>
              </div>
              <div className="sc-card-route">
                <div className="sc-card-leg">
                  {l.origin_company_name && (
                    <div className="sc-card-co">
                      {l.origin_company_name}
                      {l.origin_address_verified && <span className="sc-verified" title="Address verified">✓</span>}
                    </div>
                  )}
                  <div className="sc-card-city">{l.origin_city}, {l.origin_state}</div>
                  <div className="sc-card-when">
                    Pickup {fmtDate(l.pickup_earliest)}
                    {fmtApptMyl(l.pickup_appointment_status) && (
                      <span className={`sc-appt sc-appt-${apptKindMyl(l.pickup_appointment_status)}`}>
                        {fmtApptMyl(l.pickup_appointment_status)}
                      </span>
                    )}
                  </div>
                </div>
                <div className="sc-card-arrow">→</div>
                <div className="sc-card-leg">
                  {l.dest_company_name && (
                    <div className="sc-card-co">
                      {l.dest_company_name}
                      {l.dest_address_verified && <span className="sc-verified" title="Address verified">✓</span>}
                    </div>
                  )}
                  <div className="sc-card-city">{l.dest_city}, {l.dest_state}</div>
                  <div className="sc-card-when">
                    {l.delivery_earliest ? `Deliver ${fmtDate(l.delivery_earliest)}` : "Delivery flexible"}
                    {fmtApptMyl(l.delivery_appointment_status) && (
                      <span className={`sc-appt sc-appt-${apptKindMyl(l.delivery_appointment_status)}`}>
                        {fmtApptMyl(l.delivery_appointment_status)}
                      </span>
                    )}
                  </div>
                </div>
              </div>
              <div className="sc-card-meta">
                <span className="sc-tag sc-tag-equip">{fmtEquip(l.equipment_type)}</span>
                {l.willing_to_share && <span className="sc-tag sc-tag-share">Open to share</span>}
                  <span className="sc-tag-soft">{l.weight_lbs ? `${l.weight_lbs.toLocaleString()} lbs` : "wt n/a"}</span>
                {l.total_pallets != null && <span className="sc-tag-soft">{l.total_pallets} pallets</span>}
                <span className="sc-tag-soft">Rate {fmt$(l.rate_offered_usd)}</span>
                {l.po_number && <span className="sc-tag sc-tag-ref">PO {l.po_number}</span>}
              </div>

              <div className="sc-myl-foot">
                <button className="sc-myl-toggle"
                        onClick={() => setExpanded(s => ({ ...s, [l.id]: !s[l.id] }))}>
                  {ints.length === 0 ? "No reach-outs yet" :
                    `${isOpen ? "▾" : "▸"} ${ints.length} reach-out${ints.length === 1 ? "" : "s"}`}
                </button>
                <div className="sc-myl-actions">
                  {l.status === "draft" && (
                    <>
                      <button className="sc-myl-btn" disabled={isBusy}
                              onClick={() => onEditDraft && onEditDraft(l)}>
                        Edit
                      </button>
                      <button className="sc-myl-btn" disabled={isBusy}
                              onClick={() => {
                                if (!l.pickup_earliest || !l.total_pallets) {
                                  alert("This draft is missing the pickup time or pallet count. Click Edit, fill those in, and post the load.");
                                  return;
                                }
                                setStatus(l.id, "open");
                              }}>Publish</button>
                      <button className="sc-myl-btn sc-myl-btn-danger" disabled={isBusy}
                              onClick={() => {
                                if (confirm("Delete this draft? This can't be undone.")) {
                                  setStatus(l.id, "canceled");
                                }
                              }}>Delete</button>
                    </>
                  )}
                  {(l.status === "open" || l.status === "matched") && (
                    <button className="sc-myl-btn" disabled={isBusy}
                            onClick={() => setStatus(l.id, "booked")}>Mark booked</button>
                  )}
                  {l.status === "booked" && (
                    <button className="sc-myl-btn" disabled={isBusy}
                            onClick={() => setStatus(l.id, "completed")}>Mark completed</button>
                  )}
                  {(l.status === "open" || l.status === "matched" || l.status === "booked") && (
                    <button className="sc-myl-btn sc-myl-btn-danger" disabled={isBusy}
                            onClick={() => {
                              if (confirm("Cancel this load? It'll come off the board.")) {
                                setStatus(l.id, "canceled");
                              }
                            }}>Cancel</button>
                  )}
                  {l.status === "canceled" && (
                    <button className="sc-myl-btn" disabled={isBusy}
                            onClick={() => setStatus(l.id, "open")}>Repost</button>
                  )}
                </div>
              </div>

              {isOpen && ints.length > 0 && (
                <div className="sc-myl-interests">
                  {ints.map(i => (
                    <div key={i.id} className="sc-myl-int">
                      <div className="sc-myl-int-head">
                        <span className={`sc-role sc-role-${i.party_role}`}>{i.party_role}</span>
                        <span className="sc-myl-int-name">
                          {i.party_name || i.party_email}
                          {i.party_company && <span className="sc-myl-int-co"> · {i.party_company}</span>}
                        </span>
                        <span className="sc-myl-int-when">{fmtDate(i.created_at)}</span>
                      </div>
                      {i.message && <div className="sc-myl-int-msg">"{i.message}"</div>}
                      <a className="sc-myl-int-mail"
                         href={`mailto:${i.party_email}?subject=${encodeURIComponent(`Re: Your interest in ${l.origin_city} → ${l.dest_city}`)}`}>
                        ✉ {i.party_email}
                      </a>
                    </div>
                  ))}
                </div>
              )}
            </li>
          );
        })}
      </ul>
    </div>
  );
}

// =============================================================
// INTEREST MODAL — capture a "reach out" from a shipper or carrier.
// =============================================================
function InterestModal({ load, user, onClose }) {
  const [role, setRole] = useStateSC("shipper");
  const [name, setName] = useStateSC(user.name || "");
  const [company, setCompany] = useStateSC("");
  const [message, setMessage] = useStateSC("");
  const [busy, setBusy] = useStateSC(false);
  const [sent, setSent] = useStateSC(false);
  const [err, setErr] = useStateSC(null);

  async function submit(e) {
    e.preventDefault();
    setBusy(true); setErr(null);
    try {
      const ok = await window.SI_DB.raw.insertAuthed("shipper_load_interests", {
        load_id: load.id,
        party_email: user.email,
        party_name: name.trim() || null,
        party_company: company.trim() || null,
        party_role: role,
        message: message.trim() || null,
      });
      if (!ok) { setErr("Couldn't send. Check the schema is applied."); return; }

      // Fire-and-forget email to the load owner. We don't block the user's
      // success state on this — if email fails, the interest row is still
      // there and the shipper sees it next time they check My Loads.
      try {
        const sess = window.SI_DB.auth.readSession();
        if (sess && sess.access_token) {
          fetch("/api/notify-load-interest", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              Authorization: `Bearer ${sess.access_token}`,
            },
            body: JSON.stringify({
              load_id: load.id,
              role,
              name: name.trim() || null,
              company: company.trim() || null,
              message: message.trim() || null,
            }),
          }).catch(() => {});
        }
      } catch (_) {}

      setSent(true);
    } catch (e) {
      setErr(String(e && e.message || e));
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="sc-modal-bg" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="sc-modal">
        <button onClick={onClose} className="sc-modal-x" aria-label="Close">×</button>
        <h3 className="sc-modal-h">Reach out about this load</h3>
        <p className="sc-modal-sub">
          {load.origin_city}, {load.origin_state} → {load.dest_city}, {load.dest_state}
        </p>
        {sent ? (
          <div className="sc-sent">
            <div style={{ fontSize: 32, marginBottom: 8 }}>✓</div>
            <div style={{ fontFamily: "var(--font-serif)", fontSize: 20, marginBottom: 6 }}>Sent.</div>
            <p style={{ color: "var(--ink-soft)", fontSize: 14, lineHeight: 1.55 }}>
              We just emailed the shipper with your message and your email address. If they want this load, they reply straight to you.
            </p>
            <button className="sc-submit" onClick={onClose}>Done</button>
          </div>
        ) : (
          <form onSubmit={submit}>
            <div className="sc-form-grid sc-form-grid-2">
              <label className="sc-field">
                <span>I'm a…</span>
                <select value={role} onChange={e => setRole(e.target.value)}>
                  <option value="shipper">Another shipper · want to share this truck</option>
                  <option value="carrier">Carrier · want to take this load</option>
                  <option value="broker">Broker</option>
                </select>
              </label>
              <label className="sc-field">
                <span>Your name</span>
                <input type="text" value={name} onChange={e => setName(e.target.value)} required />
              </label>
            </div>
            <label className="sc-field">
              <span>Company</span>
              <input type="text" value={company} onChange={e => setCompany(e.target.value)} />
            </label>
            <label className="sc-field">
              <span>Message</span>
              <textarea value={message} onChange={e => setMessage(e.target.value)} rows={4}
                placeholder="What you'd add (extra pallets / lane match), available equipment, MC#, etc." />
            </label>
            {err && <div className="sc-err">{err}</div>}
            <button type="submit" className="sc-submit" disabled={busy}>
              {busy ? "Sending…" : "Send →"}
            </button>
          </form>
        )}
      </div>
    </div>
  );
}

// =============================================================
// SHIPPERS CONNECT PAGE
// =============================================================
function ShippersConnectPage({ onNav }) {
  const [user, setUser] = useStateSC(null);
  const [cities, setCities] = useStateSC([]);
  const [tab, setTab] = useStateSC("browse");
  const [refreshKey, setRefreshKey] = useStateSC(0);
  const [postedFlash, setPostedFlash] = useStateSC(false);
  // When the user clicks "Edit" on a draft in My Loads, we set this so
  // the post form re-mounts with the draft's fields pre-filled. Cleared
  // after a successful save / publish.
  const [editingDraft, setEditingDraft] = useStateSC(null);

  useEffectSC(() => {
    let alive = true;
    if (window.SI_DB && window.SI_DB.auth && window.SI_DB.auth.getCurrentUser) {
      window.SI_DB.auth.getCurrentUser().then(u => { if (alive) setUser(u || null); }).catch(() => {});
    }
    if (window.SI_DB && window.SI_DB.cities) {
      window.SI_DB.cities().then(c => { if (alive) setCities(Array.isArray(c) ? c : []); }).catch(() => {});
    }
    return () => { alive = false; };
  }, []);

  const isAuthed = !!(user && user.email);

  return (
    <div className="sc-page">
      <style>{`
        .sc-page { background: var(--paper); padding-bottom: 96px; min-height: 100vh; }
        .sc-hero { max-width: 1200px; margin: 0 auto; padding: 56px 24px 24px; }
        .sc-back {
          display: inline-flex; gap: 6px; font-family: var(--font-mono); font-size: 11px;
          letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-soft);
          background: transparent; border: 0; cursor: pointer; padding: 0 0 16px;
        }
        .sc-back:hover { color: var(--ink); }
        .sc-mark {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.32em;
          text-transform: uppercase; color: var(--ink-soft); margin-bottom: 14px;
          display: inline-flex; align-items: center; gap: 10px;
        }
        .sc-mark .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%;
          background: oklch(0.50 0.18 250); }
        .sc-title { font-family: var(--font-serif); font-size: 56px; line-height: 1.04;
          letter-spacing: -0.028em; margin: 0 0 16px; }
        .sc-title em { font-style: italic; color: oklch(0.50 0.18 250); }
        .sc-dek { font-size: 16px; line-height: 1.55; color: var(--ink-soft); margin: 0; max-width: 760px; }
        @media (max-width: 700px) { .sc-title { font-size: 38px; } }

        .sc-tabs {
          max-width: 1200px; margin: 24px auto 0; padding: 0 24px;
          border-bottom: 1px solid var(--rule); display: flex; gap: 0;
        }
        .sc-tab {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em;
          text-transform: uppercase; padding: 14px 20px;
          background: transparent; border: 0; cursor: pointer;
          color: var(--ink-soft); border-bottom: 2px solid transparent;
        }
        .sc-tab:hover { color: var(--ink); }
        .sc-tab.is-active { color: var(--ink); border-bottom-color: var(--ink); font-weight: 700; }

        .sc-body { max-width: 1200px; margin: 24px auto 0; padding: 0 24px; }

        .sc-flash {
          background: oklch(0.96 0.04 145); border: 1px solid oklch(0.85 0.08 145);
          color: oklch(0.40 0.14 145); padding: 12px 16px; border-radius: 6px;
          margin-bottom: 16px; font-size: 14px;
        }

        .sc-form { display: flex; flex-direction: column; gap: 12px;
                   max-width: 880px; }
        .sc-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
        .sc-form-grid-3 { grid-template-columns: 1fr 1fr 1fr; }
        .sc-form-grid-2 { grid-template-columns: 1fr 1fr; }
        @media (max-width: 700px) {
          .sc-form-grid, .sc-form-grid-3, .sc-form-grid-2 { grid-template-columns: 1fr; }
        }
        .sc-form-col { display: flex; flex-direction: column; gap: 12px; }
        .sc-form-h {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em;
          text-transform: uppercase; color: var(--ink-soft); margin: 0 0 4px;
          padding-bottom: 6px; border-bottom: 1px solid var(--rule);
        }
        .sc-field { display: flex; flex-direction: column; gap: 6px; }
        .sc-field > span {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
          text-transform: uppercase; color: var(--ink-soft);
        }
        .sc-hint { font-family: var(--font-sans); font-size: 11px; letter-spacing: 0;
                   text-transform: none; font-style: italic; margin-left: 4px; }
        .sc-field input, .sc-field select, .sc-field textarea {
          font-family: inherit; font-size: 14px; padding: 10px 12px;
          border: 1px solid var(--rule); border-radius: 6px; background: var(--paper);
          color: var(--ink); outline: none;
        }
        .sc-field input:focus, .sc-field select:focus, .sc-field textarea:focus {
          border-color: var(--ink);
        }
        .sc-err {
          background: oklch(0.96 0.05 25); border: 1px solid oklch(0.85 0.10 25);
          color: oklch(0.40 0.18 25); padding: 10px 14px; border-radius: 6px;
          font-size: 13px;
        }
        .sc-submit {
          font-family: inherit; font-size: 15px; padding: 14px 28px; border-radius: 6px;
          background: var(--ink); color: #fff; border: 1px solid var(--ink);
          cursor: pointer; font-weight: 600; letter-spacing: 0.02em; align-self: flex-start;
          margin-top: 16px;
        }
        .sc-submit:hover { opacity: 0.9; }
        .sc-submit:disabled { opacity: 0.5; cursor: not-allowed; }

        /* === New polished post-load layout === */
        .sc-form-page {
          display: flex; flex-direction: column; gap: 18px; max-width: 1100px;
          margin: 0 auto; padding-bottom: 96px;
        }
        .sc-form-hero {
          padding: 24px 0 8px;
        }
        .sc-form-hero-eyebrow {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.32em;
          text-transform: uppercase; color: var(--ink-soft); margin-bottom: 12px;
        }
        .sc-form-hero-h {
          font-family: var(--font-serif); font-size: 38px; line-height: 1.05;
          letter-spacing: -0.025em; margin: 0 0 10px;
        }
        @media (max-width: 700px) { .sc-form-hero-h { font-size: 28px; } }
        .sc-form-hero-sub {
          font-size: 15px; line-height: 1.55; color: var(--ink-soft);
          margin: 0 0 22px; max-width: 640px;
        }
        .sc-progress {
          display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
          padding: 14px 18px; background: #fff;
          border: 1px solid var(--rule); border-radius: 8px;
        }
        .sc-progress-label {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
          text-transform: uppercase; color: var(--ink-soft);
          white-space: nowrap;
        }
        .sc-progress-bar {
          flex: 1; height: 6px; min-width: 120px;
          background: var(--paper-2); border-radius: 3px; overflow: hidden;
        }
        .sc-progress-fill {
          height: 100%; background: oklch(0.50 0.18 145);
          transition: width 250ms cubic-bezier(.2,.8,.2,1);
        }
        .sc-progress-dots { display: flex; gap: 6px; }
        .sc-progress-dot {
          width: 9px; height: 9px; border-radius: 50%;
          background: var(--paper-2); border: 1px solid var(--rule);
          transition: all 0.15s;
        }
        .sc-progress-dot.is-done {
          background: oklch(0.50 0.18 145); border-color: oklch(0.40 0.14 145);
        }

        .sc-section-grid {
          display: grid; grid-template-columns: 1fr 1fr; gap: 18px;
        }
        @media (max-width: 880px) { .sc-section-grid { grid-template-columns: 1fr; } }

        .sc-card-section {
          background: #fff; border: 1px solid var(--rule); border-radius: 10px;
          padding: 24px 26px; transition: border-color 0.2s;
        }
        .sc-card-section.is-done { border-color: oklch(0.80 0.06 145); }
        @media (max-width: 600px) { .sc-card-section { padding: 18px 18px; } }
        .sc-section-head {
          display: grid; grid-template-columns: 36px 1fr; gap: 14px;
          align-items: start; margin-bottom: 18px;
          padding-bottom: 14px; border-bottom: 1px solid var(--rule);
        }
        .sc-section-n {
          width: 32px; height: 32px; border-radius: 50%;
          background: var(--paper-2); border: 1px solid var(--rule);
          display: flex; align-items: center; justify-content: center;
          font-family: var(--font-serif); font-size: 16px; font-weight: 700;
          color: var(--ink-soft); transition: all 0.2s;
        }
        .is-done .sc-section-n {
          background: oklch(0.55 0.18 145); border-color: oklch(0.45 0.16 145);
          color: #fff;
        }
        .sc-section-title {
          font-family: var(--font-serif); font-size: 22px; letter-spacing: -0.015em;
          line-height: 1.15; margin: 0 0 4px;
        }
        .sc-section-sub {
          font-size: 13px; line-height: 1.5; color: var(--ink-soft); margin: 0;
        }
        .sc-section-body {
          display: flex; flex-direction: column; gap: 14px;
        }

        .sc-no-hazmat {
          font-size: 13px; line-height: 1.55; color: oklch(0.45 0.16 50);
          background: oklch(0.97 0.04 50); border: 1px solid oklch(0.85 0.10 50);
          padding: 10px 14px; border-radius: 6px; margin: 0;
        }
        .sc-no-hazmat strong { color: oklch(0.40 0.18 50); font-weight: 700; }
        .sc-share-toggle {
          display: flex; align-items: flex-start; gap: 12px; cursor: pointer;
          padding: 14px 16px;
          background: oklch(0.97 0.04 145); border: 1px solid oklch(0.85 0.08 145);
          border-radius: 8px; font-size: 14px; line-height: 1.55;
        }
        .sc-share-toggle input { margin-top: 4px; }

        .sc-form-footer {
          position: sticky; bottom: 16px; z-index: 10;
          display: flex; justify-content: space-between; align-items: center;
          gap: 16px; padding: 14px 20px; margin-top: 12px;
          background: var(--ink); color: #fff; border-radius: 10px;
          box-shadow: 0 8px 28px rgba(0,0,0,0.18);
        }
        @media (max-width: 600px) {
          .sc-form-footer { flex-direction: column; align-items: stretch; }
        }
        .sc-form-footer-summary {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
          text-transform: uppercase;
        }
        .sc-form-footer-ok { color: oklch(0.85 0.16 145); }
        .sc-form-footer-pending { color: oklch(0.85 0.06 60); }
        .sc-submit-big {
          font-family: inherit; font-size: 15px; padding: 14px 28px;
          border-radius: 6px; background: #fff; color: var(--ink);
          border: 1px solid #fff; cursor: pointer; font-weight: 700;
          letter-spacing: 0.02em; white-space: nowrap;
        }
        .sc-submit-big:hover:not(:disabled) {
          background: oklch(0.55 0.18 145); border-color: oklch(0.55 0.18 145); color: #fff;
        }
        .sc-submit-big:disabled { opacity: 0.6; cursor: not-allowed; }
        .sc-submit-draft {
          font-family: inherit; font-size: 14px; padding: 14px 22px;
          border-radius: 6px; background: transparent; color: #fff;
          border: 1px solid rgba(255,255,255,0.4); cursor: pointer;
          font-weight: 500; letter-spacing: 0.02em; white-space: nowrap;
        }
        .sc-submit-draft:hover:not(:disabled) {
          background: rgba(255,255,255,0.08); border-color: #fff;
        }
        .sc-submit-draft:disabled { opacity: 0.4; cursor: not-allowed; }

        /* Board */
        .sc-board { display: flex; flex-direction: column; gap: 14px; }
        .sc-board-controls {
          display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between;
          align-items: center; padding: 14px 16px; border-radius: 8px;
          background: linear-gradient(180deg, oklch(0.97 0.02 250) 0%, oklch(0.99 0.01 250) 100%);
          border: 1px solid oklch(0.90 0.04 250);
          border-left: 4px solid oklch(0.50 0.18 250);
        }
        .sc-filter-row { display: flex; flex-wrap: wrap; gap: 12px; }
        .sc-filter { display: flex; flex-direction: column; gap: 4px; }
        .sc-filter > span {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
          text-transform: uppercase; color: oklch(0.45 0.10 250);
          font-weight: 600;
        }
        .sc-filter select {
          font-family: inherit; font-size: 14px; padding: 6px 10px; border-radius: 4px;
          border: 1px solid var(--rule); background: var(--paper);
          transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
        }
        .sc-filter select:hover {
          border-color: oklch(0.50 0.18 250); background: #fff;
          box-shadow: 0 0 0 3px oklch(0.95 0.04 250);
        }
        .sc-filter select:focus {
          outline: none; border-color: oklch(0.50 0.18 250);
          box-shadow: 0 0 0 3px oklch(0.90 0.06 250);
        }
        .sc-filter-check {
          flex-direction: row; align-items: center; gap: 6px; font-size: 13px;
          color: var(--ink); cursor: pointer;
        }
        .sc-board-count {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
          color: var(--ink-soft);
        }
        .sc-empty {
          padding: 64px 24px; text-align: center; color: var(--ink-soft);
          font-style: italic; background: var(--paper-2); border-radius: 8px;
        }
        .sc-list { list-style: none; padding: 0; margin: 0; display: flex;
                   flex-direction: column; gap: 12px; }
        .sc-card {
          background: #fff; border: 1px solid var(--rule); border-radius: 8px;
          padding: 18px 20px;
          border-left: 4px solid oklch(0.50 0.18 250);
          transition: box-shadow 0.18s, transform 0.12s, border-color 0.18s;
        }
        .sc-card:hover {
          box-shadow: 0 6px 22px rgba(20, 30, 60, 0.10);
          transform: translateY(-1px);
          border-left-color: oklch(0.45 0.20 250);
        }
        .sc-card-route {
          display: grid; grid-template-columns: 1fr auto 1fr; gap: 16px;
          align-items: center; margin-bottom: 14px;
        }
        @media (max-width: 600px) { .sc-card-route { grid-template-columns: 1fr; } }
        .sc-card-leg { min-width: 0; }
        .sc-card-city {
          font-family: var(--font-serif); font-size: 18px; letter-spacing: -0.01em;
          line-height: 1.2; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
        }
        .sc-card-when {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em;
          color: var(--ink-soft); margin-top: 4px;
        }
        .sc-card-arrow {
          color: var(--ink-soft); font-size: 22px; line-height: 1;
        }
        @media (max-width: 600px) { .sc-card-arrow { transform: rotate(90deg); } }
        .sc-dist {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.06em;
          background: oklch(0.94 0.06 250); color: oklch(0.40 0.16 250);
          padding: 2px 7px; border-radius: 3px;
        }
        .sc-card-meta {
          display: flex; flex-wrap: wrap; gap: 8px; font-family: var(--font-mono);
          font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
          margin-bottom: 10px;
        }
        .sc-tag, .sc-tag-soft {
          padding: 3px 8px; border-radius: 3px; border: 1px solid var(--rule);
          background: var(--paper-2); color: var(--ink-soft);
        }
        .sc-tag-equip { background: var(--ink); color: #fff; border-color: var(--ink); font-weight: 700; }
        .sc-tag-share { background: oklch(0.94 0.06 145); color: oklch(0.40 0.14 145); border-color: oklch(0.85 0.08 145); }
        .sc-tag-haz { background: oklch(0.94 0.06 25); color: oklch(0.40 0.18 25); border-color: oklch(0.85 0.10 25); }
        .sc-tag-ref {
          background: oklch(0.94 0.06 250); color: oklch(0.40 0.16 250);
          border-color: oklch(0.85 0.08 250); font-weight: 700;
        }
        .sc-card-co {
          font-size: 13px; font-weight: 600; color: var(--ink);
          margin-bottom: 4px; display: flex; align-items: center; gap: 6px;
          flex-wrap: wrap;
        }
        .sc-verified {
          display: inline-flex; align-items: center; justify-content: center;
          width: 16px; height: 16px; border-radius: 50%;
          background: oklch(0.55 0.18 145); color: #fff;
          font-size: 10px; font-weight: 700;
        }
        .sc-appt {
          display: inline-block; margin-left: 8px; padding: 1px 7px;
          font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.08em;
          text-transform: uppercase; border-radius: 3px; font-weight: 700;
        }
        .sc-appt-ok      { background: oklch(0.94 0.06 145); color: oklch(0.36 0.14 145); }
        .sc-appt-warn    { background: oklch(0.94 0.06 50);  color: oklch(0.40 0.18 50); }
        .sc-appt-neutral { background: var(--paper-2); color: var(--ink-soft); border: 1px solid var(--rule); }
        .sc-card-notes-block {
          background: var(--paper-2); border-radius: 4px; padding: 8px 10px;
          margin-bottom: 12px; display: flex; flex-direction: column; gap: 6px;
        }
        .sc-card-note-row {
          display: grid; grid-template-columns: 70px 1fr; gap: 10px;
          font-size: 12px; line-height: 1.5;
        }
        .sc-card-note-label {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.12em;
          text-transform: uppercase; color: var(--ink-soft); padding-top: 1px;
        }
        .sc-card-note-text { color: var(--ink); font-style: italic; }
        .sc-card-notes {
          font-style: italic; color: var(--ink); padding: 10px 12px;
          background: var(--paper-2); border-radius: 4px; font-size: 13px;
          line-height: 1.5; margin-bottom: 12px;
        }
        .sc-card-foot {
          display: flex; justify-content: space-between; align-items: center;
          padding-top: 12px;
          border-top: 1px dashed oklch(0.85 0.04 250);
        }
        .sc-shipper {
          font-size: 13px; color: var(--ink); font-weight: 600;
        }
        .sc-interest-btn {
          font-family: inherit; font-size: 13px; padding: 8px 18px;
          border-radius: 4px; cursor: pointer; border: 1px solid oklch(0.50 0.18 250);
          background: #fff; color: oklch(0.40 0.18 250); font-weight: 600;
          transition: background 0.15s, color 0.15s, box-shadow 0.15s, transform 0.1s;
        }
        .sc-interest-btn:hover {
          background: oklch(0.50 0.18 250); color: #fff;
          box-shadow: 0 4px 12px oklch(0.50 0.18 250 / 0.30);
          transform: translateY(-1px);
        }

        /* Modal */
        .sc-modal-bg {
          position: fixed; inset: 0; background: rgba(20, 18, 14, 0.55); z-index: 100;
          display: flex; align-items: center; justify-content: center; padding: 24px;
        }
        .sc-modal {
          background: #fff; border-radius: 10px; max-width: 560px; width: 100%;
          padding: 28px; position: relative; max-height: 90vh; overflow-y: auto;
        }
        .sc-modal-x {
          position: absolute; top: 14px; right: 14px; background: transparent;
          border: 0; cursor: pointer; font-size: 22px; color: var(--ink-soft);
        }
        .sc-modal-h {
          font-family: var(--font-serif); font-size: 22px; letter-spacing: -0.015em;
          margin: 0 0 4px;
        }
        .sc-modal-sub { color: var(--ink-soft); font-size: 13px; margin: 0 0 18px; }
        .sc-sent { text-align: center; padding: 24px 0; }

        /* My Loads */
        .sc-myl-tabs { display: flex; gap: 6px; }
        .sc-myl-tab {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
          text-transform: uppercase; padding: 8px 14px; cursor: pointer;
          background: var(--paper-2); border: 1px solid var(--rule); border-radius: 4px;
          color: var(--ink-soft); display: inline-flex; align-items: center; gap: 8px;
        }
        .sc-myl-tab:hover { color: var(--ink); }
        .sc-myl-tab.is-on { background: var(--ink); color: #fff; border-color: var(--ink); }
        .sc-myl-n {
          background: rgba(255,255,255,0.18); padding: 1px 7px; border-radius: 10px;
          font-size: 10px;
        }
        .sc-myl-tab:not(.is-on) .sc-myl-n { background: var(--paper); color: var(--ink-soft); }

        .sc-myl-card { position: relative; }
        .sc-myl-head {
          display: flex; justify-content: space-between; align-items: center;
          margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px dashed var(--rule);
        }
        .sc-status-pill {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
          text-transform: uppercase; padding: 3px 10px; border-radius: 3px;
          font-weight: 700;
        }
        .sc-status-pill-draft     { background: var(--paper-2); color: var(--ink-soft); border: 1px dashed var(--rule); }
        .sc-status-pill-open      { background: oklch(0.94 0.06 145); color: oklch(0.36 0.14 145); }
        .sc-status-pill-matched   { background: oklch(0.94 0.06 250); color: oklch(0.36 0.16 250); }
        .sc-status-pill-booked    { background: oklch(0.94 0.06 80);  color: oklch(0.36 0.14 80); }
        .sc-status-pill-completed { background: var(--paper-2); color: var(--ink-soft); }
        .sc-status-pill-canceled  { background: oklch(0.94 0.05 25); color: oklch(0.40 0.16 25); }
        .sc-status-pill-expired   { background: var(--paper-2); color: var(--ink-soft); }

        .sc-myl-posted {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.06em;
          color: var(--ink-soft);
        }

        .sc-myl-foot {
          display: flex; justify-content: space-between; align-items: center;
          padding-top: 12px; border-top: 1px solid var(--rule); flex-wrap: wrap; gap: 10px;
        }
        .sc-myl-toggle {
          font-family: inherit; font-size: 13px; padding: 6px 0;
          background: transparent; border: 0; cursor: pointer; color: var(--ink);
          font-weight: 600;
        }
        .sc-myl-actions { display: flex; gap: 6px; flex-wrap: wrap; }
        .sc-myl-btn {
          font-family: inherit; font-size: 12px; padding: 6px 12px;
          border-radius: 4px; cursor: pointer; border: 1px solid var(--ink);
          background: #fff; color: var(--ink); font-weight: 600;
        }
        .sc-myl-btn:hover:not(:disabled) { background: var(--ink); color: #fff; }
        .sc-myl-btn:disabled { opacity: 0.5; cursor: not-allowed; }
        .sc-myl-btn-danger {
          border-color: oklch(0.55 0.18 25); color: oklch(0.45 0.18 25);
        }
        .sc-myl-btn-danger:hover:not(:disabled) {
          background: oklch(0.50 0.20 25); color: #fff; border-color: oklch(0.50 0.20 25);
        }

        .sc-myl-interests {
          margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--rule);
          display: flex; flex-direction: column; gap: 10px;
        }
        .sc-myl-int {
          background: var(--paper-2); border: 1px solid var(--rule); border-radius: 6px;
          padding: 12px 14px;
        }
        .sc-myl-int-head {
          display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
          font-size: 13px; margin-bottom: 6px;
        }
        .sc-role {
          font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.16em;
          text-transform: uppercase; padding: 2px 8px; border-radius: 3px; font-weight: 700;
        }
        .sc-role-shipper { background: oklch(0.94 0.06 145); color: oklch(0.36 0.14 145); }
        .sc-role-carrier { background: oklch(0.94 0.06 250); color: oklch(0.36 0.16 250); }
        .sc-role-broker  { background: oklch(0.94 0.06 50);  color: oklch(0.36 0.14 50); }
        .sc-myl-int-name { font-weight: 600; }
        .sc-myl-int-co { color: var(--ink-soft); font-weight: 400; }
        .sc-myl-int-when {
          margin-left: auto; font-family: var(--font-mono); font-size: 10px;
          color: var(--ink-soft); letter-spacing: 0.04em;
        }
        .sc-myl-int-msg {
          font-style: italic; line-height: 1.55; font-size: 13px;
          padding: 8px 0; color: var(--ink);
        }
        .sc-myl-int-mail {
          font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.04em;
          color: oklch(0.40 0.18 250); text-decoration: none;
        }
        .sc-myl-int-mail:hover { text-decoration: underline; }

        /* Cargo Builder */
        .cb-wrap {
          background: #fff; border: 1px solid var(--rule); border-radius: 10px;
          padding: 20px; margin-top: 12px;
        }
        .cb-head {
          display: flex; justify-content: space-between; align-items: flex-start;
          margin-bottom: 16px; gap: 16px;
        }
        .cb-eyebrow {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.18em;
          text-transform: uppercase; color: var(--ink-soft); margin-bottom: 4px;
        }
        .cb-sub { font-size: 13px; color: var(--ink-soft); margin: 0; }
        .cb-clear {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
          text-transform: uppercase; padding: 6px 12px; border-radius: 4px;
          background: transparent; border: 1px solid var(--rule); color: var(--ink-soft);
          cursor: pointer; white-space: nowrap;
        }
        .cb-clear:hover { color: oklch(0.50 0.18 25); border-color: oklch(0.50 0.18 25); }

        .cb-palette {
          display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
          margin-bottom: 18px;
        }
        @media (max-width: 600px) { .cb-palette { grid-template-columns: 1fr 1fr; } }
        .cb-add {
          display: grid; grid-template-columns: 44px 1fr 18px; gap: 10px;
          align-items: center; background: var(--paper-2);
          border: 1px solid var(--rule); border-radius: 6px;
          padding: 10px 12px; cursor: pointer; font-family: inherit;
          text-align: left; transition: all 0.15s;
        }
        .cb-add:hover {
          border-color: oklch(0.50 0.18 250); background: #fff;
          transform: translateY(-1px);
        }
        .cb-add-icon {
          width: 44px; height: 44px; display: flex; align-items: center;
          justify-content: center; background: oklch(0.96 0.01 60);
          border-radius: 4px;
        }
        .cb-add-name {
          font-family: var(--font-serif); font-size: 14px; font-weight: 600;
          letter-spacing: -0.005em;
        }
        .cb-add-sub {
          font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.1em;
          text-transform: uppercase; color: var(--ink-soft); margin-top: 2px;
        }
        .cb-add-plus {
          font-size: 18px; color: oklch(0.50 0.18 250); font-weight: 700;
        }

        .cb-truck-wrap { margin-bottom: 16px; }
        .cb-truck-label {
          display: flex; justify-content: space-between; align-items: center;
          margin-bottom: 8px;
        }
        .cb-truck-label-tip {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.16em;
          text-transform: uppercase; color: var(--ink-soft);
          padding: 4px 10px; background: var(--paper-2); border-radius: 3px;
        }
        .cb-truck-label-mid {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
          text-transform: uppercase; color: var(--ink-soft);
        }
        .cb-truck-stage {
          background: oklch(0.99 0.005 60); border: 1px solid var(--rule);
          border-radius: 6px; padding: 10px;
          overflow-x: auto;
        }
        .cb-truck-svg {
          display: block; width: 100%; height: 110px;
          min-width: 600px;
        }
        .cb-truck-svg.is-overflow {
          background: oklch(0.99 0.02 25);
        }
        .cb-pallet { cursor: pointer; transition: filter 0.15s; }
        .cb-pallet:hover { filter: brightness(1.05); }
        .cb-pallet.is-active rect { stroke-width: 3 !important; }

        .cb-no-truck {
          padding: 24px; text-align: center; color: var(--ink-soft);
          background: var(--paper-2); border-radius: 6px; font-size: 13px;
          margin-bottom: 16px;
        }

        .cb-stats {
          display: grid; grid-template-columns: 1fr 1fr; gap: 16px;
          margin-bottom: 14px;
        }
        @media (max-width: 600px) { .cb-stats { grid-template-columns: 1fr; } }
        .cb-stat-row {
          display: flex; justify-content: space-between; align-items: baseline;
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
          margin-bottom: 6px;
        }
        .cb-stat-label {
          text-transform: uppercase; letter-spacing: 0.14em; color: var(--ink-soft);
        }
        .cb-stat-val { color: var(--ink); font-weight: 600; }
        .cb-bar {
          height: 8px; background: var(--paper-2); border-radius: 4px;
          overflow: hidden;
        }
        .cb-bar-fill {
          height: 100%; transition: width 250ms cubic-bezier(.2,.8,.2,1);
          border-radius: 4px;
        }

        .cb-verdict {
          display: flex; align-items: center; gap: 10px;
          padding: 12px 14px; border-radius: 6px; font-size: 14px;
          line-height: 1.5; margin-bottom: 14px;
        }
        .cb-verdict-ok {
          background: oklch(0.96 0.04 145); border: 1px solid oklch(0.85 0.08 145);
          color: oklch(0.36 0.14 145);
        }
        .cb-verdict-warn {
          background: oklch(0.96 0.04 25); border: 1px solid oklch(0.85 0.10 25);
          color: oklch(0.40 0.18 25);
        }
        .cb-verdict-neutral {
          background: var(--paper-2); border: 1px solid var(--rule);
          color: var(--ink-soft); font-style: italic;
        }
        .cb-check, .cb-x {
          display: inline-flex; align-items: center; justify-content: center;
          width: 22px; height: 22px; border-radius: 50%; font-weight: 700;
          flex-shrink: 0;
        }
        .cb-check { background: oklch(0.55 0.18 145); color: #fff; }
        .cb-x { background: oklch(0.55 0.18 25); color: #fff; }

        .cb-list {
          list-style: none; padding: 0; margin: 0;
          border-top: 1px solid var(--rule);
        }
        .cb-list-item {
          display: grid; grid-template-columns: auto 1fr auto auto; gap: 12px;
          align-items: center; padding: 10px 4px; cursor: pointer;
          border-bottom: 1px solid var(--rule); transition: background 0.1s;
        }
        .cb-list-item:hover { background: var(--paper-2); }
        .cb-list-item.is-active { background: oklch(0.97 0.02 250); }
        .cb-list-n {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
          color: var(--ink-soft); width: 28px;
        }
        .cb-list-name {
          font-size: 14px; display: flex; align-items: baseline; gap: 8px;
        }
        .cb-list-dim {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.06em;
          color: var(--ink-soft);
        }
        .cb-list-weight {
          display: flex; align-items: center; gap: 4px;
        }
        .cb-list-weight input {
          width: 80px; padding: 6px 8px; border: 1px solid var(--rule);
          border-radius: 4px; font-family: inherit; font-size: 13px;
          text-align: right;
        }
        .cb-list-weight span {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em;
          color: var(--ink-soft); text-transform: uppercase;
        }
        .cb-list-x {
          width: 26px; height: 26px; border-radius: 50%; border: 0;
          background: var(--paper-2); color: var(--ink-soft); cursor: pointer;
          font-size: 18px; line-height: 1;
        }
        .cb-list-x:hover {
          background: oklch(0.55 0.18 25); color: #fff;
        }

        .sc-mode-link {
          background: transparent; border: 0; cursor: pointer;
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em;
          text-transform: uppercase; color: var(--ink-soft); padding: 12px 0;
          margin-top: 4px;
        }
        .sc-mode-link:hover { color: var(--ink); }

        .sc-equip-desc {
          font-size: 13px; line-height: 1.55; color: var(--ink-soft);
          padding: 10px 14px; background: var(--paper-2);
          border: 1px solid var(--rule); border-radius: 6px;
          margin-top: 8px; font-style: italic;
        }

        /* Address Input */
        .ai-block {
          background: var(--paper-2); border: 1px solid var(--rule);
          border-radius: 6px; padding: 12px; display: flex;
          flex-direction: column; gap: 10px; margin-top: 6px;
        }
        .ai-row { display: flex; flex-direction: column; gap: 10px; }
        .ai-row-2 { display: grid; grid-template-columns: 2fr 1fr; gap: 10px; }
        @media (max-width: 600px) { .ai-row-2 { grid-template-columns: 1fr; } }
        .ai-verify-row {
          display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
        }
        .ai-verify-btn {
          font-family: inherit; font-size: 12px; padding: 7px 14px;
          border-radius: 4px; cursor: pointer; font-weight: 600;
          border: 1px solid var(--ink); background: #fff; color: var(--ink);
          white-space: nowrap;
        }
        .ai-verify-btn:hover:not(:disabled) { background: var(--ink); color: #fff; }
        .ai-verify-btn:disabled { opacity: 0.5; cursor: not-allowed; }
        .ai-status {
          font-size: 12px; line-height: 1.4; flex: 1;
        }
        .ai-status-checking { color: var(--ink-soft); font-style: italic; }
        .ai-status-ok       { color: oklch(0.40 0.16 145); }
        .ai-status-warn     { color: oklch(0.45 0.16 50); }

        /* Custom pallet dialog */
        .cb-custom-bg {
          position: fixed; inset: 0; background: rgba(20, 18, 14, 0.55); z-index: 110;
          display: flex; align-items: center; justify-content: center; padding: 24px;
        }
        .cb-custom {
          background: #fff; border-radius: 10px; max-width: 420px; width: 100%;
          padding: 28px; position: relative;
        }
        .cb-custom-x {
          position: absolute; top: 14px; right: 14px; background: transparent;
          border: 0; cursor: pointer; font-size: 22px; color: var(--ink-soft);
        }
        .cb-custom-h {
          font-family: var(--font-serif); font-size: 22px; letter-spacing: -0.015em;
          margin: 0 0 6px;
        }
        .cb-custom-sub {
          color: var(--ink-soft); font-size: 13px; margin: 0 0 18px;
        }
        .cb-custom-grid {
          display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 18px;
        }
        .cb-field { display: flex; flex-direction: column; gap: 6px; }
        .cb-field-full { grid-column: 1 / -1; }
        .cb-field > span {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
          text-transform: uppercase; color: var(--ink-soft);
        }
        .cb-field input {
          font-family: inherit; font-size: 14px; padding: 10px 12px;
          border: 1px solid var(--rule); border-radius: 6px; background: var(--paper);
          color: var(--ink); outline: none;
        }
        .cb-field input:focus { border-color: var(--ink); }
        .cb-custom-foot {
          display: flex; justify-content: space-between; gap: 10px;
        }
        .cb-custom-add {
          font-family: inherit; font-size: 14px; padding: 10px 18px;
          border-radius: 6px; cursor: pointer; font-weight: 600;
          border: 1px solid var(--ink); background: var(--ink); color: #fff;
        }
        .cb-custom-add:hover { opacity: 0.9; }

        /* Auth gate */
        .sc-gate {
          max-width: 720px; margin: 32px auto; padding: 32px;
          background: #fff; border: 1px solid var(--rule); border-radius: 8px;
          text-align: center;
        }
        .sc-gate h3 {
          font-family: var(--font-serif); font-size: 24px; margin: 0 0 12px;
        }
        .sc-gate p { color: var(--ink-soft); margin: 0 0 18px; }
        .sc-gate-btn {
          font-family: inherit; font-size: 14px; padding: 12px 22px;
          border-radius: 6px; cursor: pointer; border: 1px solid var(--ink);
          background: var(--ink); color: #fff; font-weight: 600;
        }
      `}</style>

      <section className="sc-hero">
        <button className="sc-back" onClick={() => onNav("home")}>← Home</button>
        <div className="sc-mark"><span className="dot" /> Shippers Connection</div>
        <h1 className="sc-title">Post a load. Find a <em>partner.</em></h1>
        <p className="sc-dek">
          Shippers heading the same direction split the truck, share the rate,
          hit the dock together. Carriers see the open board and pick the run
          that matches their next available trailer. v1 supports 22 metros and
          50/100/250/500-mile destination radius matching.
        </p>
      </section>

      {!isAuthed ? (
        <div className="sc-gate">
          <h3>Sign in to post or browse loads.</h3>
          <p>One email, one click, you're in. Same magic-link flow as the rest of the site.</p>
          <button className="sc-gate-btn" onClick={() => onNav("signin")}>Sign in →</button>
        </div>
      ) : (
        <>
          <nav className="sc-tabs">
            <button className={`sc-tab ${tab === "browse" ? "is-active" : ""}`}
              onClick={() => setTab("browse")}>📋 Browse loads</button>
            <button className={`sc-tab ${tab === "post" ? "is-active" : ""}`}
              onClick={() => setTab("post")}>＋ Post a load</button>
            <button className={`sc-tab ${tab === "mine" ? "is-active" : ""}`}
              onClick={() => setTab("mine")}>📬 My loads</button>
          </nav>

          <div className="sc-body">
            {postedFlash && <div className="sc-flash">✓ Load posted. It's now visible on the board.</div>}
            {tab === "browse" && <LoadBoard user={user} cities={cities} refreshKey={refreshKey} />}
            {tab === "post" && (
              <PostLoadForm
                key={editingDraft?.id || "new"}
                user={user} cities={cities}
                initialDraft={editingDraft}
                onPosted={() => {
                  setRefreshKey(k => k + 1);
                  setTab("mine");
                  setEditingDraft(null);
                  setPostedFlash(true);
                  setTimeout(() => setPostedFlash(false), 4000);
                }} />
            )}
            {tab === "mine" && (
              <MyLoads user={user} refreshKey={refreshKey}
                       onChanged={() => setRefreshKey(k => k + 1)}
                       onEditDraft={(load) => {
                         setEditingDraft(load);
                         setTab("post");
                       }} />
            )}
          </div>
        </>
      )}
    </div>
  );
}

window.ShippersConnectPage = ShippersConnectPage;
