// City Report Card Page

const { useState: useStateR, useEffect: useEffectR, useMemo: useMemoR } = React;

// Per-metro qualitative read used as the editorial topline. These are
// directional reads of the local freight market, not scores. The verdict
// shows above the live signal data so the page leads with a human take and
// then backs it with the data that drove it.
const METRO_VERDICTS = {
  "new-york":     "Ports + LTL congestion drives most of the signal here. Network-wide carriers struggle with five-borough density; regional LTLs win on consistency.",
  "chicago":      "Continental crossroads — what breaks here ripples nationwide. Cross-dock delays and rail-side detention dominate the operator log.",
  "dallas":       "Largest non-coastal LTL hub. Heat-related detention spikes May–Sep; weather-driven lane disruption is the dominant signal.",
  "atlanta":      "UPS hometown — small-package supremacy is institutional. The story to watch is regional LTL share-shift away from incumbents.",
  "phoenix":      "Last-mile-heavy, parcel-skewed. OnTrac and regional couriers visible in the data; thin LTL coverage relative to volume.",
  "seattle":      "Port + Amazon shadow. Longshore actions and weather-route closures (I-90, Snoqualmie) drive most of the high-severity signal.",
  "miami":        "Hurricane-season variance dominates. Port of Miami detention + cold-storage handoffs are the recurring pain points.",
  "denver":       "Mountain-corridor exposure. I-70 closures and Front Range capacity tightness are the persistent operator signals.",
  "boston":       "Density-constrained metro; light signal volume so far. Provisional read: regional LTLs outperform nationals on consistency.",
  "houston":      "Petrochem-corridor + port. Hazmat-tied detention and Galveston port congestion are the recurring intel patterns.",
  "philly":       "I-95 + port-of-Philadelphia signal mix. LTL-dominant; small-package carriers cluster around Lehigh Valley.",
  "memphis":      "FedEx World Hub gravity. Air-cargo handoffs dominate; the operator signal is heavily night-shift weighted.",
  "louisville":   "UPS Worldport gravity. Same shape as Memphis: air-hub handoffs drive the cycle, with regional LTL on the periphery.",
  "indianapolis": "Crossroads of America — every continental lane crosses here. FedEx Ground, FedEx Express, and rail intermodal all visible.",
  "cincinnati":   "DHL Americas hub presence. Light signal volume so far; air-cargo-tied with secondary LTL coverage.",
  "anchorage":    "Air-cargo waypoint between Asia and the lower-48. Operator network is thin but every signal here is supply-chain-grade.",
};

