{
  "version": 3,
  "sources": ["../../javascript/controllers/error_reporter.js", "../../javascript/source/session_preferences.js", "../../javascript/source/burger_menu.js", "../../javascript/source/guide_finder.js", "../../javascript/source/guide_toc.js", "../../javascript/source/map_loader.js"],
  "sourcesContent": ["// Reports JavaScript errors thrown in our own bundles to /js_errors (JsError).\n// Imported once by every layout bundle (application, admin, booking, kiosk,\n// pages, guides, public_share); add-on bundles on top of them are covered by\n// the host's listener. Errors from browser extensions, tag managers and other\n// third-party scripts are dropped here, and the server drops them again.\n// Readable messages need crossorigin on our script tags (docs/js-errors.md).\nconst MAX_REPORTS_PER_PAGE = 5;\n\n// boot_check.js reports a page whose bundle never got this far (a parse error\n// on an old browser kills this reporter too). Imported first, so this runs\n// before any other module of the bundle.\nwindow.gamerBooted = true;\n// An own frame ends in <origin>/assets/<entry>-<64 hex digest>.js:<line>:<column>\n// (no digest in test and development). Anchored at the end: a V8 eval frame\n// names the script that called eval earlier in the line, but runs elsewhere.\nconst OWN_FRAME =\n  /https?:\\/\\/[^\\s/]+(\\/assets\\/[a-z_]+(?:-[0-9a-f]{64})?\\.js):(\\d+):(\\d+)\\)?\\s*$/;\n// Stack lines that are frames with a position of their own (V8 \"at \u2026\",\n// Gecko/JSC \"fn@\u2026\"). Builtins (`Array.map (<anonymous>)`, `[native code]`)\n// have none and are skipped, so our code calling into them still counts.\nconst POSITIONED_FRAME = /:\\d+:\\d+\\)?\\s*$/;\nconst BUILTIN_FRAME = /\\[native code\\]|\\(<anonymous>\\)\\s*$|\\(native\\)\\s*$/;\n\n// A fetch that lost the connection (Chrome, Safari, Firefox wording). Turbo\n// rethrows these and aborted requests after handling them: a failed visit\n// falls back to a full page load, an aborted one was superseded by the next\n// tap. Nothing in our code to fix (docs/js-errors.md).\nconst NETWORK_FAILURE =\n  /^(Failed to fetch|Load failed|NetworkError when attempting to fetch resource\\.?)$/;\n// Firefox's cross-compartment security error. Our code never touches another\n// frame or window, so the object came from a browser extension: e.g. a node it\n// inserted, which Stimulus' MutationObserver then reads `nodeType` on.\nconst FOREIGN_OBJECT = /^Permission denied to access (property|object)\\b/;\n// Browser extensions inject scripts and styles the CSP refuses; not ours.\nconst EXTENSION_URL =\n  /^((chrome|moz|safari|safari-web|ms-browser)-extension|webkit-masked-url|about)\\b/;\n\nlet sent = 0;\nconst seen = new Set();\n// Where the page came from when the error hit, sent as `context`: a crash on a\n// back/forward restore, a Turbo cache preview or in a just-loaded frame looks\n// the same in the stack as one on a fresh load.\nlet lastVisit = null;\nlet lastFrame = null;\nlet lastRenderAt = 0;\n\ndocument.addEventListener(\"turbo:visit\", (event) => {\n  lastVisit = event.detail.action;\n});\ndocument.addEventListener(\"turbo:load\", () => {\n  lastRenderAt = performance.now();\n});\ndocument.addEventListener(\"turbo:frame-load\", (event) => {\n  lastFrame = event.target.id || \"frame\";\n});\n\nwindow.addEventListener(\"error\", (event) => {\n  if (isBrowserNoise(event.error)) return;\n  const own =\n    ownFrame(`${event.filename}:${event.lineno}:${event.colno}`) ||\n    ownStackFrame(event.error?.stack);\n  if (own) report(event.message, own, event.error?.stack);\n});\n\nwindow.addEventListener(\"unhandledrejection\", (event) => {\n  const reason = event.reason;\n  if (isBrowserNoise(reason)) return;\n  const own = ownStackFrame(reason?.stack);\n  if (own) report(reason?.message || String(reason), own, reason?.stack);\n});\n\n// What the Content-Security-Policy blocks, or would block while production\n// runs it report-only, as source \"csp\" (docs/js-errors.md \"CSP violations\").\n// No line or column: the row is one per directive, blocked URL and sample,\n// whichever page it hit. Where it hit goes in the stack, a bundle frame there\n// resolves through the source map like an error's.\ndocument.addEventListener(\"securitypolicyviolation\", (event) => {\n  if (\n    EXTENSION_URL.test(event.sourceFile) ||\n    EXTENSION_URL.test(event.blockedURI) ||\n    event.sample.startsWith(\"sandbox eval code\")\n  ) {\n    return;\n  }\n  const blocked = withoutQuery(event.blockedURI) || \"inline\";\n  const at = `${withoutQuery(event.sourceFile)}:${event.lineNumber}:${event.columnNumber}`;\n  report(\n    `CSP ${event.effectiveDirective} blocked ${blocked} ${event.sample}`.trim(),\n    { source: \"csp\", line: null, column: null },\n    at,\n  );\n});\n\n// A query string can carry tokens or email addresses.\nfunction withoutQuery(url) {\n  return String(url || \"\").split(/[?#]/)[0];\n}\n\nfunction isBrowserNoise(error) {\n  return (\n    error?.name === \"AbortError\" ||\n    (error?.name === \"TypeError\" && NETWORK_FAILURE.test(error.message)) ||\n    FOREIGN_OBJECT.test(error?.message)\n  );\n}\n\n// The first frame with code of its own decides, not any frame further down:\n// an inline or injected script that Turbo runs (`<anonymous>:1:1`, e.g. from\n// a browser extension) has Turbo's activateScriptElements, ours, below it.\nfunction ownStackFrame(stack) {\n  for (const line of String(stack || \"\").split(\"\\n\")) {\n    if (BUILTIN_FRAME.test(line) || !POSITIONED_FRAME.test(line)) continue;\n    return ownFrame(line);\n  }\n  return null;\n}\n\n// The own-bundle location in a \"file:line:column\" string.\nfunction ownFrame(text) {\n  const match = OWN_FRAME.exec(text || \"\");\n  return match && { source: match[1], line: +match[2], column: +match[3] };\n}\n\n// keepalive lets the report outlive a page that is being left. Failures are\n// ignored: a lost report must never turn into another error.\nfunction report(message, { source, line, column }, stack) {\n  const key = `${message}|${source}|${line}|${column}`;\n  if (sent >= MAX_REPORTS_PER_PAGE || seen.has(key)) return;\n  sent += 1;\n  seen.add(key);\n\n  fetch(\"/js_errors\", {\n    method: \"POST\",\n    keepalive: true,\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify({\n      message: String(message || \"unknown\").slice(0, 500),\n      source,\n      line,\n      column,\n      // Hosts stripped: every frame is ours or a browser internal anyway.\n      stack: String(stack || \"\")\n        .replace(/https?:\\/\\/[^\\s/)]+/g, \"\")\n        .slice(0, 4000),\n      page: window.location.pathname,\n      context: context(),\n    }),\n  }).catch(() => {});\n}\n\n// Scalars only; the server keeps the keys it knows (JsError::CONTEXT_KEYS).\nfunction context() {\n  return {\n    navigation: performance.getEntriesByType?.(\"navigation\")[0]?.type,\n    turbo_visit: lastVisit,\n    turbo_preview: document.documentElement.hasAttribute(\"data-turbo-preview\"),\n    frame: lastFrame,\n    ms_since_load: Math.round(performance.now()),\n    ms_since_render: lastRenderAt\n      ? Math.round(performance.now() - lastRenderAt)\n      : null,\n    visibility: document.visibilityState,\n  };\n}\n", "const PREFS_ENDPOINT = \"/sp\";\n\nfunction encodeData(data) {\n  try {\n    const json = JSON.stringify(data);\n    const encoded = encodeURIComponent(json).replace(\n      /%([0-9A-F]{2})/g,\n      (_, match) => String.fromCharCode(parseInt(match, 16)),\n    );\n    return window.btoa(encoded);\n  } catch (error) {\n    console.error(\"Failed to encode preferences\", error);\n    return null;\n  }\n}\n\nfunction submitPreferences(bodyData) {\n  const csrf = document.querySelector('meta[name=\"csrf-token\"]');\n  const headers = { \"Content-Type\": \"application/json\" };\n  if (csrf) {\n    headers[\"X-CSRF-Token\"] = csrf.getAttribute(\"content\");\n  }\n\n  fetch(PREFS_ENDPOINT, {\n    method: \"POST\",\n    headers,\n    body: bodyData,\n    credentials: \"same-origin\",\n    keepalive: true,\n  }).catch(() => {});\n}\n\nfunction loadPreferences() {\n  const body = document.body;\n  if (!body) return;\n  // The server omits this attribute once it has buffered preferences for\n  // the session (tracked in the encrypted Rails session cookie), so the\n  // gate is not visible or editable by the browser user.\n  if (body.dataset.sessionPrefsNeeded !== \"1\") return;\n\n  try {\n    const nav = window.navigator || {};\n    const dtz = Intl.DateTimeFormat().resolvedOptions();\n    const data = {\n      tz: dtz.timeZone || null,\n      lg: nav.language || null,\n      lgs: Array.isArray(nav.languages) ? nav.languages : [],\n      hB: (() => {\n        const n = nav.hardwareConcurrency || 0;\n        if (n <= 2) return \"1-2\";\n        if (n <= 4) return \"3-4\";\n        if (n <= 8) return \"5-8\";\n        return \"9+\";\n      })(),\n      mB: (() => {\n        const m = nav.deviceMemory || 0;\n        if (!m) return null;\n        if (m <= 2) return \"\u22642\";\n        if (m <= 4) return \"3-4\";\n        if (m <= 8) return \"5-8\";\n        return \"9+\";\n      })(),\n      sB: (() => {\n        const { width, height } = window.screen || {};\n        const min = Math.min(width || 0, height || 0);\n        if (!min) return null;\n        if (min <= 400) return \"\u2264400\";\n        if (min <= 768) return \"401-768\";\n        if (min <= 1080) return \"769-1080\";\n        if (min <= 1440) return \"1081-1440\";\n        return \"1441+\";\n      })(),\n      dB: (() => {\n        const d = window.devicePixelRatio || 1;\n        if (d <= 1) return \"\u22641\";\n        if (d <= 2) return \"1-2\";\n        return \"2+\";\n      })(),\n      cD: (window.screen && window.screen.colorDepth) || null,\n      tc: (nav.maxTouchPoints || 0) > 0,\n      pD:\n        window.matchMedia &&\n        window.matchMedia(\"(prefers-color-scheme: dark)\").matches,\n      rM:\n        window.matchMedia &&\n        window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches,\n      dn: nav.doNotTrack === \"1\",\n      gp: !!nav.globalPrivacyControl,\n      pl: nav.userAgentData?.platform || nav.platform || null,\n      br: nav.userAgentData?.brands || null,\n    };\n\n    const encoded = encodeData(data);\n    if (!encoded) return;\n\n    const bodyData = JSON.stringify({ p: encoded });\n    submitPreferences(bodyData);\n  } catch (error) {\n    console.error(\"Session preferences failed\", error);\n  }\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", loadPreferences);\n", "// Mobile burger-menu open/close. Document-level delegation so the listener\n// survives Turbo navigation without being re-registered.\ndocument.addEventListener(\"click\", function (e) {\n  if (e.target.closest(\"[data-burger-open]\")) {\n    const menu = document.getElementById(\"burger-menu\");\n    const backdrop = document.getElementById(\"burger-backdrop\");\n    const panel = document.getElementById(\"burger-panel\");\n    if (!menu || !backdrop || !panel) return;\n    document.body.classList.add(\"overflow-hidden\");\n    menu.classList.remove(\"hidden\");\n    requestAnimationFrame(function () {\n      backdrop.classList.remove(\"opacity-0\");\n      backdrop.classList.add(\"opacity-100\");\n      panel.classList.remove(\"translate-x-full\");\n      panel.classList.add(\"translate-x-0\");\n    });\n  } else if (e.target.closest(\"[data-burger-close]\")) {\n    const backdrop2 = document.getElementById(\"burger-backdrop\");\n    const panel2 = document.getElementById(\"burger-panel\");\n    if (!backdrop2 || !panel2) return;\n    backdrop2.classList.remove(\"opacity-100\");\n    backdrop2.classList.add(\"opacity-0\");\n    panel2.classList.remove(\"translate-x-0\");\n    panel2.classList.add(\"translate-x-full\");\n    setTimeout(function () {\n      const menu2 = document.getElementById(\"burger-menu\");\n      if (menu2) menu2.classList.add(\"hidden\");\n      document.body.classList.remove(\"overflow-hidden\");\n    }, 300);\n  }\n});\n", "// Question module for guide pages, configured per topic under :finder (see\n// GuidePresenter::TOPIC_CONFIG). It SCORES the cards instead of hiding them:\n// each answered question adds its weight when the card matches and subtracts it\n// when it doesn't, ties fall back to the editorial ranking, and the top three\n// are rendered as links into the untouched list. A visitor can therefore never\n// reach an empty state \u2014 the failure mode of the filter bar this replaced.\n//\n// Questions reveal progressively: only the first is visible, and answering one\n// opens the next. Answered questions stay open and editable, and revealing is\n// one-way \u2014 taking an answer back never collapses what it opened, which would\n// yank content out from under the reader. An option with an empty match\n// (\"Egal\", \"Einfach so\") is the no-preference answer: it survives pruning,\n// scores neutrally, and still opens the next question.\n\nfunction initGuideFinder() {\n  const root = document.getElementById(\"guide-finder\");\n  if (!root) return;\n\n  let questions = JSON.parse(root.dataset.finderQuestions || \"[]\");\n  const cards = Array.prototype.slice.call(\n    document.querySelectorAll(\"[data-guide-card]\"),\n  );\n  const resultsEl = document.getElementById(\"guide-finder-results\");\n  const progressEl = document.getElementById(\"guide-finder-progress\");\n  const progressFill = root.querySelector(\"[data-finder-progress-fill]\");\n  const RESULT_COUNT = 3;\n\n  if (!cards.length || !questions.length) return;\n\n  // --- Matchers -------------------------------------------------------------\n  // Return true/false, or null when the card carries no data for this\n  // dimension \u2014 null scores neutrally instead of penalising missing data.\n  function matches(card, match) {\n    if (match.boolean) return card.hasAttribute(\"data-filter-\" + match.boolean);\n\n    if (match.categories) {\n      const cat = card.dataset.filterCat;\n      if (!cat) return null;\n      return match.categories.some(function (c) {\n        return c.toLowerCase() === cat;\n      });\n    }\n\n    // Budget and time are ceilings: an activity fits when its cheapest/shortest\n    // form stays under the limit.\n    if (match.max_price) {\n      const price = parseInt(card.dataset.filterPrice, 10);\n      if (isNaN(price)) return null;\n      return price <= parseInt(match.max_price, 10);\n    }\n\n    if (match.max_minutes) {\n      const low = parseInt(card.dataset.finderMin, 10);\n      if (isNaN(low)) return null;\n      return low <= match.max_minutes;\n    }\n\n    return null;\n  }\n\n  function isSkip(option) {\n    return !option.match || !Object.keys(option.match).length;\n  }\n\n  // --- Prune options nothing on this page can satisfy ------------------------\n  questions = questions.filter(function (question) {\n    const group = root.querySelector(\n      '[data-finder-question=\"' + question.key + '\"]',\n    );\n    if (!group) return false;\n\n    question.options = question.options.filter(function (option) {\n      const keep =\n        isSkip(option) ||\n        cards.some(function (card) {\n          return matches(card, option.match) === true;\n        });\n      if (!keep) {\n        const dead = group.querySelector(\n          '[data-finder-option=\"' + option.value + '\"]',\n        );\n        if (dead) dead.remove();\n      }\n      return keep;\n    });\n\n    // A question left with nothing but its skip option can't tell us anything.\n    if (\n      question.options.some(function (option) {\n        return !isSkip(option);\n      })\n    )\n      return true;\n\n    group.remove();\n    return false;\n  });\n\n  if (!questions.length) return;\n\n  const groups = questions.map(function (question) {\n    return root.querySelector('[data-finder-question=\"' + question.key + '\"]');\n  });\n\n  const skipValues = {}; // question key -> [option value, ...] with an empty match\n  questions.forEach(function (question) {\n    skipValues[question.key] = question.options\n      .filter(isSkip)\n      .map(function (option) {\n        return option.value;\n      });\n  });\n\n  // --- Answer state ---------------------------------------------------------\n  const selected = {}; // question key -> [option value, ...]\n  let revealed = 1;\n  let resultsShown = false;\n\n  root.querySelectorAll(\"[data-finder-option]\").forEach(function (button) {\n    button.addEventListener(\"click\", function () {\n      const group = button.closest(\"[data-finder-question]\");\n      const key = group.dataset.finderQuestion;\n\n      if (group.dataset.finderMulti === \"true\") {\n        const turningOn = !button.classList.contains(\"finder-selected\");\n        setOptionState(button, turningOn);\n        if (turningOn) clearConflicting(group, button, key);\n      } else {\n        group\n          .querySelectorAll(\"[data-finder-option]\")\n          .forEach(function (sibling) {\n            setOptionState(sibling, sibling === button);\n          });\n      }\n\n      selected[key] = Array.prototype.slice\n        .call(group.querySelectorAll(\"[data-finder-option].finder-selected\"))\n        .map(function (el) {\n          return el.dataset.finderOption;\n        });\n\n      update();\n    });\n  });\n\n  // In a multi-select question \"Egal\" and a real preference contradict each\n  // other, so picking one drops the other \u2014 the usual none-of-the-above rule.\n  function clearConflicting(group, button, key) {\n    const skips = skipValues[key] || [];\n    const pickedSkip = skips.indexOf(button.dataset.finderOption) !== -1;\n\n    group\n      .querySelectorAll(\"[data-finder-option].finder-selected\")\n      .forEach(function (sibling) {\n        if (sibling === button) return;\n        if (pickedSkip || skips.indexOf(sibling.dataset.finderOption) !== -1) {\n          setOptionState(sibling, false);\n        }\n      });\n  }\n\n  function setOptionState(button, on) {\n    button.setAttribute(\"aria-pressed\", on ? \"true\" : \"false\");\n    button.classList.toggle(\"finder-selected\", on);\n    button.classList.toggle(\"bg-pages-darkfrom\", on);\n    button.classList.toggle(\"text-white\", on);\n    button.classList.toggle(\"border-pages-darkfrom\", on);\n    button.classList.toggle(\"bg-white\", !on);\n    button.classList.toggle(\"text-gray-700\", !on);\n    button.classList.toggle(\"border-gray-300\", !on);\n  }\n\n  function answeredCount() {\n    return questions.filter(function (question) {\n      return (selected[question.key] || []).length;\n    }).length;\n  }\n\n  // The bar tracks answers, not reveals \u2014 pruning can leave fewer questions\n  // than the config declares, so the max comes from what actually rendered.\n  function setProgress(answered) {\n    if (!progressFill) return;\n\n    progressFill.style.width =\n      Math.round((answered / questions.length) * 100) + \"%\";\n    progressEl.setAttribute(\"aria-valuemax\", questions.length);\n    progressEl.setAttribute(\"aria-valuenow\", answered);\n  }\n\n  function update() {\n    const answered = answeredCount();\n\n    revealed = Math.max(revealed, Math.min(answered + 1, groups.length));\n    groups.forEach(function (group, i) {\n      group.classList.toggle(\"hidden\", i >= revealed);\n    });\n    setProgress(answered);\n\n    if (answered === questions.length) resultsShown = true;\n    if (resultsShown) showResults();\n  }\n\n  // --- Scoring --------------------------------------------------------------\n  function score(card) {\n    let total = 0;\n\n    questions.forEach(function (question) {\n      const answers = selected[question.key] || [];\n      if (!answers.length) return;\n\n      const chosen = question.options.filter(function (option) {\n        return answers.indexOf(option.value) !== -1;\n      });\n\n      const verdicts = chosen.map(function (option) {\n        return matches(card, option.match);\n      });\n      if (\n        verdicts.every(function (v) {\n          return v === null;\n        })\n      )\n        return; // skipped, or no data\n\n      total +=\n        verdicts.indexOf(true) !== -1 ? question.weight : -question.weight;\n    });\n\n    return total;\n  }\n\n  function showResults() {\n    const ranked = cards\n      .map(function (card, index) {\n        return { card: card, index: index, score: score(card) };\n      })\n      .sort(function (a, b) {\n        return b.score - a.score || a.index - b.index;\n      })\n      .slice(0, Math.min(RESULT_COUNT, cards.length));\n\n    resultsEl.innerHTML = \"\";\n    resultsEl.appendChild(resultsHeading(ranked.length));\n\n    const list = document.createElement(\"div\");\n    list.className = \"flex flex-col gap-3\";\n    ranked.forEach(function (entry) {\n      list.appendChild(resultCard(entry.card));\n    });\n    resultsEl.appendChild(list);\n    resultsEl.classList.remove(\"hidden\");\n  }\n\n  function resultsHeading(count) {\n    const heading = document.createElement(\"p\");\n    heading.className = \"text-base font-bold mb-3\";\n    heading.setAttribute(\"role\", \"status\");\n    // The template comes from the finder container so the heading follows the\n    // page's locale (Dutch on Tilburg guides); the German literal is a fallback.\n    const finderEl = document.getElementById(\"guide-finder\");\n    const template =\n      (finderEl && finderEl.dataset.resultsHeading) || \"Eure %{count} Ideen\";\n    heading.textContent = template.replace(\"%{count}\", count);\n    return heading;\n  }\n\n  // Built from the card's own DOM rather than duplicated markup, so a\n  // suggestion can never drift from the entry it links to.\n  function resultCard(card) {\n    const title = card.querySelector(\"[data-card-title]\");\n    const oneLiner = card.querySelector(\"[data-card-oneliner]\");\n    const image = card.querySelector(\"img\");\n\n    const link = document.createElement(\"a\");\n    link.href = \"#\" + card.id;\n    link.className =\n      \"flex items-center gap-4 bg-white border border-gray-300 rounded-lg p-3 no-underline hover:border-gray-400 transition-colors\";\n\n    if (image) {\n      const thumb = document.createElement(\"img\");\n      thumb.src = image.currentSrc || image.src;\n      thumb.alt = \"\";\n      thumb.loading = \"lazy\";\n      thumb.className = \"w-20 h-14 object-cover rounded flex-shrink-0\";\n      link.appendChild(thumb);\n    }\n\n    const text = document.createElement(\"div\");\n    text.className = \"min-w-0\";\n\n    const name = document.createElement(\"span\");\n    name.className = \"block font-bold text-pages-darkfrom\";\n    name.textContent = title ? title.textContent.trim() : \"\";\n    text.appendChild(name);\n\n    if (oneLiner) {\n      const description = document.createElement(\"span\");\n      description.className = \"block text-sm text-gray-600 line-clamp-2\";\n      description.textContent = oneLiner.textContent.trim();\n      text.appendChild(description);\n    }\n\n    link.appendChild(text);\n    return link;\n  }\n\n  update();\n}\n\n// pages/guides bundles only - neither loads Turbo, so DOMContentLoaded is\n// the page-ready event here (turbo:load would never fire).\ndocument.addEventListener(\"DOMContentLoaded\", initGuideFinder);\n", "function initGuideToc() {\n  const links = document.querySelectorAll(\".guide-toc-link\");\n  if (!links.length) return;\n  const anchors = Array.from(links)\n    .map(function (l) {\n      return { link: l, el: document.getElementById(l.dataset.tocAnchor) };\n    })\n    .filter(function (a) {\n      return a.el;\n    });\n\n  // The sticky brand bar shows the same \"where am I\" state below xl, where the\n  // TOC itself is display:none. Its links stay in the DOM at every width, so\n  // one pass drives both.\n  const label = document.querySelector(\"[data-guide-current-section]\");\n\n  // Viewport coordinates, not offsetTop: offsetTop is measured from the nearest\n  // positioned ancestor (the .relative wrapper), so it silently changed meaning\n  // whenever that wrapper moved and the highlight lit up the wrong entry.\n  function update() {\n    let current = null;\n    for (let i = anchors.length - 1; i >= 0; i--) {\n      if (anchors[i].el.getBoundingClientRect().top <= 120) {\n        current = anchors[i];\n        break;\n      }\n    }\n    links.forEach(function (l) {\n      l.classList.remove(\"text-pages-darkfrom\", \"font-semibold\");\n      l.classList.add(\"text-gray-500\");\n    });\n    if (current) {\n      current.link.classList.add(\"text-pages-darkfrom\", \"font-semibold\");\n      current.link.classList.remove(\"text-gray-500\");\n    }\n    // Above the first section there is nothing to name, so the bar falls back to\n    // its server-rendered text rather than keeping a stale heading.\n    if (label) {\n      label.textContent = current\n        ? current.link.textContent.trim()\n        : label.dataset.default;\n    }\n  }\n\n  let ticking = false;\n  window.addEventListener(\"scroll\", function () {\n    if (!ticking) {\n      requestAnimationFrame(function () {\n        update();\n        ticking = false;\n      });\n      ticking = true;\n    }\n  });\n  update();\n}\n\n// pages/guides bundles only - neither loads Turbo, so DOMContentLoaded is\n// the page-ready event here (turbo:load would never fire).\ndocument.addEventListener(\"DOMContentLoaded\", initGuideToc);\n", "// Lazy-loads the MapLibre bundle (data-map-script) only when a [data-map]\n// element comes near the viewport. Shared by pages.js and guides.js: MapLibre\n// is far too heavy to ship on every page load, and most visitors never scroll\n// to the map.\n// Visibility is only half of the gate. The home page's fleet map sits just\n// below the city buttons, so it intersects during the initial load and the\n// ~1 MB of MapLibre would compete with the page's own images and CSS for\n// bandwidth. Hold every injection until the page itself has finished loading,\n// then take the first idle moment. `timeout` keeps a permanently busy main\n// thread from starving the map entirely; the setTimeout is the Safari < 16.4\n// fallback, which has no requestIdleCallback.\nfunction whenPageIdle(callback) {\n  const idle = () => {\n    if (\"requestIdleCallback\" in window)\n      requestIdleCallback(callback, { timeout: 2000 });\n    else setTimeout(callback, 200);\n  };\n  if (document.readyState === \"complete\") idle();\n  else window.addEventListener(\"load\", idle, { once: true });\n}\n\nexport function initMapLoader() {\n  const mapEls = document.querySelectorAll(\"[data-map]\");\n  if (!mapEls.length) return;\n\n  // Read each path from the first element that actually carries it, not from\n  // mapEls[0]: a page can mix map elements (Stuttgart renders a city overview\n  // next to the close-up) and one of them omitting data-map-css used to leave\n  // the whole page without maplibre-gl.css \u2014 the map drew, the markers didn't.\n  const datasetValue = (key) =>\n    [...mapEls].map((el) => el.dataset[key]).find(Boolean);\n\n  const scriptSrc = datasetValue(\"mapScript\");\n  if (!scriptSrc) return;\n  // The address_map bundle's stylesheet (extracted maplibre-gl CSS) must be\n  // loaded alongside the script; the bundle cannot know its digested path.\n  const cssHref = datasetValue(\"mapCss\");\n\n  // Propagate the page's CSP nonce so the injected <script> is allowed under\n  // a nonce-only policy (incl. 'strict-dynamic', which drops host-source).\n  const nonce = document.querySelector('meta[name=\"csp-nonce\"]')?.content;\n\n  const inject = () => {\n    if (cssHref && !document.querySelector(`link[href=\"${cssHref}\"]`)) {\n      const link = document.createElement(\"link\");\n      link.rel = \"stylesheet\";\n      link.href = cssHref;\n      document.head.appendChild(link);\n    }\n    const script = document.createElement(\"script\");\n    if (nonce) script.nonce = nonce;\n    // CloudFront bundle: crossorigin lets its errors through unmasked (see\n    // ApplicationHelper#javascript_include_tag).\n    script.crossOrigin = \"anonymous\";\n    script.src = scriptSrc;\n    document.head.appendChild(script);\n  };\n\n  const observer = new IntersectionObserver(\n    (entries) => {\n      entries.forEach((entry) => {\n        if (entry.isIntersecting) {\n          whenPageIdle(inject);\n          observer.disconnect();\n        }\n      });\n    },\n    { rootMargin: \"200px\" },\n  );\n\n  mapEls.forEach((el) => observer.observe(el));\n}\n\n// pages/guides bundles only - neither loads Turbo, so DOMContentLoaded is\n// the page-ready event here (turbo:load would never fire).\ndocument.addEventListener(\"DOMContentLoaded\", initMapLoader);\n"],
  "mappings": "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",
  "names": ["OWN_FRAME", "POSITIONED_FRAME", "BUILTIN_FRAME", "NETWORK_FAILURE", "FOREIGN_OBJECT", "EXTENSION_URL", "sent", "seen", "lastVisit", "lastFrame", "lastRenderAt", "event", "isBrowserNoise", "own", "ownFrame", "ownStackFrame", "report", "reason", "blocked", "withoutQuery", "at", "url", "error", "stack", "line", "text", "match", "message", "source", "column", "key", "context", "encodeData", "data", "json", "encoded", "_", "match", "error", "submitPreferences", "bodyData", "csrf", "headers", "loadPreferences", "body", "nav", "n", "m", "width", "height", "min", "d", "e", "menu", "backdrop", "panel", "backdrop2", "panel2", "menu2", "initGuideFinder", "root", "questions", "cards", "resultsEl", "progressEl", "progressFill", "RESULT_COUNT", "matches", "card", "match", "cat", "c", "price", "low", "isSkip", "option", "question", "group", "keep", "dead", "groups", "skipValues", "selected", "revealed", "resultsShown", "button", "key", "turningOn", "setOptionState", "clearConflicting", "sibling", "el", "update", "skips", "pickedSkip", "on", "answeredCount", "setProgress", "answered", "i", "showResults", "score", "total", "answers", "verdicts", "v", "ranked", "index", "a", "b", "resultsHeading", "list", "entry", "resultCard", "count", "heading", "finderEl", "template", "title", "oneLiner", "image", "link", "thumb", "text", "name", "description", "initGuideToc", "links", "anchors", "a", "label", "update", "current", "i", "l", "ticking", "whenPageIdle", "callback", "idle", "initMapLoader", "mapEls", "datasetValue", "key", "el", "scriptSrc", "cssHref", "nonce", "inject", "link", "script", "observer", "entries", "entry"]
}
