{
  "version": 3,
  "sources": ["return-trip.js"],
  "sourcesContent": ["// Where you came from, remembered for the tab. The app has HUBS — the ops\n// board and its requests screen, the crawls queue, a crawl's own page, the\n// crawls list — and VIEWERS — the foundation, the query explorer, the report,\n// a job log, a revision history. A viewer's Close used to be a guess:\n// history.back() when the referrer looked right, otherwise a hard-coded\n// destination. The guess sent an operator who had opened a foundation from the\n// requests screen to a bare /account/ops/fulfillment/ with nothing selected,\n// and every \"Back to crawls\" on the ops sub-pages went to the queue whatever\n// you had been looking at.\n//\n// Now every hub records itself as you click OUT of it, and every viewer's\n// Close goes exactly there, labelled. Viewers never record themselves: a chain\n// of viewers (foundation → revision history → job log) still belongs to the\n// hub that started it. Session-scoped, per tab, on purpose — this is \"where I\n// am right now\", not a preference; a return address that persisted for days\n// would send you somewhere you no longer remember leaving.\nimport { safeHref } from \"/account/safe-url.js\";\nexport const RETURN_KEY = \"rl:return\";\nconst returnStore = () => { try { return window.sessionStorage; } catch (_) { return null; } };\n\nexport function rememberReturn(href, s = returnStore()) {\n  const h = href ?? (location.pathname + location.search);\n  try { s?.setItem(RETURN_KEY, h); } catch (_) {}\n}\n\nexport function returnTo(s = returnStore()) {\n  let href = null;\n  try { href = s?.getItem(RETURN_KEY) || null; } catch (_) {}\n  return href ? { href, label: returnLabel(href) } : null;\n}\n/* THE RETURN ADDRESS HAS TO BE ABOUT THIS CRAWL. A viewer opened from a page\n   that never recorded itself inherited whatever the last hub left behind, so\n   Close on Biltmore's foundation could land on another customer's crawl page.\n   A remembered address that names a different crawl is stale for this viewer\n   and is ignored; the caller falls back to this crawl's own page. */\nexport function returnToFor(auditId, s = returnStore()) {\n  const back = returnTo(s);\n  if (!back || !auditId) return back;\n  try {\n    const u = new URL(back.href, \"https://x\");\n    const other = u.searchParams.get(\"id\");\n    if (other && other !== String(auditId) && /^\\/account\\/(crawl|foundation|query-explorer|report|reader|plan|audit)\\/?$/.test(u.pathname)) return null;\n  } catch (_) {}\n  return back;\n}\n\n// The words for where a link goes back to, from its URL alone — so a Close\n// button can say \"Back to the requests\" rather than just \"Close\".\nexport function returnLabel(href) {\n  const [path, qs = \"\"] = String(href || \"\").split(\"?\");\n  const p = new URLSearchParams(qs);\n  const dir = path.replace(/\\/+$/, \"\");\n  if (dir.startsWith(\"/account/ops\")) {\n    const view = p.get(\"view\") || \"board\";\n    if (view === \"crawls\") return p.get(\"order\") ? \"the crawl\" : \"the crawls queue\";\n    if (view === \"board\") return p.get(\"origin\") === \"customer\" ? \"the requests\" : \"the board\";\n    return { machines: \"the fleet\", fleet: \"the fleet\", customers: \"the orders\", orders: \"the orders\", activity: \"the activity log\" }[view]\n      || \"the board\";\n  }\n  if (dir === \"/account/crawl\") return \"the crawl\";\n  if (dir === \"/account/reader\") return /#\\/plan/.test(String(href)) ? \"the plan\" : \"your visibility\";\n  if (dir === \"/account/foundation\") return \"the foundation\";\n  if (dir === \"/account/report\") return \"the report\";\n  if (dir === \"/account/query-explorer\") return \"the questions\";\n  if (dir === \"/account/voice-of-customer\") return \"the Voice of Customer\";\n  if (dir === \"/account/audits\") return \"your crawls\";\n  if (dir === \"/account\") return \"your account\";\n  return \"where you were\";\n}\n\n// A screen is a path plus, on the ops shell, its ?view= — the board and the\n// crawls queue share a URL and are different places.\nconst screenOf = (href) => {\n  const [path, qs = \"\"] = String(href || \"\").split(\"?\");\n  return path.replace(/\\/+$/, \"\") + \"|\" + (new URLSearchParams(qs).get(\"view\") || \"\");\n};\n\n// Install on a HUB: record this page as the return address whenever a link\n// leaves it for another in-app screen. Same-screen links (a tab, a filter, an\n// order opened in place) are not leaving. Capture phase, so it runs before a\n// handler that navigates programmatically.\nexport function recordReturnOnLeave(root = document) {\n  root.addEventListener(\"click\", (e) => {\n    const a = e.target?.closest?.(\"a[href]\"); if (!a) return;\n    const href = a.getAttribute(\"href\") || \"\";\n    if (!href.startsWith(\"/account/\")) return;\n    if (screenOf(href) === screenOf(location.pathname + location.search)) return;\n    rememberReturn();\n    rememberSpot(a);\n  }, true);\n}\n\n/* THE PLACE, NOT JUST THE PAGE. Coming back to a list of twelve cards at the\n   top of the page is not coming back. Alongside the return address, remember\n   the card or section the link was inside (a [data-series] card on the lists,\n   a [id] section on the crawl page) and the scroll position as a fallback, so\n   the hub can put the reader back where they were. */\nconst SPOT_KEY = \"rl:return-spot\";\nexport function rememberSpot(fromEl, s = returnStore()) {\n  const card = fromEl?.closest?.(\"[data-series]\");\n  const sec = fromEl?.closest?.(\"[id]\");\n  const sel = card?.dataset?.series ? `[data-series=\"${card.dataset.series}\"]` : sec?.id ? `#${sec.id}` : \"\";\n  try { s?.setItem(SPOT_KEY, JSON.stringify({ href: location.pathname + location.search, sel, y: window.scrollY || 0 })); } catch (_) {}\n}\n/* Call once the page has painted the thing the spot points at. Restores only\n   on the page the spot was recorded on, and only once per load. */\nlet spotRestored = false;\nexport function restoreReturnSpot({ flash = \"is-return\" } = {}, s = returnStore()) {\n  if (spotRestored) return false;\n  let spot = null;\n  try { spot = JSON.parse(s?.getItem(SPOT_KEY) || \"null\"); } catch (_) { spot = null; }\n  if (!spot || spot.href !== location.pathname + location.search) return false;\n  spotRestored = true;\n  let el = null;\n  try { el = spot.sel ? document.querySelector(spot.sel) : null; } catch (_) { el = null; }\n  if (el) {\n    el.scrollIntoView({ block: \"center\", behavior: \"instant\" });\n    if (flash) { el.classList.add(flash); setTimeout(() => el.classList.remove(flash), 1600); }\n  } else if (spot.y) {\n    window.scrollTo({ top: spot.y, behavior: \"instant\" });\n  }\n  return true;\n}\n\n// Point a Back/Close control at the remembered hub, with a fallback for a\n// direct visit. Returns the href it chose so a caller can label it too.\nexport function wireReturn(el, fallbackHref, { prefix = \"Back to\" } = {}) {\n  const back = returnTo();\n  const href = back?.href || fallbackHref;\n  if (el) {\n    el.setAttribute(\"href\", safeHref(href));\n    if (back && prefix) el.setAttribute(\"title\", `${prefix} ${back.label}`);\n  }\n  return { href, label: back?.label || null };\n}\n"],
  "mappings": "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",
  "names": ["safeHref", "returnStore", "href", "s", "h", "auditId", "back", "u", "other", "path", "qs", "p", "dir", "view", "screenOf", "root", "e", "a", "SPOT_KEY", "fromEl", "card", "sec", "sel", "spotRestored", "flash", "spot", "el", "fallbackHref", "prefix"]
}