// MetroProvisional — provisional metro report card backed by live signal
// data. Replaces the old "Q3 2026 sign-up" stub. Pulls the last 30d of
// verified+public intel for the city, computes severity mix + top types +
// top carriers/facilities, and frames it with an honest "full scorecard
// pending field validation" disclaimer. Each metro reads from the same DB
// — no per-city hard-coded fakery.
function MetroProvisional({ cityId, onNav }) {
  const cities  = (window.SI_DATA && window.SI_DATA.FEATURED_CITIES) || [];
  const allCities = (window.SI_DATA && window.SI_DATA.ALL_CITIES) || cities;
  const meta = allCities.find(c => c.id === cityId)
    || { name: cityId, state: "" };

  const [rows, setRows] = useStateR([]);
  const [lanes, setLanes] = useStateR([]);
  const [topShippers, setTopShippers] = useStateR([]);
  const [loading, setLoading] = useStateR(true);

  useEffectR(() => {
    let alive = true;
    async function load() {
      if (!window.SI_DB || !window.SI_DB.raw) { setLoading(false); return; }
      try {
        // Pull intel + lanes + nearby shippers in parallel so the page
        // shows a fuller picture of the metro, not just signals.
        const cityName = meta.name || "";
        const cityState = meta.state || "";
        const cityNameEnc = encodeURIComponent(cityName);
        const stateEnc = encodeURIComponent(cityState);
        const [intel, laneA, laneB, shippers] = await Promise.all([
          window.SI_DB.raw.select(
            "intel_submissions",
            `select=id,parsed_carrier,parsed_intel_type,severity,raw_text,created_at,source_url,notes`
            + `&city_id=eq.${encodeURIComponent(cityId)}`
            + `&status=eq.verified&visibility=eq.public`
            + `&order=created_at.desc&limit=200`
          ).catch(() => []),
          window.SI_DB.raw.select(
            "dat_lane_rates",
            `select=*&origin_city=eq.${cityNameEnc}&order=lane_rate_per_mi.desc&limit=20`
          ).catch(() => []),
          window.SI_DB.raw.select(
            "dat_lane_rates",
            `select=*&dest_city=eq.${cityNameEnc}&order=lane_rate_per_mi.desc&limit=20`
          ).catch(() => []),
          cityState
            ? window.SI_DB.raw.select(
                "shippers",
                `select=id,canonical_name,slug,size_band,description,hq_state&hq_state=eq.${stateEnc}&order=size_band.asc&limit=10`
              ).catch(() => [])
            : Promise.resolve([]),
        ]);
        if (!alive) return;
        setRows(Array.isArray(intel) ? intel : []);
        // Combine outbound + inbound lanes; tag direction so we render both.
        const lanesOut = (Array.isArray(laneA) ? laneA : []).map(l => ({ ...l, _dir: "out" }));
        const lanesIn = (Array.isArray(laneB) ? laneB : []).map(l => ({ ...l, _dir: "in" }));
        setLanes([...lanesOut, ...lanesIn].slice(0, 8));
        setTopShippers(Array.isArray(shippers) ? shippers : []);
      } catch (e) {
        console.warn("[metro-provisional] load failed", e);
      } finally {
        if (alive) setLoading(false);
      }
    }
    load();
    return () => { alive = false; };
  }, [cityId]);

  const now = Date.now();
  const day = 24 * 3600 * 1000;
  const within30d = rows.filter(r => now - new Date(r.created_at).getTime() < 30 * day);
  const sev = (r) => r.severity || "low";
  const highCount = within30d.filter(r => sev(r) === "high" || sev(r) === "critical").length;

  const byType = {};
  const byCarrier = {};
  within30d.forEach(r => {
    const t = r.parsed_intel_type || "other";
    byType[t] = (byType[t] || 0) + 1;
    if (r.parsed_carrier) byCarrier[r.parsed_carrier] = (byCarrier[r.parsed_carrier] || 0) + 1;
  });
  const topTypes    = Object.entries(byType).sort((a,b)=>b[1]-a[1]).slice(0, 4);
  const topCarriers = Object.entries(byCarrier).sort((a,b)=>b[1]-a[1]).slice(0, 5);

  const recentTop = within30d.slice(0, 8);

  function fmtDate(s) {
    const d = new Date(s);
    const days = Math.round((now - d.getTime()) / day);
    if (days === 0) return "today";
    if (days === 1) return "yesterday";
    if (days < 7)   return `${days}d ago`;
    return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
  }
  function prettyType(t) {
    return t.replace(/_/g, " ");
  }
  function prettyCarrier(slug) {
    return slug.split("-").map(w => w[0].toUpperCase() + w.slice(1)).join(" ");
  }

  const verdict = METRO_VERDICTS[cityId];

  return (
    <div className="page-report metro-provisional">
      <style>{`
        .mp-eyebrow .dot { display:inline-block; width:8px; height:8px; border-radius:50%;
          background: oklch(0.55 0.18 145); margin-right:8px; vertical-align:middle; }
        .mp-stats { display:grid; grid-template-columns:repeat(4,1fr); gap:16px;
          max-width:1100px; margin:32px auto 0; padding:0 24px; }
        @media (max-width:760px) { .mp-stats { grid-template-columns:repeat(2,1fr); } }
        .mp-stat { background:#fff; border:1px solid var(--rule); border-radius:8px;
          padding:18px; }
        .mp-stat-num { font-family:var(--font-serif); font-size:32px; line-height:1.1;
          letter-spacing:-0.02em; }
        .mp-stat-label { font-family:var(--font-mono); font-size:10px; letter-spacing:0.16em;
          text-transform:uppercase; color:var(--ink-soft); margin-top:6px; }
        .mp-section { max-width:1100px; margin:48px auto; padding:0 24px; }
        .mp-section-h { font-family:var(--font-mono); font-size:12px; letter-spacing:0.18em;
          text-transform:uppercase; color:var(--ink-soft); padding-bottom:14px;
          border-bottom:1px solid var(--rule); margin-bottom:24px; }
        .mp-grid-2 { display:grid; grid-template-columns:1fr 1fr; gap:36px; }
        @media (max-width:760px) { .mp-grid-2 { grid-template-columns:1fr; } }
        .mp-list { list-style:none; padding:0; margin:0; }
        .mp-list li { display:flex; justify-content:space-between; padding:12px 0;
          border-bottom:1px solid var(--rule); font-size:15px; }
        .mp-list li:last-child { border-bottom:none; }
        .mp-list .label { color:var(--ink); }
        .mp-list .count { font-family:var(--font-mono); color:var(--ink-soft); font-size:13px; }
        .mp-feed { display:flex; flex-direction:column; gap:12px; }
        .mp-row { background:#fff; border:1px solid var(--rule); border-radius:6px;
          padding:14px 16px; }
        .mp-row-meta { display:flex; gap:10px; font-family:var(--font-mono); font-size:10px;
          letter-spacing:0.14em; text-transform:uppercase; color:var(--ink-soft);
          margin-bottom:6px; align-items:center; }
        .mp-pill { display:inline-block; padding:2px 8px; border-radius:4px; font-weight:600; }
        .mp-pill.critical { background:oklch(0.92 0.1 25);  color:oklch(0.35 0.18 25); }
        .mp-pill.high     { background:oklch(0.93 0.08 50); color:oklch(0.35 0.16 50); }
        .mp-pill.moderate { background:oklch(0.93 0.05 80); color:oklch(0.40 0.10 80); }
        .mp-pill.low      { background:oklch(0.95 0.02 250); color:var(--ink-soft); }
        .mp-row-text { font-size:15px; line-height:1.5; color:var(--ink); margin:0; }
        .mp-empty { text-align:center; padding:64px 24px; color:var(--ink-soft); }
        .mp-disclaimer { background:oklch(0.97 0.01 80); border:1px solid oklch(0.88 0.04 80);
          border-radius:6px; padding:16px 18px; max-width:1100px; margin:32px auto 0;
          font-size:14px; color:oklch(0.40 0.10 80); }
      `}</style>

      <section className="report-hero">
        <div className="report-hero-inner">
          <div className="report-breadcrumb">
            <a href="#" onClick={(e) => { e.preventDefault(); onNav("home"); }}>Home</a>
            <span>/</span>
            <span className="current">{meta.name}, {meta.state}</span>
          </div>
          <div style={{ maxWidth: 760 }}>
            <div className="report-eyebrow mp-eyebrow">
              <span className="dot" /> Live read · operator-network signal · last 30 days
            </div>
            <h1 className="report-title">
              <span style={{ fontStyle: "italic" }}>{meta.name},</span> {meta.state}
            </h1>
            {verdict && (
              <p className="report-sub" style={{ marginTop: 16, fontSize: 18, lineHeight: 1.5 }}>
                {verdict}
              </p>
            )}
          </div>
        </div>
      </section>

      <div className="mp-stats">
        <div className="mp-stat">
          <div className="mp-stat-num">{loading ? "…" : within30d.length}</div>
          <div className="mp-stat-label">Operator signals · 30d</div>
        </div>
        <div className="mp-stat">
          <div className="mp-stat-num" style={{ color: highCount > 0 ? "oklch(0.55 0.18 25)" : "var(--ink)" }}>
            {loading ? "…" : highCount}
          </div>
          <div className="mp-stat-label">High + critical · 30d</div>
        </div>
        <div className="mp-stat">
          <div className="mp-stat-num">{loading ? "…" : Object.keys(byCarrier).length}</div>
          <div className="mp-stat-label">Carriers in feed</div>
        </div>
        <div className="mp-stat">
          <div className="mp-stat-num">{loading ? "…" : Object.keys(byType).length}</div>
          <div className="mp-stat-label">Distinct signal types</div>
        </div>
      </div>

      <section className="mp-section">
        <div className="mp-section-h">What the data is telling us</div>
        <div className="mp-grid-2">
          <div>
            <h3 style={{ fontFamily: "var(--font-serif)", fontSize: 18, marginBottom: 12, letterSpacing: "-0.01em" }}>
              Top signal types
            </h3>
            {topTypes.length === 0 ? (
              <p style={{ color: "var(--ink-soft)" }}>No public signals in the last 30 days.</p>
            ) : (
              <ul className="mp-list">
                {topTypes.map(([t, n]) => (
                  <li key={t}><span className="label">{prettyType(t)}</span><span className="count">{n}</span></li>
                ))}
              </ul>
            )}
          </div>
          <div>
            <h3 style={{ fontFamily: "var(--font-serif)", fontSize: 18, marginBottom: 12, letterSpacing: "-0.01em" }}>
              Carriers in the feed
            </h3>
            {topCarriers.length === 0 ? (
              <p style={{ color: "var(--ink-soft)" }}>No carrier-tagged signals in the last 30 days.</p>
            ) : (
              <ul className="mp-list">
                {topCarriers.map(([c, n]) => (
                  <li key={c}><span className="label">{prettyCarrier(c)}</span><span className="count">{n}</span></li>
                ))}
              </ul>
            )}
          </div>
        </div>
      </section>

      <section className="mp-section">
        <div className="mp-section-h">Recent signals</div>
        {loading ? (
          <p className="mp-empty">Loading…</p>
        ) : recentTop.length === 0 ? (
          <div className="mp-empty">
            No public signals tagged to {meta.name} in the last 30 days.
            <br />
            That doesn't mean nothing is happening — it means we haven't surfaced it yet.
          </div>
        ) : (
          <div className="mp-feed">
            {recentTop.map(r => (
              <div className="mp-row" key={r.id}>
                <div className="mp-row-meta">
                  <span className={`mp-pill ${sev(r)}`}>{sev(r)}</span>
                  <span>{prettyType(r.parsed_intel_type || "other")}</span>
                  {r.parsed_carrier && <span>· {prettyCarrier(r.parsed_carrier)}</span>}
                  <span>· {fmtDate(r.created_at)}</span>
                </div>
                <p className="mp-row-text">{r.raw_text}</p>
              </div>
            ))}
          </div>
        )}
      </section>

      {/* Lane heat in/out of this metro — pulls live from dat_lane_rates.
          Shows both directions so the asymmetry is visible at a glance. */}
      {lanes.length > 0 && (
        <section className="mp-section">
          <div className="mp-section-h">Lane heat · in and out of {meta.name}</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))", gap: 12 }}>
            {lanes.map((l, i) => {
              const rate = parseFloat(l.lane_rate_per_mi);
              const out = l._dir === "out";
              const otherCity = out ? `${l.dest_city}, ${l.dest_state}` : `${l.origin_city}, ${l.origin_state}`;
              return (
                <a key={i} href="#/rates" onClick={(e) => { e.preventDefault(); window.location.hash = "#/rates"; }}
                   style={{ textDecoration: "none", color: "inherit", padding: 14, border: "1px solid var(--rule)", borderRadius: 6, background: "#fff", display: "block" }}>
                  <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--ink-soft)", marginBottom: 6 }}>
                    {out ? "Outbound · headhaul" : "Inbound · headhaul"} · {l.equipment_type}
                  </div>
                  <div style={{ fontFamily: "var(--font-serif)", fontSize: 17, color: "var(--ink)", lineHeight: 1.3, marginBottom: 6 }}>
                    {out ? `${meta.name} → ${otherCity}` : `${otherCity} → ${meta.name}`}
                  </div>
                  <div style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
                    <span style={{ fontFamily: "var(--font-serif)", fontSize: 22, fontWeight: 600, color: "var(--ink)" }}>
                      ${rate.toFixed(2)}
                    </span>
                    <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--ink-soft)" }}>
                      /mi
                    </span>
                  </div>
                </a>
              );
            })}
          </div>
          <p style={{ fontSize: 12, color: "var(--ink-soft)", marginTop: 14 }}>
            <a href="#/rates" onClick={(e) => { e.preventDefault(); window.location.hash = "#/rates"; }}
               style={{ color: "var(--ink)", borderBottom: "1px solid var(--rule)" }}>
              See the full lane heat table + asymmetry analytics →
            </a>
          </p>
        </section>
      )}

      {/* Top shippers in this metro — surfaces the directory inline so the
          metro page reads as a real intelligence dossier, not a stub. */}
      {topShippers.length > 0 && (
        <section className="mp-section">
          <div className="mp-section-h">Shippers headquartered in {meta.state}</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))", gap: 10 }}>
            {topShippers.slice(0, 6).map(s => (
              <a key={s.id} href={`#/shipper/${s.slug}`}
                 onClick={(e) => { e.preventDefault(); window.location.hash = `#/shipper/${s.slug}`; }}
                 style={{ textDecoration: "none", color: "inherit", padding: 14, border: "1px solid var(--rule)", borderRadius: 6, background: "#fff", display: "block" }}>
                <div style={{ fontFamily: "var(--font-serif)", fontSize: 17, color: "var(--ink)", lineHeight: 1.3 }}>
                  {s.canonical_name}
                </div>
                {s.size_band && s.size_band !== "unknown" && (
                  <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--ink-soft)", marginTop: 4 }}>
                    {s.size_band} · {s.hq_state}
                  </div>
                )}
                {s.description && (
                  <div style={{ fontSize: 13, color: "var(--ink-soft)", marginTop: 6, lineHeight: 1.4, display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden" }}>
                    {s.description}
                  </div>
                )}
              </a>
            ))}
          </div>
          <p style={{ fontSize: 12, color: "var(--ink-soft)", marginTop: 14 }}>
            <a href="#/shippers" onClick={(e) => { e.preventDefault(); window.location.hash = "#/shippers"; }}
               style={{ color: "var(--ink)", borderBottom: "1px solid var(--rule)" }}>
              Browse all 29,762 shippers in the directory →
            </a>
          </p>
        </section>
      )}

      {window.CrossDocksByCity && (
        <section className="mp-section" style={{ padding: "24px 24px 8px" }}>
          <div className="section-eyebrow">Carrier hubs in this metro</div>
          <h2 className="section-title" style={{ marginBottom: 18 }}>
            Where the major carriers run their networks in {meta.name}.
          </h2>
          <window.CrossDocksByCity cityId={cityId} onNav={onNav} />
        </section>
      )}

      {/* Cross-links — get visitors out of this metro page and into the
          rest of the graph: the rates engine for lanes touching this metro,
          the shipper directory for who ships from/to here, verification
          for any carrier they're considering. */}
      <section className="mp-section">
        <div className="mp-section-h">Connected surfaces</div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(260px, 1fr))", gap: 12 }}>
          <a href="#/rates" onClick={(e) => { e.preventDefault(); window.location.hash = "#/rates"; }}
             style={{ textDecoration: "none", color: "inherit", padding: 16, border: "1px solid var(--rule)", borderRadius: 6, background: "#fff", display: "block" }}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--ink-soft)", marginBottom: 6 }}>Lane rates →</div>
            <div style={{ fontFamily: "var(--font-serif)", fontSize: 17, color: "var(--ink)", lineHeight: 1.3 }}>
              See $/mi heat bands and headhaul-vs-backhaul asymmetry on lanes in and out of {meta.name}.
            </div>
          </a>
          <a href="#/shippers" onClick={(e) => { e.preventDefault(); window.location.hash = "#/shippers"; }}
             style={{ textDecoration: "none", color: "inherit", padding: 16, border: "1px solid var(--rule)", borderRadius: 6, background: "#fff", display: "block" }}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--ink-soft)", marginBottom: 6 }}>Shipper directory →</div>
            <div style={{ fontFamily: "var(--font-serif)", fontSize: 17, color: "var(--ink)", lineHeight: 1.3 }}>
              Browse the shippers operating warehouses, plants, and DCs in this metro.
            </div>
          </a>
          <a href="#/find-carrier" onClick={(e) => { e.preventDefault(); window.location.hash = "#/find-carrier"; }}
             style={{ textDecoration: "none", color: "inherit", padding: 16, border: "1px solid var(--rule)", borderRadius: 6, background: "#fff", display: "block" }}>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--ink-soft)", marginBottom: 6 }}>Verify a carrier →</div>
            <div style={{ fontFamily: "var(--font-serif)", fontSize: 17, color: "var(--ink)", lineHeight: 1.3 }}>
              Run any carrier name, DOT#, or MC# against the federal registry before you tender a load.
            </div>
          </a>
        </div>
      </section>

      <section className="mp-section" style={{ textAlign: "center", padding: "32px 24px 96px" }}>
        <h2 style={{ fontFamily: "var(--font-serif)", fontSize: 28, letterSpacing: "-0.02em", margin: "0 0 12px" }}>
          Get the {meta.name} Pulse.
        </h2>
        <p style={{ color: "var(--ink-soft)", margin: "0 0 24px" }}>
          7 AM local. Every signal worth knowing about, the night before it hits your dock.
        </p>
        <div style={{ display: "flex", gap: 12, justifyContent: "center", flexWrap: "wrap" }}>
          <button className="btn-primary-lg" onClick={() => onNav("home")}>
            Subscribe to the {meta.name} Pulse →
          </button>
          <button className="btn-ghost-lg" onClick={() => onNav("home")}>
            See the LA report card
          </button>
        </div>
      </section>
    </div>
  );
}

