{"version":3,"names":["PerformanceObserver","PerformanceEventTiming","prototype","interactions","Map","sent","recent","noteTarget","e","push","t","timeStamp","sel","selectorFor","target","length","shift","recentSelector","startTime","best","bestGap","i","gap","Math","abs","record","entry","id","interactionId","prev","get","duration","set","name","selector","path","window","location","pathname","worst","list","Array","from","values","sort","a","b","idx","min","floor","size","el","nodeType","parts","node","depth","unshift","nodeName","toLowerCase","cls","className","trim","split","slice","join","parentElement","replace","rate","ms","emit","params","gtag","isArray","dataLayer","send","metric_inp_value","round","metric_inp_rating","metric_inp_event_type","metric_inp_event_target","page_location","origin","transport_type","__inpDebug","console","log","po","getEntries","forEach","observe","type","buffered","durationThreshold","addEventListener","capture","passive","document","visibilityState"],"sources":["theme-6-inline-common-head_tag.js"],"sourcesContent":["\n// INP RUM beacon -> GA4 (G-6L1V96449Y, property 321456009)\n// Dependency-free on purpose: Discourse's CSP is nonce-based, so pulling\n// web-vitals from a CDN would need content_security_policy_script_src widened.\n// Set window.__inpDebug = true to log instead of waiting for GA4.\n\n(function () {\n  if (\n    typeof PerformanceObserver === \"undefined\" ||\n    typeof PerformanceEventTiming === \"undefined\" ||\n    !(\"interactionId\" in PerformanceEventTiming.prototype)\n  ) {\n    return; // Chrome 96+ only; Safari/Firefox don't report INP\n  }\n\n  // interactionId -> worst entry. One tap emits several entries\n  // (pointerdown/pointerup/click) sharing an id; the interaction's latency is\n  // the max among them.\n  var interactions = new Map();\n  var sent = false;\n\n  // entry.target is null for any element already detached when the observer\n  // callback runs — which is exactly what an SPA route change does to the row\n  // you just tapped. Measured on prod 2026-08-17: a topic-list tap reported\n  // \"(no-target)\". So snapshot the selector at input time, while it's still\n  // live. Capture + passive, ring buffer of 12.\n  var recent = [];\n\n  function noteTarget(e) {\n    recent.push({ t: e.timeStamp, sel: selectorFor(e.target) });\n    if (recent.length > 12) {\n      recent.shift();\n    }\n  }\n\n  // Event.timeStamp and PerformanceEntry.startTime share a time origin, so the\n  // nearest input within 100 ms is the one that produced this entry.\n  function recentSelector(startTime) {\n    var best = null;\n    var bestGap = 100;\n    for (var i = 0; i < recent.length; i++) {\n      var gap = Math.abs(recent[i].t - startTime);\n      if (gap <= bestGap) {\n        bestGap = gap;\n        best = recent[i].sel;\n      }\n    }\n    return best || \"(no-target)\";\n  }\n\n  function record(entry) {\n    var id = entry.interactionId;\n    if (!id) {\n      return;\n    }\n    var prev = interactions.get(id);\n    if (!prev || entry.duration > prev.duration) {\n      interactions.set(id, {\n        duration: entry.duration,\n        name: entry.name,\n        // Resolved HERE, not at send time — see noteTarget above.\n        selector: entry.target\n          ? selectorFor(entry.target)\n          : recentSelector(entry.startTime),\n        // Same reason: by the time we report, the URL has usually moved on. We\n        // want the page the slow tap actually happened on.\n        path: window.location.pathname,\n      });\n    }\n  }\n\n  // INP = drop one interaction per 50, take the next worst. Under 50\n  // interactions (almost every forum page view) that is just the max.\n  function worst() {\n    var list = Array.from(interactions.values()).sort(function (a, b) {\n      return b.duration - a.duration;\n    });\n    if (!list.length) {\n      return null;\n    }\n    var idx = Math.min(list.length - 1, Math.floor(interactions.size / 50));\n    return list[idx];\n  }\n\n  // Low-cardinality selector. GA4 event-scoped dimensions degrade past ~500\n  // distinct values/day and Discourse ids like #post_12345 would blow through\n  // that, so digits collapse to N (#post_N). Capped at the 100-char GA4 limit.\n  function selectorFor(el) {\n    if (!el || el.nodeType !== 1) {\n      return \"(no-target)\";\n    }\n    var parts = [];\n    var node = el;\n    var depth = 0;\n    while (node && node.nodeType === 1 && depth < 4) {\n      if (node.id) {\n        parts.unshift(\"#\" + node.id);\n        break;\n      }\n      var sel = node.nodeName.toLowerCase();\n      var cls = typeof node.className === \"string\" ? node.className.trim() : \"\";\n      if (cls) {\n        sel += \".\" + cls.split(/\\s+/).slice(0, 2).join(\".\");\n      }\n      parts.unshift(sel);\n      node = node.parentElement;\n      depth++;\n    }\n    return parts.join(\">\").replace(/\\d+/g, \"N\").slice(0, 100);\n  }\n\n  function rate(ms) {\n    return ms <= 200 ? \"good\" : ms <= 500 ? \"needs-improvement\" : \"poor\";\n  }\n\n  function emit(params) {\n    if (typeof window.gtag === \"function\") {\n      window.gtag(\"event\", \"inp\", params);\n      return true;\n    }\n    // gtag() is literally a dataLayer.push of its arguments, so this is the\n    // same call if only dataLayer is defined.\n    if (Array.isArray(window.dataLayer)) {\n      window.dataLayer.push([\"event\", \"inp\", params]);\n      return true;\n    }\n    return false;\n  }\n\n  function send() {\n    if (sent) {\n      return;\n    }\n    var best = worst();\n    if (!best) {\n      return; // no interactions this page view — nothing to report\n    }\n\n    var params = {\n      metric_inp_value: Math.round(best.duration),\n      metric_inp_rating: rate(best.duration),\n      metric_inp_event_type: best.name,\n      metric_inp_event_target: best.selector,\n      page_location: window.location.origin + best.path,\n      transport_type: \"beacon\",\n    };\n\n    if (window.__inpDebug) {\n      // eslint-disable-next-line no-console\n      console.log(\"[inp-rum]\", params, \"interactions:\", interactions.size);\n    }\n\n    if (emit(params)) {\n      sent = true;\n    }\n  }\n\n  var po = new PerformanceObserver(function (list) {\n    list.getEntries().forEach(record);\n  });\n  // 16 ms is the lowest durationThreshold the spec allows; buffered picks up\n  // interactions from before this script ran.\n  po.observe({ type: \"event\", buffered: true, durationThreshold: 16 });\n  po.observe({ type: \"first-input\", buffered: true });\n\n  [\"pointerdown\", \"keydown\", \"click\"].forEach(function (t) {\n    window.addEventListener(t, noteTarget, { capture: true, passive: true });\n  });\n\n  // visibilitychange is the reliable one — mobile Safari often never fires\n  // pagehide. pagehide is the backstop. Neither fires on a killed tab.\n  document.addEventListener(\n    \"visibilitychange\",\n    function () {\n      if (document.visibilityState === \"hidden\") {\n        send();\n      }\n    },\n    true\n  );\n  window.addEventListener(\"pagehide\", send, true);\n})();\n"],"mappings":"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","ignoreList":[]}