function ReportPage({ onNav, onCarrier, cityId = "los-angeles" }) {
  // Defensive guard: if data.jsx hasn't loaded yet (Babel scripts compile
  // out-of-order), show a brief loading state instead of crashing on the
  // destructure. This is what made /#/report appear to lock up on cold load.
  if (!window.SI_DATA || !window.SI_DATA.LA_REPORT) {
    return (
      <div style={{ padding: 96, textAlign: "center", color: "var(--ink-soft)" }}>
        Loading report…
      </div>
    );
  }

  // LA is the only metro with a full carrier-level scorecard seeded today.
  // For every other metro we show a *provisional* verdict driven by live
  // operator-network signal — recent intel volume, severity mix, top
  // patterns — instead of faking a scorecard. Honest framing: "we'll
  // publish a full carrier scorecard once we have enough field data."
  if (cityId && cityId !== "los-angeles") {
    return <MetroProvisional cityId={cityId} onNav={onNav} />;
  }

  const { LA_REPORT, SHIPPING_CATEGORIES, METRICS, scoreToLetter } = window.SI_DATA;
  const [activeCat, setActiveCat] = useStateR("small");
  const [expanded, setExpanded] = useStateR(null);
  const [sortKey, setSortKey] = useStateR("score");
  const [sortDir, setSortDir] = useStateR("desc");
  const [compareMode, setCompareMode] = useStateR(false);
  const [compareIds, setCompareIds] = useStateR([]);

  const r = LA_REPORT;
  const carriers = r.carriers[activeCat] || [];

  const sortedCarriers = useMemoR(() => {
    const arr = [...carriers];
    arr.sort((a, b) => {
      let av, bv;
      if (sortKey === "score") { av = a.score; bv = b.score; }
      else if (sortKey === "name") { av = a.name; bv = b.name; }
      else if (sortKey === "shipments") {
        av = parseFloat(a.shipments); bv = parseFloat(b.shipments);
      } else if (sortKey === "trend") { av = a.trend; bv = b.trend; }
      else { av = a.scores[sortKey]; bv = b.scores[sortKey]; }
      if (typeof av === "string") return sortDir === "asc" ? av.localeCompare(bv) : bv.localeCompare(av);
      return sortDir === "asc" ? av - bv : bv - av;
    });
    return arr;
  }, [carriers, sortKey, sortDir]);

  const toggleSort = (k) => {
    if (sortKey === k) setSortDir(sortDir === "asc" ? "desc" : "asc");
    else { setSortKey(k); setSortDir(k === "name" ? "asc" : "desc"); }
  };

  const toggleCompare = (id) => {
    setCompareIds(prev => {
      if (prev.includes(id)) return prev.filter(i => i !== id);
      if (prev.length >= 2) return [prev[1], id];
      return [...prev, id];
    });
  };

  const overallScore = r.overall[activeCat];
  const activeCatLabel = SHIPPING_CATEGORIES.find(c => c.id === activeCat)?.label;

  return (
    <div className="page-report">
      {/* Hero band */}
      <section className="report-hero">
        <div className="report-hero-inner">
          <div className="report-breadcrumb">
            <a href="#" onClick={(e) => { e.preventDefault(); onNav("home"); }}>Home</a>
            <span>/</span>
            <a href="#" onClick={(e) => { e.preventDefault(); onNav("home"); }}>City reports</a>
            <span>/</span>
            <span className="current">Los Angeles, CA</span>
          </div>

          <div className="report-hero-grid">
            <div>
              <div className="report-eyebrow">{r.reportPeriod} Report Card · Updated {r.lastUpdated}</div>
              <h1 className="report-title">
                <span style={{ fontStyle: "italic" }}>Los Angeles,</span> CA
              </h1>
              <p className="report-sub">
                {r.metroPop} metro population · {r.zips} ZIP codes tracked · {r.shipmentsTracked} shipments analyzed
              </p>
              <div className="report-tldr">
                <span className="tldr-label">TL;DR</span>
                <p>UPS edges out FedEx for small-package supremacy; <strong>Old Dominion</strong> dominates LTL with a near-flawless damage record. USPS continues to slip on tracking and service. Saia is the carrier to watch — quietly climbing every quarter.</p>
              </div>
            </div>
            <div className="report-overall-card">
              <div className="report-overall-label">{activeCatLabel} · Metro Average</div>
              <CircleScore score={overallScore} size={180} />
              <div className="report-overall-foot">
                Across {carriers.length} carriers tracked
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* Category tabs */}
      <section className="cat-tabs">
        <div className="cat-tabs-inner">
          {SHIPPING_CATEGORIES.map(c => (
            <button
              key={c.id}
              className={`cat-tab ${activeCat === c.id ? "active" : ""}`}
              onClick={() => { setActiveCat(c.id); setExpanded(null); setCompareIds([]); }}
            >
              <span className="cat-tab-label">{c.label}</span>
              <span className="cat-tab-grade">
                <LetterBadge score={r.overall[c.id]} size="sm" />
              </span>
            </button>
          ))}
        </div>
      </section>

      {/* Toolbar */}
      <section className="report-toolbar">
        <div className="report-toolbar-inner">
          <div className="toolbar-left">
            <h2 className="toolbar-h">{activeCatLabel} carriers — ranked</h2>
            <span className="toolbar-meta">{carriers.length} tracked · sorted by {sortKey === "score" ? "Clarity Score" : sortKey}</span>
          </div>
          <div className="toolbar-right">
            <button
              className={`btn-toggle ${compareMode ? "on" : ""}`}
              onClick={() => { setCompareMode(!compareMode); setCompareIds([]); }}
            >
              {compareMode ? `Comparing (${compareIds.length}/2)` : "Compare carriers"}
            </button>
          </div>
        </div>
      </section>

      {/* Table */}
      <section className="carrier-table-section">
        <div className="carrier-table-inner">
          <div className="carrier-table">
            <div className="carrier-table-head">
              <div className="ct-col ct-rank">#</div>
              <div className="ct-col ct-name sortable" onClick={() => toggleSort("name")}>
                Carrier <SortInd active={sortKey==="name"} dir={sortDir} />
              </div>
              <div className="ct-col ct-score sortable" onClick={() => toggleSort("score")}>
                Clarity Score <SortInd active={sortKey==="score"} dir={sortDir} />
              </div>
              <div className="ct-col ct-grade">Grade</div>
              <div className="ct-col ct-trend sortable" onClick={() => toggleSort("trend")}>
                QoQ <SortInd active={sortKey==="trend"} dir={sortDir} />
              </div>
              <div className="ct-col ct-ontime sortable" onClick={() => toggleSort("ontime")}>
                On-Time <SortInd active={sortKey==="ontime"} dir={sortDir} />
              </div>
              <div className="ct-col ct-damage sortable" onClick={() => toggleSort("damage")}>
                Damage <SortInd active={sortKey==="damage"} dir={sortDir} />
              </div>
              <div className="ct-col ct-volume sortable" onClick={() => toggleSort("shipments")}>
                Volume <SortInd active={sortKey==="shipments"} dir={sortDir} />
              </div>
              <div className="ct-col ct-action"></div>
            </div>

            {sortedCarriers.map((c, i) => (
              <CarrierRow
                key={c.id} c={c} rank={i + 1}
                expanded={expanded === c.id}
                onExpand={() => setExpanded(expanded === c.id ? null : c.id)}
                compareMode={compareMode}
                compared={compareIds.includes(c.id)}
                onCompare={() => toggleCompare(c.id)}
                onCarrier={onCarrier}
              />
            ))}
          </div>

          {compareMode && compareIds.length === 2 && (
            <CompareDrawer
              carriers={compareIds.map(id => carriers.find(c => c.id === id))}
              metrics={METRICS}
              onClose={() => { setCompareMode(false); setCompareIds([]); }}
            />
          )}
        </div>
      </section>

      {/* Methodology footer */}
      {/* Cross-dock terminal directory for this metro — surfaced before
          the methodology section so shippers + drivers see the actual
          handoff facilities under each carrier's grade. */}
      {window.CrossDocksByCity && (
        <section className="report-section" style={{
          maxWidth: 1240, margin: "0 auto", padding: "32px 24px",
        }}>
          <div className="section-eyebrow">Cross-dock terminals</div>
          <h2 className="section-title" style={{ marginBottom: 18 }}>
            Where the freight actually changes hands in LA.
          </h2>
          <window.CrossDocksByCity cityId="los-angeles" onNav={onNav} />
        </section>
      )}

      <section className="report-method">
        <div className="report-method-inner">
          <div>
            <div className="section-eyebrow">Methodology</div>
            <h2 className="section-title">How we graded LA.</h2>
            <p className="report-method-p">
              Grades are derived from {r.shipmentsTracked} tracked shipments across {r.zips} LA-area ZIP codes during {r.reportPeriod}. We weight 8 metrics — on-time delivery, damage rate, customer service responsiveness, tracking accuracy, transit vs. promise, pricing competitiveness, pickup reliability, and driver professionalism — and produce a 0–100 Insight Score per carrier per category. Sponsored placements are clearly labeled and never affect grades.
            </p>
            <button className="btn-ghost" style={{ marginTop: 16 }}>Read full methodology →</button>
          </div>
          <div className="metric-weights">
            <div className="metric-weights-h">Metric weights</div>
            {METRICS.map(m => (
              <div key={m.id} className="metric-weight-row">
                <span className="mw-label">{m.label}</span>
                <span className="mw-bar"><span className="mw-fill" style={{ width: `${m.weight*100*5}%` }}/></span>
                <span className="mw-val">{Math.round(m.weight*100)}%</span>
              </div>
            ))}
          </div>
        </div>
      </section>
    </div>
  );
}

function SortInd({ active, dir }) {
  if (!active) return <span style={{ opacity: 0.3, fontFamily: "var(--font-mono)", fontSize: 10 }}>↕</span>;
  return <span style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--red)" }}>{dir === "asc" ? "↑" : "↓"}</span>;
}

function CarrierRow({ c, rank, expanded, onExpand, compareMode, compared, onCompare, onCarrier }) {
  return (
    <div className={`ct-row-wrap ${expanded ? "expanded" : ""}`}>
      <div className="ct-row" onClick={compareMode ? onCompare : onExpand}>
        <div className="ct-col ct-rank">
          <span className="rank-num">{String(rank).padStart(2, "0")}</span>
        </div>
        <div className="ct-col ct-name">
          <div className="carrier-name-row">
            <span className="carrier-logo-dot" style={{ background: carrierColor(c.id) }}>{c.name[0]}</span>
            <div>
              <div className="carrier-name">
                <a
                  href={`#/carrier/${c.id}`}
                  className="carrier-name-link"
                  onClick={(e) => { e.stopPropagation(); onCarrier(c.id); }}
                  title={`Open ${c.name} profile`}
                >{c.name}</a> {c.sponsored && <SponsoredTag />}
                {c.intel && c.intel.total > 0 && (
                  <span className="intel-badge" title={`${c.intel.total} driver-sourced reports in the last 7 days (${c.intel.high} high, ${c.intel.moderate} moderate, ${c.intel.low} low). Aggregated from public freight forums and operator chatter.`}>
                    {c.intel.high > 0 && <span className="intel-dot intel-dot-high" />}
                    {c.intel.total} this week
                  </span>
                )}
                <a
                  className="iy-link"
                  href={`https://www.importyeti.com/company/${c.id}`}
                  target="_blank"
                  rel="noopener noreferrer"
                  title="View this company's public import history"
                  onClick={(e) => e.stopPropagation()}
                >
                  Imports →
                </a>
              </div>
              <div className="carrier-sub">{c.shipments} shipments · {c.complaints} complaints</div>
            </div>
          </div>
        </div>
        <div className="ct-col ct-score">
          <div className="score-cell">
            <span className="score-num">{c.score}</span>
            <span className="score-bar"><span className="score-bar-fill" style={{ width: `${c.score}%`, background: scoreColor(c.score) }} /></span>
          </div>
        </div>
        <div className="ct-col ct-grade"><LetterBadge score={c.score} size="md" /></div>
        <div className="ct-col ct-trend"><TrendArrow trend={c.trend} /></div>
        <div className="ct-col ct-ontime"><span style={{ fontFamily: "var(--font-mono)", fontSize: 14 }}>{c.scores.ontime}</span></div>
        <div className="ct-col ct-damage"><span style={{ fontFamily: "var(--font-mono)", fontSize: 14 }}>{c.scores.damage}</span></div>
        <div className="ct-col ct-volume"><span style={{ fontFamily: "var(--font-mono)", fontSize: 14 }}>{c.shipments}</span></div>
        <div className="ct-col ct-action">
          {compareMode ? (
            <span className={`compare-check ${compared ? "checked" : ""}`}>
              {compared ? "✓" : ""}
            </span>
          ) : (
            <span className="expand-arrow" style={{ transform: expanded ? "rotate(180deg)" : "" }}>▾</span>
          )}
        </div>
      </div>

      {expanded && !compareMode && (
        <div className="ct-detail">
          <div className="ct-detail-grid">
            <div className="ct-detail-verdict">
              <div className="detail-eyebrow">Our verdict</div>
              <p className="detail-verdict-p">{c.verdict}</p>
              <div className="strengths-weak">
                <div>
                  <div className="sw-h sw-h-good">What works</div>
                  <ul className="sw-list">
                    {c.strengths.map((s, i) => <li key={i}>{s}</li>)}
                  </ul>
                </div>
                <div>
                  <div className="sw-h sw-h-bad">What doesn't</div>
                  <ul className="sw-list">
                    {c.weaknesses.map((s, i) => <li key={i}>{s}</li>)}
                  </ul>
                </div>
              </div>
              <button className="btn-ghost" onClick={() => onCarrier(c.id)} style={{ marginTop: 18 }}>
                Full {c.name} profile →
              </button>
            </div>
            <div className="ct-detail-metrics">
              <div className="detail-eyebrow">Metric breakdown</div>
              {window.SI_DATA.METRICS.map((m, i) => (
                <MetricBar key={m.id} label={m.label} score={c.scores[m.id]} delay={i * 45} />
              ))}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function CompareDrawer({ carriers, metrics, onClose }) {
  const [a, b] = carriers;
  return (
    <div className="compare-drawer">
      <div className="compare-head">
        <div className="compare-h">Head-to-head</div>
        <button className="compare-close" onClick={onClose}>×</button>
      </div>
      <div className="compare-grid">
        <div className="compare-col">
          <div className="compare-name">{a.name}</div>
          <CircleScore score={a.score} size={120} />
        </div>
        <div className="compare-vs">VS</div>
        <div className="compare-col">
          <div className="compare-name">{b.name}</div>
          <CircleScore score={b.score} size={120} />
        </div>
      </div>
      <div className="compare-metrics">
        {metrics.map(m => {
          const av = a.scores[m.id], bv = b.scores[m.id];
          const aWin = av > bv, bWin = bv > av;
          return (
            <div key={m.id} className="compare-metric-row">
              <span className={`cmr-val ${aWin ? "win" : ""}`} style={{ textAlign: "right" }}>{av}</span>
              <span className="cmr-bar-wrap">
                <span className="cmr-bar cmr-bar-a" style={{ width: `${av/2}%` }} />
                <span className="cmr-bar cmr-bar-b" style={{ width: `${bv/2}%` }} />
              </span>
              <span className={`cmr-val ${bWin ? "win" : ""}`}>{bv}</span>
              <span className="cmr-label">{m.label}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function carrierColor(id) {
  const map = {
    ups: "#8B5A1A", fedex: "#5A2C8C", usps: "#1E3A8A", amazon: "#E8A33D",
    "amazon-logistics": "#E8A33D",
    ontrac: "#C53030", dhl: "#D4A017",
    "old-dominion": "#1A4D2E", saia: "#2563EB", estes: "#7C2D12", xpo: "#DC2626", abf: "#374151",
    "knight-swift": "#B45309", schneider: "#EA580C", "jb-hunt": "#7C2D12", werner: "#1F2937",
    "us-xpress": "#0891B2",
    "uber-freight": "#111827", "doordash-drive": "#DC2626", roadie: "#7C3AED", "courier-express": "#374151",
    "dhl-express": "#D4A017", "fedex-intl": "#5A2C8C", "fedex-international": "#7C3AED",
    "ups-intl": "#8B5A1A", "ups-worldwide": "#A05A1A", "usps-intl": "#1E3A8A",
  };
  return map[id] || "var(--ink)";
}

function scoreColor(s) {
  if (s >= 85) return "var(--green)";
  if (s >= 70) return "var(--ink)";
  if (s >= 55) return "var(--amber)";
  return "var(--red)";
}

window.ReportPage = ReportPage;
window.carrierColor = carrierColor;
window.scoreColor = scoreColor;
